userver: userver/crypto/signers.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
signers.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/crypto/signers.hpp
4/// @brief Digital signature generators
5/// @ingroup userver_universal
6
7#include <initializer_list>
8#include <memory>
9#include <string>
10#include <string_view>
11
12#include <userver/utils/flags.hpp>
13
14#include <userver/crypto/basic_types.hpp>
15#include <userver/crypto/certificate.hpp>
16#include <userver/crypto/exception.hpp>
17#include <userver/crypto/private_key.hpp>
18
19USERVER_NAMESPACE_BEGIN
20
21namespace crypto {
22
23/// Base signer class
24class Signer : public NamedAlgo {
25 public:
26 explicit Signer(const std::string& name);
27 ~Signer() override;
28
29 /// Signs a raw message, returning the signature
30 virtual std::string Sign(
31 std::initializer_list<std::string_view> data) const = 0;
32};
33
34/// "none" algorithm signer
35class SignerNone final : public Signer {
36 public:
37 SignerNone();
38
39 /// Signs a raw message, returning the signature
40 std::string Sign(std::initializer_list<std::string_view> data) const override;
41};
42
43/// HMAC-SHA signer
44template <DigestSize bits>
45class HmacShaSigner final : public Signer {
46 public:
47 /// Constructor from a shared secret
48 explicit HmacShaSigner(std::string secret);
49 ~HmacShaSigner() override;
50
51 /// Signs a raw message, returning the signature
52 std::string Sign(std::initializer_list<std::string_view> data) const override;
53
54 private:
55 std::string secret_;
56};
57
58/// @name Outputs HMAC SHA MAC.
59/// @{
60using SignerHs1 = HmacShaSigner<DigestSize::k160>;
61using SignerHs256 = HmacShaSigner<DigestSize::k256>;
62using SignerHs384 = HmacShaSigner<DigestSize::k384>;
63using SignerHs512 = HmacShaSigner<DigestSize::k512>;
64/// @}
65
66/// Generic signer for asymmetric cryptography
67template <DsaType type, DigestSize bits>
68class DsaSigner final : public Signer {
69 public:
70 /// Constructor from a PEM-encoded private key and an optional passphrase
71 explicit DsaSigner(const std::string& privkey,
72 const std::string& password = {});
73
74 /// Signs a raw message, returning the signature
75 std::string Sign(std::initializer_list<std::string_view> data) const override;
76
77 /// Signs a message digest, returning the signature.
78 ///
79 /// Not available for RSASSA-PSS.
80 std::string SignDigest(std::string_view digest) const;
81
82 private:
83 PrivateKey pkey_;
84};
85
86/// @name Outputs RSASSA signature using SHA-2 and PKCS1 padding.
87/// @{
88using SignerRs256 = DsaSigner<DsaType::kRsa, DigestSize::k256>;
89using SignerRs384 = DsaSigner<DsaType::kRsa, DigestSize::k384>;
90using SignerRs512 = DsaSigner<DsaType::kRsa, DigestSize::k512>;
91/// @}
92
93/// @name Outputs ECDSA as per RFC7518.
94///
95/// OpenSSL generates ECDSA signatures in ASN.1/DER format, RFC7518 specifies
96/// signature as a concatenation of zero-padded big-endian `(R, S)` values.
97/// @{
98using SignerEs256 = DsaSigner<DsaType::kEc, DigestSize::k256>;
99using SignerEs384 = DsaSigner<DsaType::kEc, DigestSize::k384>;
100using SignerEs512 = DsaSigner<DsaType::kEc, DigestSize::k512>;
101/// @}
102
103/// @name Outputs RSASSA signature using SHA-2 and PSS padding as per RFC7518.
104///
105/// JWA specifications require using MGF1 function with the same hash function
106/// as for the digest and salt length to be the same size as the hash output.
107/// @{
108using SignerPs256 = DsaSigner<DsaType::kRsaPss, DigestSize::k256>;
109using SignerPs384 = DsaSigner<DsaType::kRsaPss, DigestSize::k384>;
110using SignerPs512 = DsaSigner<DsaType::kRsaPss, DigestSize::k512>;
111/// @}
112
113/// @name CMS signer per RFC 5652
114class CmsSigner final : public NamedAlgo {
115 public:
116 /// Signer flags
117 enum class Flags {
118 kNone = 0x0,
119 /// If set MIME headers for type text/plain are prepended to the data.
120 kText = 0x1,
121 /// If set the signer's certificate will not be included in the
122 /// resulting CMS structure. This can reduce the size of
123 /// the signature if the signers certificate can be obtained by other means:
124 /// for example a previously signed message.
125 kNoCerts = 0x2,
126 /// If set data being signed is omitted from the resulting CMS structure.
127 kDetached = 0x40,
128 /// Normally the supplied content is translated into MIME canonical format
129 /// (as required by the S/MIME specifications).
130 /// If set no translation occurs.
131 kBinary = 0x80
132 };
133
134 /// Output encoding
135 enum class OutForm { kDer, kPem, kSMime };
136
137 /// Construct from certificate and private key
138 CmsSigner(Certificate certificate, PrivateKey pkey);
139
140 ~CmsSigner() override;
141
142 /// Signs a raw message, returning as specified by flags
143 std::string Sign(std::initializer_list<std::string_view> data,
144 utils::Flags<Flags> flags, OutForm out_form) const;
145
146 private:
147 Certificate cert_;
148 PrivateKey pkey_;
149};
150
151namespace weak {
152
153/// Outputs RSASSA signature using SHA-1 and PKCS1 padding.
154using SignerRs1 = DsaSigner<DsaType::kRsa, DigestSize::k160>;
155
156/// Outputs RSASSA signature using SHA-2 and PSS padding.
157///
158/// JWA specifications require using MGF1 function with the same hash function
159/// as for the digest and salt length to be the same size as the hash output.
160using SignerPs1 = DsaSigner<DsaType::kRsaPss, DigestSize::k160>;
161
162} // namespace weak
163} // namespace crypto
164
165USERVER_NAMESPACE_END