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