/src/cryptopp/xed25519.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // xed25519.cpp - written and placed in public domain by Jeffrey Walton |
2 | | // Crypto++ specific implementation wrapped around Andrew |
3 | | // Moon's public domain curve25519-donna and ed25519-donna, |
4 | | // https://github.com/floodyberry/curve25519-donna and |
5 | | // https://github.com/floodyberry/ed25519-donna. |
6 | | |
7 | | #include "pch.h" |
8 | | |
9 | | #include "cryptlib.h" |
10 | | #include "asn.h" |
11 | | #include "integer.h" |
12 | | #include "filters.h" |
13 | | #include "stdcpp.h" |
14 | | |
15 | | #include "xed25519.h" |
16 | | #include "donna.h" |
17 | | |
18 | | ANONYMOUS_NAMESPACE_BEGIN |
19 | | |
20 | | using CryptoPP::byte; |
21 | | |
22 | | CRYPTOPP_ALIGN_DATA(16) |
23 | | const byte blacklist[][32] = { |
24 | | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
25 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
26 | | { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
27 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
28 | | { 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, |
29 | | 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 }, |
30 | | { 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, |
31 | | 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 }, |
32 | | { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
33 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, |
34 | | { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
35 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, |
36 | | { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
37 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, |
38 | | { 0xcd, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, |
39 | | 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x80 }, |
40 | | { 0x4c, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, |
41 | | 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0xd7 }, |
42 | | { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
43 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, |
44 | | { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
45 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, |
46 | | { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
47 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } |
48 | | }; |
49 | | |
50 | | bool HasSmallOrder(const byte y[32]) |
51 | 0 | { |
52 | | // The magic 12 is the count of blaklisted points |
53 | 0 | byte c[12] = { 0 }; |
54 | 0 | for (size_t j = 0; j < 32; j++) { |
55 | 0 | for (size_t i = 0; i < COUNTOF(blacklist); i++) { |
56 | 0 | c[i] |= y[j] ^ blacklist[i][j]; |
57 | 0 | } |
58 | 0 | } |
59 | |
|
60 | 0 | unsigned int k = 0; |
61 | 0 | for (size_t i = 0; i < COUNTOF(blacklist); i++) { |
62 | 0 | k |= (c[i] - 1); |
63 | 0 | } |
64 | |
|
65 | 0 | return (bool)((k >> 8) & 1); |
66 | 0 | } |
67 | | |
68 | | ANONYMOUS_NAMESPACE_END |
69 | | |
70 | | NAMESPACE_BEGIN(CryptoPP) |
71 | | |
72 | | // ******************** x25519 Agreement ************************* // |
73 | | |
74 | | x25519::x25519(const byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) |
75 | 0 | { |
76 | 0 | std::memcpy(m_pk, y, PUBLIC_KEYLENGTH); |
77 | 0 | std::memcpy(m_sk, x, SECRET_KEYLENGTH); |
78 | |
|
79 | 0 | CRYPTOPP_ASSERT(IsClamped(m_sk) == true); |
80 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
81 | 0 | } Unexecuted instantiation: CryptoPP::x25519::x25519(unsigned char const*, unsigned char const*) Unexecuted instantiation: CryptoPP::x25519::x25519(unsigned char const*, unsigned char const*) |
82 | | |
83 | | x25519::x25519(const byte x[SECRET_KEYLENGTH]) |
84 | 0 | { |
85 | 0 | std::memcpy(m_sk, x, SECRET_KEYLENGTH); |
86 | 0 | Donna::curve25519_mult(m_pk, m_sk); |
87 | |
|
88 | 0 | CRYPTOPP_ASSERT(IsClamped(m_sk) == true); |
89 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
90 | 0 | } Unexecuted instantiation: CryptoPP::x25519::x25519(unsigned char const*) Unexecuted instantiation: CryptoPP::x25519::x25519(unsigned char const*) |
91 | | |
92 | | x25519::x25519(const Integer &y, const Integer &x) |
93 | 0 | { |
94 | 0 | CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH); |
95 | 0 | CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); |
96 | |
|
97 | 0 | y.Encode(m_pk, PUBLIC_KEYLENGTH); std::reverse(m_pk+0, m_pk+PUBLIC_KEYLENGTH); |
98 | 0 | x.Encode(m_sk, SECRET_KEYLENGTH); std::reverse(m_sk+0, m_sk+SECRET_KEYLENGTH); |
99 | |
|
100 | 0 | CRYPTOPP_ASSERT(IsClamped(m_sk) == true); |
101 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
102 | 0 | } Unexecuted instantiation: CryptoPP::x25519::x25519(CryptoPP::Integer const&, CryptoPP::Integer const&) Unexecuted instantiation: CryptoPP::x25519::x25519(CryptoPP::Integer const&, CryptoPP::Integer const&) |
103 | | |
104 | | x25519::x25519(const Integer &x) |
105 | 0 | { |
106 | 0 | CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); |
107 | |
|
108 | 0 | x.Encode(m_sk, SECRET_KEYLENGTH); |
109 | 0 | std::reverse(m_sk+0, m_sk+SECRET_KEYLENGTH); |
110 | 0 | Donna::curve25519_mult(m_pk, m_sk); |
111 | |
|
112 | 0 | CRYPTOPP_ASSERT(IsClamped(m_sk) == true); |
113 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
114 | 0 | } Unexecuted instantiation: CryptoPP::x25519::x25519(CryptoPP::Integer const&) Unexecuted instantiation: CryptoPP::x25519::x25519(CryptoPP::Integer const&) |
115 | | |
116 | | x25519::x25519(RandomNumberGenerator &rng) |
117 | 0 | { |
118 | 0 | rng.GenerateBlock(m_sk, SECRET_KEYLENGTH); |
119 | 0 | ClampKey(m_sk); |
120 | 0 | SecretToPublicKey(m_pk, m_sk); |
121 | 0 | } Unexecuted instantiation: CryptoPP::x25519::x25519(CryptoPP::RandomNumberGenerator&) Unexecuted instantiation: CryptoPP::x25519::x25519(CryptoPP::RandomNumberGenerator&) |
122 | | |
123 | | x25519::x25519(BufferedTransformation ¶ms) |
124 | 0 | { |
125 | 0 | Load(params); |
126 | 0 | } Unexecuted instantiation: CryptoPP::x25519::x25519(CryptoPP::BufferedTransformation&) Unexecuted instantiation: CryptoPP::x25519::x25519(CryptoPP::BufferedTransformation&) |
127 | | |
128 | | void x25519::ClampKey(byte x[SECRET_KEYLENGTH]) const |
129 | 0 | { |
130 | 0 | x[0] &= 248; x[31] &= 127; x[31] |= 64; |
131 | 0 | } |
132 | | |
133 | | bool x25519::IsClamped(const byte x[SECRET_KEYLENGTH]) const |
134 | 0 | { |
135 | 0 | return (x[0] & 248) == x[0] && (x[31] & 127) == x[31] && (x[31] | 64) == x[31]; |
136 | 0 | } |
137 | | |
138 | | bool x25519::IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const |
139 | 0 | { |
140 | 0 | return HasSmallOrder(y); |
141 | 0 | } |
142 | | |
143 | | void x25519::SecretToPublicKey(byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) const |
144 | 28 | { |
145 | 28 | Donna::curve25519_mult(y, x); |
146 | 28 | } |
147 | | |
148 | | void x25519::BERDecodeAndCheckAlgorithmID(BufferedTransformation &bt) |
149 | 0 | { |
150 | | // We have not yet determined the OID to use for this object. |
151 | | // We can't use OID's decoder because it throws BERDecodeError |
152 | | // if the OIDs do not match. |
153 | 0 | OID oid(bt); |
154 | | |
155 | | // 1.3.6.1.4.1.3029.1.5.1/curvey25519 from Cryptlib used by OpenPGP. |
156 | | // https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-rfc4880bis |
157 | 0 | if (!m_oid.Empty() && m_oid != oid) |
158 | 0 | BERDecodeError(); // Only accept user specified OID |
159 | 0 | else if (oid == ASN1::curve25519() || oid == ASN1::X25519() || |
160 | 0 | oid == OID(1)+3+6+1+4+1+3029+1+5) |
161 | 0 | m_oid = oid; // Accept any of the x25519 OIDs |
162 | 0 | else |
163 | 0 | BERDecodeError(); |
164 | 0 | } |
165 | | |
166 | | void x25519::BERDecode(BufferedTransformation &bt) |
167 | 0 | { |
168 | | // https://tools.ietf.org/html/rfc8410, section 7 and |
169 | | // https://www.cryptopp.com/wiki/curve25519_keys |
170 | 0 | BERSequenceDecoder privateKeyInfo(bt); |
171 | 0 | word32 version; |
172 | 0 | BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 1); // check version |
173 | |
|
174 | 0 | BERSequenceDecoder algorithm(privateKeyInfo); |
175 | | // GetAlgorithmID().BERDecodeAndCheck(algorithm); |
176 | 0 | BERDecodeAndCheckAlgorithmID(algorithm); |
177 | 0 | algorithm.MessageEnd(); |
178 | |
|
179 | 0 | BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); |
180 | 0 | BERDecodePrivateKey(octetString, false, (size_t)privateKeyInfo.RemainingLength()); |
181 | 0 | octetString.MessageEnd(); |
182 | | |
183 | | // publicKey [1] IMPLICIT PublicKey OPTIONAL |
184 | 0 | bool generatePublicKey = true; |
185 | 0 | if (privateKeyInfo.EndReached() == false /*version == 1?*/) |
186 | 0 | { |
187 | | // Should we test this before decoding? In either case we |
188 | | // just throw a BERDecodeErr() when we can't parse it. |
189 | 0 | BERGeneralDecoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1); |
190 | 0 | SecByteBlock subjectPublicKey; |
191 | 0 | unsigned int unusedBits; |
192 | 0 | BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); |
193 | 0 | CRYPTOPP_ASSERT(unusedBits == 0); |
194 | 0 | CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH); |
195 | 0 | if (subjectPublicKey.size() != PUBLIC_KEYLENGTH) |
196 | 0 | BERDecodeError(); |
197 | 0 | std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH); |
198 | 0 | generatePublicKey = false; |
199 | 0 | publicKey.MessageEnd(); |
200 | 0 | } |
201 | |
|
202 | 0 | privateKeyInfo.MessageEnd(); |
203 | |
|
204 | 0 | if (generatePublicKey) |
205 | 0 | Donna::curve25519_mult(m_pk, m_sk); |
206 | |
|
207 | 0 | CRYPTOPP_ASSERT(IsClamped(m_sk) == true); |
208 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
209 | 0 | } |
210 | | |
211 | | void x25519::DEREncode(BufferedTransformation &bt, int version) const |
212 | 0 | { |
213 | | // https://tools.ietf.org/html/rfc8410, section 7 and |
214 | | // https://www.cryptopp.com/wiki/curve25519_keys |
215 | 0 | CRYPTOPP_ASSERT(version == 0 || version == 1); |
216 | |
|
217 | 0 | DERSequenceEncoder privateKeyInfo(bt); |
218 | 0 | DEREncodeUnsigned<word32>(privateKeyInfo, version); |
219 | |
|
220 | 0 | DERSequenceEncoder algorithm(privateKeyInfo); |
221 | 0 | GetAlgorithmID().DEREncode(algorithm); |
222 | 0 | algorithm.MessageEnd(); |
223 | |
|
224 | 0 | DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); |
225 | 0 | DEREncodePrivateKey(octetString); |
226 | 0 | octetString.MessageEnd(); |
227 | |
|
228 | 0 | if (version == 1) |
229 | 0 | { |
230 | 0 | DERGeneralEncoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1); |
231 | 0 | DEREncodeBitString(publicKey, m_pk, PUBLIC_KEYLENGTH); |
232 | 0 | publicKey.MessageEnd(); |
233 | 0 | } |
234 | |
|
235 | 0 | privateKeyInfo.MessageEnd(); |
236 | 0 | } |
237 | | |
238 | | void x25519::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/) |
239 | 0 | { |
240 | | // https://tools.ietf.org/html/rfc8410 and |
241 | | // https://www.cryptopp.com/wiki/curve25519_keys |
242 | |
|
243 | 0 | BERGeneralDecoder privateKey(bt, OCTET_STRING); |
244 | |
|
245 | 0 | if (!privateKey.IsDefiniteLength()) |
246 | 0 | BERDecodeError(); |
247 | |
|
248 | 0 | size_t size = privateKey.Get(m_sk, SECRET_KEYLENGTH); |
249 | 0 | if (size != SECRET_KEYLENGTH) |
250 | 0 | BERDecodeError(); |
251 | | |
252 | | // We don't know how to decode them |
253 | 0 | if (parametersPresent) |
254 | 0 | BERDecodeError(); |
255 | |
|
256 | 0 | privateKey.MessageEnd(); |
257 | 0 | } |
258 | | |
259 | | void x25519::DEREncodePrivateKey(BufferedTransformation &bt) const |
260 | 0 | { |
261 | | // https://tools.ietf.org/html/rfc8410 |
262 | 0 | DERGeneralEncoder privateKey(bt, OCTET_STRING); |
263 | 0 | privateKey.Put(m_sk, SECRET_KEYLENGTH); |
264 | 0 | privateKey.MessageEnd(); |
265 | 0 | } |
266 | | |
267 | | bool x25519::Validate(RandomNumberGenerator &rng, unsigned int level) const |
268 | 0 | { |
269 | 0 | CRYPTOPP_UNUSED(rng); |
270 | 0 | CRYPTOPP_ASSERT(IsClamped(m_sk) == true); |
271 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
272 | |
|
273 | 0 | if (level >= 1 && IsClamped(m_sk) == false) |
274 | 0 | return false; |
275 | 0 | if (level >= 2 && IsSmallOrder(m_pk) == true) |
276 | 0 | return false; |
277 | 0 | if (level >= 3) |
278 | 0 | { |
279 | | // Verify m_pk is pairwise consistent with m_sk |
280 | 0 | SecByteBlock pk(PUBLIC_KEYLENGTH); |
281 | 0 | SecretToPublicKey(pk, m_sk); |
282 | |
|
283 | 0 | if (VerifyBufsEqual(pk, m_pk, PUBLIC_KEYLENGTH) == false) |
284 | 0 | return false; |
285 | 0 | } |
286 | | |
287 | 0 | return true; |
288 | 0 | } |
289 | | |
290 | | bool x25519::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const |
291 | 0 | { |
292 | 0 | if (std::strcmp(name, Name::PrivateExponent()) == 0 || std::strcmp(name, "SecretKey") == 0) |
293 | 0 | { |
294 | 0 | this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); |
295 | 0 | reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_sk, SECRET_KEYLENGTH, false); |
296 | 0 | return true; |
297 | 0 | } |
298 | | |
299 | 0 | if (std::strcmp(name, Name::PublicElement()) == 0) |
300 | 0 | { |
301 | 0 | this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); |
302 | 0 | reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false); |
303 | 0 | return true; |
304 | 0 | } |
305 | | |
306 | 0 | if (std::strcmp(name, Name::GroupOID()) == 0) |
307 | 0 | { |
308 | 0 | if (m_oid.Empty()) |
309 | 0 | return false; |
310 | | |
311 | 0 | this->ThrowIfTypeMismatch(name, typeid(OID), valueType); |
312 | 0 | *reinterpret_cast<OID *>(pValue) = m_oid; |
313 | 0 | return true; |
314 | 0 | } |
315 | | |
316 | 0 | return false; |
317 | 0 | } |
318 | | |
319 | | void x25519::AssignFrom(const NameValuePairs &source) |
320 | 0 | { |
321 | 0 | ConstByteArrayParameter val; |
322 | 0 | if (source.GetValue(Name::PrivateExponent(), val) || source.GetValue("SecretKey", val)) |
323 | 0 | { |
324 | 0 | std::memcpy(m_sk, val.begin(), SECRET_KEYLENGTH); |
325 | 0 | } |
326 | |
|
327 | 0 | if (source.GetValue(Name::PublicElement(), val)) |
328 | 0 | { |
329 | 0 | std::memcpy(m_pk, val.begin(), PUBLIC_KEYLENGTH); |
330 | 0 | } |
331 | |
|
332 | 0 | OID oid; |
333 | 0 | if (source.GetValue(Name::GroupOID(), oid)) |
334 | 0 | { |
335 | 0 | m_oid = oid; |
336 | 0 | } |
337 | |
|
338 | 0 | bool derive = false; |
339 | 0 | if (source.GetValue("DerivePublicKey", derive) && derive == true) |
340 | 0 | SecretToPublicKey(m_pk, m_sk); |
341 | 0 | } |
342 | | |
343 | | void x25519::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) |
344 | 0 | { |
345 | 0 | ConstByteArrayParameter seed; |
346 | 0 | if (params.GetValue(Name::Seed(), seed) && rng.CanIncorporateEntropy()) |
347 | 0 | rng.IncorporateEntropy(seed.begin(), seed.size()); |
348 | |
|
349 | 0 | rng.GenerateBlock(m_sk, SECRET_KEYLENGTH); |
350 | 0 | ClampKey(m_sk); |
351 | 0 | SecretToPublicKey(m_pk, m_sk); |
352 | 0 | } |
353 | | |
354 | | void x25519::GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const |
355 | 0 | { |
356 | 0 | rng.GenerateBlock(privateKey, SECRET_KEYLENGTH); |
357 | 0 | ClampKey(privateKey); |
358 | 0 | } |
359 | | |
360 | | void x25519::GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const |
361 | 28 | { |
362 | 28 | CRYPTOPP_UNUSED(rng); |
363 | 28 | SecretToPublicKey(publicKey, privateKey); |
364 | 28 | } |
365 | | |
366 | | bool x25519::Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey) const |
367 | 0 | { |
368 | 0 | CRYPTOPP_ASSERT(agreedValue != NULLPTR); |
369 | 0 | CRYPTOPP_ASSERT(otherPublicKey != NULLPTR); |
370 | |
|
371 | 0 | if (validateOtherPublicKey && IsSmallOrder(otherPublicKey)) |
372 | 0 | return false; |
373 | | |
374 | 0 | return Donna::curve25519_mult(agreedValue, privateKey, otherPublicKey) == 0; |
375 | 0 | } |
376 | | |
377 | | // ******************** ed25519 Signer ************************* // |
378 | | |
379 | | void ed25519PrivateKey::SecretToPublicKey(byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) const |
380 | 0 | { |
381 | 0 | int ret = Donna::ed25519_publickey(y, x); |
382 | 0 | CRYPTOPP_ASSERT(ret == 0); CRYPTOPP_UNUSED(ret); |
383 | 0 | } |
384 | | |
385 | | bool ed25519PrivateKey::IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const |
386 | 0 | { |
387 | 0 | return HasSmallOrder(y); |
388 | 0 | } |
389 | | |
390 | | bool ed25519PrivateKey::Validate(RandomNumberGenerator &rng, unsigned int level) const |
391 | 0 | { |
392 | 0 | CRYPTOPP_UNUSED(rng); |
393 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
394 | |
|
395 | 0 | if (level >= 1 && IsSmallOrder(m_pk) == true) |
396 | 0 | return false; |
397 | 0 | if (level >= 3) |
398 | 0 | { |
399 | | // Verify m_pk is pairwise consistent with m_sk |
400 | 0 | SecByteBlock pk(PUBLIC_KEYLENGTH); |
401 | 0 | SecretToPublicKey(pk, m_sk); |
402 | |
|
403 | 0 | if (VerifyBufsEqual(pk, m_pk, PUBLIC_KEYLENGTH) == false) |
404 | 0 | return false; |
405 | 0 | } |
406 | | |
407 | 0 | return true; |
408 | 0 | } |
409 | | |
410 | | bool ed25519PrivateKey::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const |
411 | 0 | { |
412 | 0 | if (std::strcmp(name, Name::PrivateExponent()) == 0 || std::strcmp(name, "SecretKey") == 0) |
413 | 0 | { |
414 | 0 | this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); |
415 | 0 | reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_sk, SECRET_KEYLENGTH, false); |
416 | 0 | return true; |
417 | 0 | } |
418 | | |
419 | 0 | if (std::strcmp(name, Name::PublicElement()) == 0) |
420 | 0 | { |
421 | 0 | this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); |
422 | 0 | reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false); |
423 | 0 | return true; |
424 | 0 | } |
425 | | |
426 | 0 | if (std::strcmp(name, Name::GroupOID()) == 0) |
427 | 0 | { |
428 | 0 | if (m_oid.Empty()) |
429 | 0 | return false; |
430 | | |
431 | 0 | this->ThrowIfTypeMismatch(name, typeid(OID), valueType); |
432 | 0 | *reinterpret_cast<OID *>(pValue) = m_oid; |
433 | 0 | return true; |
434 | 0 | } |
435 | | |
436 | 0 | return false; |
437 | 0 | } |
438 | | |
439 | | void ed25519PrivateKey::AssignFrom(const NameValuePairs &source) |
440 | 0 | { |
441 | 0 | ConstByteArrayParameter val; |
442 | 0 | if (source.GetValue(Name::PrivateExponent(), val) || source.GetValue("SecretKey", val)) |
443 | 0 | { |
444 | 0 | CRYPTOPP_ASSERT(val.size() == SECRET_KEYLENGTH); |
445 | 0 | std::memcpy(m_sk, val.begin(), SECRET_KEYLENGTH); |
446 | 0 | } |
447 | 0 | if (source.GetValue(Name::PublicElement(), val)) |
448 | 0 | { |
449 | 0 | CRYPTOPP_ASSERT(val.size() == PUBLIC_KEYLENGTH); |
450 | 0 | std::memcpy(m_pk, val.begin(), PUBLIC_KEYLENGTH); |
451 | 0 | } |
452 | |
|
453 | 0 | OID oid; |
454 | 0 | if (source.GetValue(Name::GroupOID(), oid)) |
455 | 0 | { |
456 | 0 | m_oid = oid; |
457 | 0 | } |
458 | |
|
459 | 0 | bool derive = false; |
460 | 0 | if (source.GetValue("DerivePublicKey", derive) && derive == true) |
461 | 0 | SecretToPublicKey(m_pk, m_sk); |
462 | |
|
463 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
464 | 0 | } |
465 | | |
466 | | void ed25519PrivateKey::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms=g_nullNameValuePairs) |
467 | 0 | { |
468 | 0 | ConstByteArrayParameter seed; |
469 | 0 | if (params.GetValue(Name::Seed(), seed) && rng.CanIncorporateEntropy()) |
470 | 0 | rng.IncorporateEntropy(seed.begin(), seed.size()); |
471 | |
|
472 | 0 | rng.GenerateBlock(m_sk, SECRET_KEYLENGTH); |
473 | 0 | int ret = Donna::ed25519_publickey(m_pk, m_sk); |
474 | 0 | CRYPTOPP_ASSERT(ret == 0); CRYPTOPP_UNUSED(ret); |
475 | 0 | } |
476 | | |
477 | | void ed25519PrivateKey::MakePublicKey (PublicKey &pub) const |
478 | 0 | { |
479 | 0 | pub.AssignFrom(MakeParameters |
480 | 0 | (Name::PublicElement(), ConstByteArrayParameter(m_pk.begin(), PUBLIC_KEYLENGTH)) |
481 | 0 | (Name::GroupOID(), GetAlgorithmID())); |
482 | 0 | } |
483 | | |
484 | | void ed25519PrivateKey::BERDecodeAndCheckAlgorithmID(BufferedTransformation &bt) |
485 | 0 | { |
486 | | // We have not yet determined the OID to use for this object. |
487 | | // We can't use OID's decoder because it throws BERDecodeError |
488 | | // if the OIDs do not match. |
489 | 0 | OID oid(bt); |
490 | |
|
491 | 0 | if (!m_oid.Empty() && m_oid != oid) |
492 | 0 | BERDecodeError(); // Only accept user specified OID |
493 | 0 | else if (oid == ASN1::curve25519() || oid == ASN1::Ed25519()) |
494 | 0 | m_oid = oid; // Accept any of the ed25519PrivateKey OIDs |
495 | 0 | else |
496 | 0 | BERDecodeError(); |
497 | 0 | } |
498 | | |
499 | | void ed25519PrivateKey::BERDecode(BufferedTransformation &bt) |
500 | 0 | { |
501 | | // https://tools.ietf.org/html/rfc8410, section 7 and |
502 | | // https://www.cryptopp.com/wiki/curve25519_keys |
503 | 0 | BERSequenceDecoder privateKeyInfo(bt); |
504 | 0 | word32 version; |
505 | 0 | BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 1); // check version |
506 | |
|
507 | 0 | BERSequenceDecoder algorithm(privateKeyInfo); |
508 | | // GetAlgorithmID().BERDecodeAndCheck(algorithm); |
509 | 0 | BERDecodeAndCheckAlgorithmID(algorithm); |
510 | 0 | algorithm.MessageEnd(); |
511 | |
|
512 | 0 | BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); |
513 | 0 | BERDecodePrivateKey(octetString, false, (size_t)privateKeyInfo.RemainingLength()); |
514 | 0 | octetString.MessageEnd(); |
515 | | |
516 | | // publicKey [1] IMPLICIT PublicKey OPTIONAL |
517 | 0 | bool generatePublicKey = true; |
518 | 0 | if (privateKeyInfo.EndReached() == false /*version == 1?*/) |
519 | 0 | { |
520 | | // Should we test this before decoding? In either case we |
521 | | // just throw a BERDecodeErr() when we can't parse it. |
522 | 0 | BERGeneralDecoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1); |
523 | 0 | SecByteBlock subjectPublicKey; |
524 | 0 | unsigned int unusedBits; |
525 | 0 | BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); |
526 | 0 | CRYPTOPP_ASSERT(unusedBits == 0); |
527 | 0 | CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH); |
528 | 0 | if (subjectPublicKey.size() != PUBLIC_KEYLENGTH) |
529 | 0 | BERDecodeError(); |
530 | 0 | std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH); |
531 | 0 | generatePublicKey = false; |
532 | 0 | publicKey.MessageEnd(); |
533 | 0 | } |
534 | |
|
535 | 0 | privateKeyInfo.MessageEnd(); |
536 | |
|
537 | 0 | if (generatePublicKey) |
538 | 0 | Donna::ed25519_publickey(m_pk, m_sk); |
539 | |
|
540 | 0 | CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false); |
541 | 0 | } |
542 | | |
543 | | void ed25519PrivateKey::DEREncode(BufferedTransformation &bt, int version) const |
544 | 0 | { |
545 | | // https://tools.ietf.org/html/rfc8410, section 7 and |
546 | | // https://www.cryptopp.com/wiki/curve25519_keys |
547 | 0 | CRYPTOPP_ASSERT(version == 0 || version == 1); |
548 | |
|
549 | 0 | DERSequenceEncoder privateKeyInfo(bt); |
550 | 0 | DEREncodeUnsigned<word32>(privateKeyInfo, version); |
551 | |
|
552 | 0 | DERSequenceEncoder algorithm(privateKeyInfo); |
553 | 0 | GetAlgorithmID().DEREncode(algorithm); |
554 | 0 | algorithm.MessageEnd(); |
555 | |
|
556 | 0 | DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); |
557 | 0 | DEREncodePrivateKey(octetString); |
558 | 0 | octetString.MessageEnd(); |
559 | |
|
560 | 0 | if (version == 1) |
561 | 0 | { |
562 | 0 | DERGeneralEncoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1); |
563 | 0 | DEREncodeBitString(publicKey, m_pk, PUBLIC_KEYLENGTH); |
564 | 0 | publicKey.MessageEnd(); |
565 | 0 | } |
566 | |
|
567 | 0 | privateKeyInfo.MessageEnd(); |
568 | 0 | } |
569 | | |
570 | | void ed25519PrivateKey::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/) |
571 | 0 | { |
572 | | // https://tools.ietf.org/html/rfc8410 and |
573 | | // https://www.cryptopp.com/wiki/curve25519_keys |
574 | |
|
575 | 0 | BERGeneralDecoder privateKey(bt, OCTET_STRING); |
576 | |
|
577 | 0 | if (!privateKey.IsDefiniteLength()) |
578 | 0 | BERDecodeError(); |
579 | |
|
580 | 0 | size_t size = privateKey.Get(m_sk, SECRET_KEYLENGTH); |
581 | 0 | if (size != SECRET_KEYLENGTH) |
582 | 0 | BERDecodeError(); |
583 | | |
584 | | // We don't know how to decode them |
585 | 0 | if (parametersPresent) |
586 | 0 | BERDecodeError(); |
587 | |
|
588 | 0 | privateKey.MessageEnd(); |
589 | 0 | } |
590 | | |
591 | | void ed25519PrivateKey::DEREncodePrivateKey(BufferedTransformation &bt) const |
592 | 0 | { |
593 | | // https://tools.ietf.org/html/rfc8410 |
594 | 0 | DERGeneralEncoder privateKey(bt, OCTET_STRING); |
595 | 0 | privateKey.Put(m_sk, SECRET_KEYLENGTH); |
596 | 0 | privateKey.MessageEnd(); |
597 | 0 | } |
598 | | |
599 | | void ed25519PrivateKey::SetPrivateExponent (const byte x[SECRET_KEYLENGTH]) |
600 | 0 | { |
601 | 0 | AssignFrom(MakeParameters |
602 | 0 | (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH)) |
603 | 0 | ("DerivePublicKey", true)); |
604 | 0 | } |
605 | | |
606 | | void ed25519PrivateKey::SetPrivateExponent (const Integer &x) |
607 | 0 | { |
608 | 0 | CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); |
609 | |
|
610 | 0 | SecByteBlock bx(SECRET_KEYLENGTH); |
611 | 0 | x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH); |
612 | |
|
613 | 0 | AssignFrom(MakeParameters |
614 | 0 | (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false)) |
615 | 0 | ("DerivePublicKey", true)); |
616 | 0 | } |
617 | | |
618 | | const Integer& ed25519PrivateKey::GetPrivateExponent() const |
619 | 0 | { |
620 | 0 | m_x = Integer(m_sk, SECRET_KEYLENGTH, Integer::UNSIGNED, LITTLE_ENDIAN_ORDER); |
621 | 0 | return m_x; |
622 | 0 | } |
623 | | |
624 | | //////////////////////// |
625 | | |
626 | | ed25519Signer::ed25519Signer(const byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) |
627 | 0 | { |
628 | 0 | AccessPrivateKey().AssignFrom(MakeParameters |
629 | 0 | (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH, false)) |
630 | 0 | (Name::PublicElement(), ConstByteArrayParameter(y, PUBLIC_KEYLENGTH, false))); |
631 | 0 | } |
632 | | |
633 | | ed25519Signer::ed25519Signer(const byte x[SECRET_KEYLENGTH]) |
634 | 0 | { |
635 | 0 | AccessPrivateKey().AssignFrom(MakeParameters |
636 | 0 | (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH, false)) |
637 | 0 | ("DerivePublicKey", true)); |
638 | 0 | } |
639 | | |
640 | | ed25519Signer::ed25519Signer(const Integer &y, const Integer &x) |
641 | 0 | { |
642 | 0 | CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH); |
643 | 0 | CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); |
644 | |
|
645 | 0 | SecByteBlock by(PUBLIC_KEYLENGTH), bx(SECRET_KEYLENGTH); |
646 | 0 | y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH); |
647 | 0 | x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH); |
648 | |
|
649 | 0 | AccessPrivateKey().AssignFrom(MakeParameters |
650 | 0 | (Name::PublicElement(), ConstByteArrayParameter(by, PUBLIC_KEYLENGTH, false)) |
651 | 0 | (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false))); |
652 | 0 | } |
653 | | |
654 | | ed25519Signer::ed25519Signer(const Integer &x) |
655 | 0 | { |
656 | 0 | CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH); |
657 | |
|
658 | 0 | SecByteBlock bx(SECRET_KEYLENGTH); |
659 | 0 | x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH); |
660 | |
|
661 | 0 | AccessPrivateKey().AssignFrom(MakeParameters |
662 | 0 | (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false)) |
663 | 0 | ("DerivePublicKey", true)); |
664 | 0 | } |
665 | | |
666 | | ed25519Signer::ed25519Signer(const PKCS8PrivateKey &key) |
667 | 0 | { |
668 | | // Load all fields from the other key |
669 | 0 | ByteQueue queue; |
670 | 0 | key.Save(queue); |
671 | 0 | AccessPrivateKey().Load(queue); |
672 | 0 | } |
673 | | |
674 | | ed25519Signer::ed25519Signer(RandomNumberGenerator &rng) |
675 | 0 | { |
676 | 0 | AccessPrivateKey().GenerateRandom(rng); |
677 | 0 | } |
678 | | |
679 | | ed25519Signer::ed25519Signer(BufferedTransformation ¶ms) |
680 | 0 | { |
681 | 0 | AccessPrivateKey().Load(params); |
682 | 0 | } |
683 | | |
684 | | size_t ed25519Signer::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const |
685 | 0 | { |
686 | 0 | CRYPTOPP_ASSERT(signature != NULLPTR); CRYPTOPP_UNUSED(rng); |
687 | |
|
688 | 0 | ed25519_MessageAccumulator& accum = dynamic_cast<ed25519_MessageAccumulator&>(messageAccumulator); |
689 | 0 | const ed25519PrivateKey& pk = dynamic_cast<const ed25519PrivateKey&>(GetPrivateKey()); |
690 | 0 | int ret = Donna::ed25519_sign(accum.data(), accum.size(), pk.GetPrivateKeyBytePtr(), pk.GetPublicKeyBytePtr(), signature); |
691 | 0 | CRYPTOPP_ASSERT(ret == 0); |
692 | |
|
693 | 0 | if (restart) |
694 | 0 | accum.Restart(); |
695 | |
|
696 | 0 | return ret == 0 ? SIGNATURE_LENGTH : 0; |
697 | 0 | } |
698 | | |
699 | | size_t ed25519Signer::SignStream (RandomNumberGenerator &rng, std::istream& stream, byte *signature) const |
700 | 0 | { |
701 | 0 | CRYPTOPP_ASSERT(signature != NULLPTR); CRYPTOPP_UNUSED(rng); |
702 | |
|
703 | 0 | const ed25519PrivateKey& pk = dynamic_cast<const ed25519PrivateKey&>(GetPrivateKey()); |
704 | 0 | int ret = Donna::ed25519_sign(stream, pk.GetPrivateKeyBytePtr(), pk.GetPublicKeyBytePtr(), signature); |
705 | 0 | CRYPTOPP_ASSERT(ret == 0); |
706 | |
|
707 | 0 | return ret == 0 ? SIGNATURE_LENGTH : 0; |
708 | 0 | } |
709 | | |
710 | | // ******************** ed25519 Verifier ************************* // |
711 | | |
712 | | bool ed25519PublicKey::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const |
713 | 0 | { |
714 | 0 | if (std::strcmp(name, Name::PublicElement()) == 0) |
715 | 0 | { |
716 | 0 | this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType); |
717 | 0 | reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false); |
718 | 0 | return true; |
719 | 0 | } |
720 | | |
721 | 0 | if (std::strcmp(name, Name::GroupOID()) == 0) |
722 | 0 | { |
723 | 0 | if (m_oid.Empty()) |
724 | 0 | return false; |
725 | | |
726 | 0 | this->ThrowIfTypeMismatch(name, typeid(OID), valueType); |
727 | 0 | *reinterpret_cast<OID *>(pValue) = m_oid; |
728 | 0 | return true; |
729 | 0 | } |
730 | | |
731 | 0 | return false; |
732 | 0 | } |
733 | | |
734 | | void ed25519PublicKey::AssignFrom(const NameValuePairs &source) |
735 | 0 | { |
736 | 0 | ConstByteArrayParameter ba; |
737 | 0 | if (source.GetValue(Name::PublicElement(), ba)) |
738 | 0 | { |
739 | 0 | std::memcpy(m_pk, ba.begin(), PUBLIC_KEYLENGTH); |
740 | 0 | } |
741 | |
|
742 | 0 | OID oid; |
743 | 0 | if (source.GetValue(Name::GroupOID(), oid)) |
744 | 0 | { |
745 | 0 | m_oid = oid; |
746 | 0 | } |
747 | 0 | } |
748 | | |
749 | | void ed25519PublicKey::BERDecodeAndCheckAlgorithmID(BufferedTransformation& bt) |
750 | 0 | { |
751 | | // We have not yet determined the OID to use for this object. |
752 | | // We can't use OID's decoder because it throws BERDecodeError |
753 | | // if the OIDs do not match. |
754 | 0 | OID oid(bt); |
755 | |
|
756 | 0 | if (!m_oid.Empty() && m_oid != oid) |
757 | 0 | BERDecodeError(); // Only accept user specified OID |
758 | 0 | else if (oid == ASN1::curve25519() || oid == ASN1::Ed25519()) |
759 | 0 | m_oid = oid; // Accept any of the ed25519PublicKey OIDs |
760 | 0 | else |
761 | 0 | BERDecodeError(); |
762 | 0 | } |
763 | | |
764 | | void ed25519PublicKey::BERDecode(BufferedTransformation &bt) |
765 | 0 | { |
766 | 0 | BERSequenceDecoder publicKeyInfo(bt); |
767 | |
|
768 | 0 | BERSequenceDecoder algorithm(publicKeyInfo); |
769 | | // GetAlgorithmID().BERDecodeAndCheck(algorithm); |
770 | 0 | BERDecodeAndCheckAlgorithmID(algorithm); |
771 | 0 | algorithm.MessageEnd(); |
772 | |
|
773 | 0 | BERDecodePublicKey(publicKeyInfo, false, (size_t)publicKeyInfo.RemainingLength()); |
774 | |
|
775 | 0 | publicKeyInfo.MessageEnd(); |
776 | 0 | } |
777 | | |
778 | | void ed25519PublicKey::DEREncode(BufferedTransformation &bt) const |
779 | 0 | { |
780 | 0 | DERSequenceEncoder publicKeyInfo(bt); |
781 | |
|
782 | 0 | DERSequenceEncoder algorithm(publicKeyInfo); |
783 | 0 | GetAlgorithmID().DEREncode(algorithm); |
784 | 0 | algorithm.MessageEnd(); |
785 | |
|
786 | 0 | DEREncodePublicKey(publicKeyInfo); |
787 | |
|
788 | 0 | publicKeyInfo.MessageEnd(); |
789 | 0 | } |
790 | | |
791 | | void ed25519PublicKey::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/) |
792 | 0 | { |
793 | | // We don't know how to decode them |
794 | 0 | if (parametersPresent) |
795 | 0 | BERDecodeError(); |
796 | |
|
797 | 0 | SecByteBlock subjectPublicKey; |
798 | 0 | unsigned int unusedBits; |
799 | 0 | BERDecodeBitString(bt, subjectPublicKey, unusedBits); |
800 | |
|
801 | 0 | CRYPTOPP_ASSERT(unusedBits == 0); |
802 | 0 | CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH); |
803 | 0 | if (subjectPublicKey.size() != PUBLIC_KEYLENGTH) |
804 | 0 | BERDecodeError(); |
805 | |
|
806 | 0 | std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH); |
807 | 0 | } |
808 | | |
809 | | void ed25519PublicKey::DEREncodePublicKey(BufferedTransformation &bt) const |
810 | 0 | { |
811 | 0 | DEREncodeBitString(bt, m_pk, PUBLIC_KEYLENGTH); |
812 | 0 | } |
813 | | |
814 | | void ed25519PublicKey::SetPublicElement (const byte y[PUBLIC_KEYLENGTH]) |
815 | 0 | { |
816 | 0 | std::memcpy(m_pk, y, PUBLIC_KEYLENGTH); |
817 | 0 | } |
818 | | |
819 | | void ed25519PublicKey::SetPublicElement (const Integer &y) |
820 | 0 | { |
821 | 0 | CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH); |
822 | |
|
823 | 0 | SecByteBlock by(PUBLIC_KEYLENGTH); |
824 | 0 | y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH); |
825 | |
|
826 | 0 | std::memcpy(m_pk, by, PUBLIC_KEYLENGTH); |
827 | 0 | } |
828 | | |
829 | | const Integer& ed25519PublicKey::GetPublicElement() const |
830 | 0 | { |
831 | 0 | m_y = Integer(m_pk, PUBLIC_KEYLENGTH, Integer::UNSIGNED, LITTLE_ENDIAN_ORDER); |
832 | 0 | return m_y; |
833 | 0 | } |
834 | | |
835 | | bool ed25519PublicKey::Validate(RandomNumberGenerator &rng, unsigned int level) const |
836 | 0 | { |
837 | 0 | CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(level); |
838 | 0 | return true; |
839 | 0 | } |
840 | | |
841 | | //////////////////////// |
842 | | |
843 | | ed25519Verifier::ed25519Verifier(const byte y[PUBLIC_KEYLENGTH]) |
844 | 0 | { |
845 | 0 | AccessPublicKey().AssignFrom(MakeParameters |
846 | 0 | (Name::PublicElement(), ConstByteArrayParameter(y, PUBLIC_KEYLENGTH))); |
847 | 0 | } |
848 | | |
849 | | ed25519Verifier::ed25519Verifier(const Integer &y) |
850 | 0 | { |
851 | 0 | CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH); |
852 | |
|
853 | 0 | SecByteBlock by(PUBLIC_KEYLENGTH); |
854 | 0 | y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH); |
855 | |
|
856 | 0 | AccessPublicKey().AssignFrom(MakeParameters |
857 | 0 | (Name::PublicElement(), ConstByteArrayParameter(by, PUBLIC_KEYLENGTH, false))); |
858 | 0 | } |
859 | | |
860 | | ed25519Verifier::ed25519Verifier(const X509PublicKey &key) |
861 | 0 | { |
862 | | // Load all fields from the other key |
863 | 0 | ByteQueue queue; |
864 | 0 | key.Save(queue); |
865 | 0 | AccessPublicKey().Load(queue); |
866 | 0 | } |
867 | | |
868 | | ed25519Verifier::ed25519Verifier(BufferedTransformation ¶ms) |
869 | 0 | { |
870 | 0 | AccessPublicKey().Load(params); |
871 | 0 | } |
872 | | |
873 | | ed25519Verifier::ed25519Verifier(const ed25519Signer& signer) |
874 | 0 | { |
875 | 0 | const ed25519PrivateKey& priv = dynamic_cast<const ed25519PrivateKey&>(signer.GetPrivateKey()); |
876 | 0 | priv.MakePublicKey(AccessPublicKey()); |
877 | 0 | } |
878 | | |
879 | | bool ed25519Verifier::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const |
880 | 0 | { |
881 | 0 | ed25519_MessageAccumulator& accum = static_cast<ed25519_MessageAccumulator&>(messageAccumulator); |
882 | 0 | const ed25519PublicKey& pk = dynamic_cast<const ed25519PublicKey&>(GetPublicKey()); |
883 | 0 | int ret = Donna::ed25519_sign_open(accum.data(), accum.size(), pk.GetPublicKeyBytePtr(), accum.signature()); |
884 | 0 | accum.Restart(); |
885 | |
|
886 | 0 | return ret == 0; |
887 | 0 | } |
888 | | |
889 | | bool ed25519Verifier::VerifyStream(std::istream& stream, const byte *signature, size_t signatureLen) const |
890 | 0 | { |
891 | 0 | CRYPTOPP_ASSERT(signatureLen == SIGNATURE_LENGTH); |
892 | 0 | CRYPTOPP_UNUSED(signatureLen); |
893 | |
|
894 | 0 | const ed25519PublicKey& pk = static_cast<const ed25519PublicKey&>(GetPublicKey()); |
895 | 0 | int ret = Donna::ed25519_sign_open(stream, pk.GetPublicKeyBytePtr(), signature); |
896 | |
|
897 | 0 | return ret == 0; |
898 | 0 | } |
899 | | |
900 | | NAMESPACE_END // CryptoPP |