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 {
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