Security Scol plugin
xed25519.cpp
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
18ANONYMOUS_NAMESPACE_BEGIN
19
20using CryptoPP::byte;
21
22CRYPTOPP_ALIGN_DATA(16)
23const 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
50bool HasSmallOrder(const byte y[32])
51{
52 // The magic 12 is the count of blaklisted points
53 byte c[12] = { 0 };
54 for (size_t j = 0; j < 32; j++) {
55 for (size_t i = 0; i < COUNTOF(blacklist); i++) {
56 c[i] |= y[j] ^ blacklist[i][j];
57 }
58 }
59
60 unsigned int k = 0;
61 for (size_t i = 0; i < COUNTOF(blacklist); i++) {
62 k |= (c[i] - 1);
63 }
64
65 return (bool)((k >> 8) & 1);
66}
67
68ANONYMOUS_NAMESPACE_END
69
70NAMESPACE_BEGIN(CryptoPP)
71
72// ******************** x25519 Agreement ************************* //
73
74x25519::x25519(const byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH])
75{
76 std::memcpy(m_pk, y, PUBLIC_KEYLENGTH);
77 std::memcpy(m_sk, x, SECRET_KEYLENGTH);
78
79 CRYPTOPP_ASSERT(IsClamped(m_sk) == true);
80 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
81}
82
83x25519::x25519(const byte x[SECRET_KEYLENGTH])
84{
85 std::memcpy(m_sk, x, SECRET_KEYLENGTH);
86 Donna::curve25519_mult(m_pk, m_sk);
87
88 CRYPTOPP_ASSERT(IsClamped(m_sk) == true);
89 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
90}
91
92x25519::x25519(const Integer &y, const Integer &x)
93{
94 CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH);
95 CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH);
96
97 y.Encode(m_pk, PUBLIC_KEYLENGTH); std::reverse(m_pk+0, m_pk+PUBLIC_KEYLENGTH);
98 x.Encode(m_sk, SECRET_KEYLENGTH); std::reverse(m_sk+0, m_sk+SECRET_KEYLENGTH);
99
100 CRYPTOPP_ASSERT(IsClamped(m_sk) == true);
101 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
102}
103
105{
106 CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH);
107
108 x.Encode(m_sk, SECRET_KEYLENGTH);
109 std::reverse(m_sk+0, m_sk+SECRET_KEYLENGTH);
110 Donna::curve25519_mult(m_pk, m_sk);
111
112 CRYPTOPP_ASSERT(IsClamped(m_sk) == true);
113 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
114}
115
117{
118 rng.GenerateBlock(m_sk, SECRET_KEYLENGTH);
119 ClampKey(m_sk);
120 SecretToPublicKey(m_pk, m_sk);
121}
122
124{
125 Load(params);
126}
127
128void x25519::ClampKey(byte x[SECRET_KEYLENGTH]) const
129{
130 x[0] &= 248; x[31] &= 127; x[31] |= 64;
131}
132
133bool x25519::IsClamped(const byte x[SECRET_KEYLENGTH]) const
134{
135 return (x[0] & 248) == x[0] && (x[31] & 127) == x[31] && (x[31] | 64) == x[31];
136}
137
138bool x25519::IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const
139{
140 return HasSmallOrder(y);
141}
142
143void x25519::SecretToPublicKey(byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) const
144{
145 Donna::curve25519_mult(y, x);
146}
147
149{
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 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 if (!m_oid.Empty() && m_oid != oid)
158 BERDecodeError(); // Only accept user specified OID
159 else if (oid == ASN1::curve25519() || oid == ASN1::X25519() ||
160 oid == OID(1)+3+6+1+4+1+3029+1+5)
161 m_oid = oid; // Accept any of the x25519 OIDs
162 else
164}
165
167{
168 // https://tools.ietf.org/html/rfc8410, section 7 and
169 // https://www.cryptopp.com/wiki/curve25519_keys
170 BERSequenceDecoder privateKeyInfo(bt);
171 word32 version;
172 BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 1); // check version
173
174 BERSequenceDecoder algorithm(privateKeyInfo);
175 // GetAlgorithmID().BERDecodeAndCheck(algorithm);
177 algorithm.MessageEnd();
178
179 BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
180 BERDecodePrivateKey(octetString, false, (size_t)privateKeyInfo.RemainingLength());
181 octetString.MessageEnd();
182
183 // publicKey [1] IMPLICIT PublicKey OPTIONAL
184 bool generatePublicKey = true;
185 if (privateKeyInfo.EndReached() == false /*version == 1?*/)
186 {
187 // Should we test this before decoding? In either case we
188 // just throw a BERDecodeErr() when we can't parse it.
189 BERGeneralDecoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1);
190 SecByteBlock subjectPublicKey;
191 unsigned int unusedBits;
192 BERDecodeBitString(publicKey, subjectPublicKey, unusedBits);
193 CRYPTOPP_ASSERT(unusedBits == 0);
194 CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH);
195 if (subjectPublicKey.size() != PUBLIC_KEYLENGTH)
197 std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH);
198 generatePublicKey = false;
199 publicKey.MessageEnd();
200 }
201
202 privateKeyInfo.MessageEnd();
203
204 if (generatePublicKey)
205 Donna::curve25519_mult(m_pk, m_sk);
206
207 CRYPTOPP_ASSERT(IsClamped(m_sk) == true);
208 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
209}
210
211void x25519::DEREncode(BufferedTransformation &bt, int version) const
212{
213 // https://tools.ietf.org/html/rfc8410, section 7 and
214 // https://www.cryptopp.com/wiki/curve25519_keys
215 CRYPTOPP_ASSERT(version == 0 || version == 1);
216
217 DERSequenceEncoder privateKeyInfo(bt);
218 DEREncodeUnsigned<word32>(privateKeyInfo, version);
219
220 DERSequenceEncoder algorithm(privateKeyInfo);
221 GetAlgorithmID().DEREncode(algorithm);
222 algorithm.MessageEnd();
223
224 DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
225 DEREncodePrivateKey(octetString);
226 octetString.MessageEnd();
227
228 if (version == 1)
229 {
230 DERGeneralEncoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1);
231 DEREncodeBitString(publicKey, m_pk, PUBLIC_KEYLENGTH);
232 publicKey.MessageEnd();
233 }
234
235 privateKeyInfo.MessageEnd();
236}
237
238void x25519::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/)
239{
240 // https://tools.ietf.org/html/rfc8410 and
241 // https://www.cryptopp.com/wiki/curve25519_keys
242
243 BERGeneralDecoder privateKey(bt, OCTET_STRING);
244
245 if (!privateKey.IsDefiniteLength())
247
248 size_t size = privateKey.Get(m_sk, SECRET_KEYLENGTH);
249 if (size != SECRET_KEYLENGTH)
251
252 // We don't know how to decode them
253 if (parametersPresent)
255
256 privateKey.MessageEnd();
257}
258
260{
261 // https://tools.ietf.org/html/rfc8410
262 DERGeneralEncoder privateKey(bt, OCTET_STRING);
263 privateKey.Put(m_sk, SECRET_KEYLENGTH);
264 privateKey.MessageEnd();
265}
266
267bool x25519::Validate(RandomNumberGenerator &rng, unsigned int level) const
268{
269 CRYPTOPP_UNUSED(rng);
270 CRYPTOPP_ASSERT(IsClamped(m_sk) == true);
271 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
272
273 if (level >= 1 && IsClamped(m_sk) == false)
274 return false;
275 if (level >= 2 && IsSmallOrder(m_pk) == true)
276 return false;
277 if (level >= 3)
278 {
279 // Verify m_pk is pairwise consistent with m_sk
280 SecByteBlock pk(PUBLIC_KEYLENGTH);
281 SecretToPublicKey(pk, m_sk);
282
283 if (VerifyBufsEqual(pk, m_pk, PUBLIC_KEYLENGTH) == false)
284 return false;
285 }
286
287 return true;
288}
289
290bool x25519::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
291{
292 if (std::strcmp(name, Name::PrivateExponent()) == 0 || std::strcmp(name, "SecretKey") == 0)
293 {
294 this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType);
295 reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_sk, SECRET_KEYLENGTH, false);
296 return true;
297 }
298
299 if (std::strcmp(name, Name::PublicElement()) == 0)
300 {
301 this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType);
302 reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false);
303 return true;
304 }
305
306 if (std::strcmp(name, Name::GroupOID()) == 0)
307 {
308 if (m_oid.Empty())
309 return false;
310
311 this->ThrowIfTypeMismatch(name, typeid(OID), valueType);
312 *reinterpret_cast<OID *>(pValue) = m_oid;
313 return true;
314 }
315
316 return false;
317}
318
320{
322 if (source.GetValue(Name::PrivateExponent(), val) || source.GetValue("SecretKey", val))
323 {
324 std::memcpy(m_sk, val.begin(), SECRET_KEYLENGTH);
325 }
326
327 if (source.GetValue(Name::PublicElement(), val))
328 {
329 std::memcpy(m_pk, val.begin(), PUBLIC_KEYLENGTH);
330 }
331
332 OID oid;
333 if (source.GetValue(Name::GroupOID(), oid))
334 {
335 m_oid = oid;
336 }
337
338 bool derive = false;
339 if (source.GetValue("DerivePublicKey", derive) && derive == true)
340 SecretToPublicKey(m_pk, m_sk);
341}
342
344{
346 if (params.GetValue(Name::Seed(), seed) && rng.CanIncorporateEntropy())
347 rng.IncorporateEntropy(seed.begin(), seed.size());
348
349 rng.GenerateBlock(m_sk, SECRET_KEYLENGTH);
350 ClampKey(m_sk);
351 SecretToPublicKey(m_pk, m_sk);
352}
353
354void x25519::GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
355{
356 rng.GenerateBlock(privateKey, SECRET_KEYLENGTH);
357 ClampKey(privateKey);
358}
359
360void x25519::GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
361{
362 CRYPTOPP_UNUSED(rng);
363 SecretToPublicKey(publicKey, privateKey);
364}
365
366bool x25519::Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey) const
367{
368 CRYPTOPP_ASSERT(agreedValue != NULLPTR);
369 CRYPTOPP_ASSERT(otherPublicKey != NULLPTR);
370
371 if (validateOtherPublicKey && IsSmallOrder(otherPublicKey))
372 return false;
373
374 return Donna::curve25519_mult(agreedValue, privateKey, otherPublicKey) == 0;
375}
376
377// ******************** ed25519 Signer ************************* //
378
379void ed25519PrivateKey::SecretToPublicKey(byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH]) const
380{
381 int ret = Donna::ed25519_publickey(y, x);
382 CRYPTOPP_ASSERT(ret == 0); CRYPTOPP_UNUSED(ret);
383}
384
385bool ed25519PrivateKey::IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const
386{
387 return HasSmallOrder(y);
388}
389
390bool ed25519PrivateKey::Validate(RandomNumberGenerator &rng, unsigned int level) const
391{
392 CRYPTOPP_UNUSED(rng);
393 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
394
395 if (level >= 1 && IsSmallOrder(m_pk) == true)
396 return false;
397 if (level >= 3)
398 {
399 // Verify m_pk is pairwise consistent with m_sk
400 SecByteBlock pk(PUBLIC_KEYLENGTH);
401 SecretToPublicKey(pk, m_sk);
402
403 if (VerifyBufsEqual(pk, m_pk, PUBLIC_KEYLENGTH) == false)
404 return false;
405 }
406
407 return true;
408}
409
410bool ed25519PrivateKey::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
411{
412 if (std::strcmp(name, Name::PrivateExponent()) == 0 || std::strcmp(name, "SecretKey") == 0)
413 {
414 this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType);
415 reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_sk, SECRET_KEYLENGTH, false);
416 return true;
417 }
418
419 if (std::strcmp(name, Name::PublicElement()) == 0)
420 {
421 this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType);
422 reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false);
423 return true;
424 }
425
426 if (std::strcmp(name, Name::GroupOID()) == 0)
427 {
428 if (m_oid.Empty())
429 return false;
430
431 this->ThrowIfTypeMismatch(name, typeid(OID), valueType);
432 *reinterpret_cast<OID *>(pValue) = m_oid;
433 return true;
434 }
435
436 return false;
437}
438
440{
442 if (source.GetValue(Name::PrivateExponent(), val) || source.GetValue("SecretKey", val))
443 {
444 CRYPTOPP_ASSERT(val.size() == SECRET_KEYLENGTH);
445 std::memcpy(m_sk, val.begin(), SECRET_KEYLENGTH);
446 }
447 if (source.GetValue(Name::PublicElement(), val))
448 {
449 CRYPTOPP_ASSERT(val.size() == PUBLIC_KEYLENGTH);
450 std::memcpy(m_pk, val.begin(), PUBLIC_KEYLENGTH);
451 }
452
453 OID oid;
454 if (source.GetValue(Name::GroupOID(), oid))
455 {
456 m_oid = oid;
457 }
458
459 bool derive = false;
460 if (source.GetValue("DerivePublicKey", derive) && derive == true)
461 SecretToPublicKey(m_pk, m_sk);
462
463 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
464}
465
466void ed25519PrivateKey::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params=g_nullNameValuePairs)
467{
469 if (params.GetValue(Name::Seed(), seed) && rng.CanIncorporateEntropy())
470 rng.IncorporateEntropy(seed.begin(), seed.size());
471
472 rng.GenerateBlock(m_sk, SECRET_KEYLENGTH);
473 int ret = Donna::ed25519_publickey(m_pk, m_sk);
474 CRYPTOPP_ASSERT(ret == 0); CRYPTOPP_UNUSED(ret);
475}
476
478{
480 (Name::PublicElement(), ConstByteArrayParameter(m_pk.begin(), PUBLIC_KEYLENGTH))
481 (Name::GroupOID(), GetAlgorithmID()));
482}
483
485{
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 OID oid(bt);
490
491 if (!m_oid.Empty() && m_oid != oid)
492 BERDecodeError(); // Only accept user specified OID
493 else if (oid == ASN1::curve25519() || oid == ASN1::Ed25519())
494 m_oid = oid; // Accept any of the ed25519PrivateKey OIDs
495 else
497}
498
500{
501 // https://tools.ietf.org/html/rfc8410, section 7 and
502 // https://www.cryptopp.com/wiki/curve25519_keys
503 BERSequenceDecoder privateKeyInfo(bt);
504 word32 version;
505 BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 1); // check version
506
507 BERSequenceDecoder algorithm(privateKeyInfo);
508 // GetAlgorithmID().BERDecodeAndCheck(algorithm);
510 algorithm.MessageEnd();
511
512 BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
513 BERDecodePrivateKey(octetString, false, (size_t)privateKeyInfo.RemainingLength());
514 octetString.MessageEnd();
515
516 // publicKey [1] IMPLICIT PublicKey OPTIONAL
517 bool generatePublicKey = true;
518 if (privateKeyInfo.EndReached() == false /*version == 1?*/)
519 {
520 // Should we test this before decoding? In either case we
521 // just throw a BERDecodeErr() when we can't parse it.
522 BERGeneralDecoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1);
523 SecByteBlock subjectPublicKey;
524 unsigned int unusedBits;
525 BERDecodeBitString(publicKey, subjectPublicKey, unusedBits);
526 CRYPTOPP_ASSERT(unusedBits == 0);
527 CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH);
528 if (subjectPublicKey.size() != PUBLIC_KEYLENGTH)
530 std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH);
531 generatePublicKey = false;
532 publicKey.MessageEnd();
533 }
534
535 privateKeyInfo.MessageEnd();
536
537 if (generatePublicKey)
538 Donna::ed25519_publickey(m_pk, m_sk);
539
540 CRYPTOPP_ASSERT(IsSmallOrder(m_pk) == false);
541}
542
544{
545 // https://tools.ietf.org/html/rfc8410, section 7 and
546 // https://www.cryptopp.com/wiki/curve25519_keys
547 CRYPTOPP_ASSERT(version == 0 || version == 1);
548
549 DERSequenceEncoder privateKeyInfo(bt);
550 DEREncodeUnsigned<word32>(privateKeyInfo, version);
551
552 DERSequenceEncoder algorithm(privateKeyInfo);
553 GetAlgorithmID().DEREncode(algorithm);
554 algorithm.MessageEnd();
555
556 DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
557 DEREncodePrivateKey(octetString);
558 octetString.MessageEnd();
559
560 if (version == 1)
561 {
562 DERGeneralEncoder publicKey(privateKeyInfo, CONTEXT_SPECIFIC | CONSTRUCTED | 1);
563 DEREncodeBitString(publicKey, m_pk, PUBLIC_KEYLENGTH);
564 publicKey.MessageEnd();
565 }
566
567 privateKeyInfo.MessageEnd();
568}
569
570void ed25519PrivateKey::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/)
571{
572 // https://tools.ietf.org/html/rfc8410 and
573 // https://www.cryptopp.com/wiki/curve25519_keys
574
575 BERGeneralDecoder privateKey(bt, OCTET_STRING);
576
577 if (!privateKey.IsDefiniteLength())
579
580 size_t size = privateKey.Get(m_sk, SECRET_KEYLENGTH);
581 if (size != SECRET_KEYLENGTH)
583
584 // We don't know how to decode them
585 if (parametersPresent)
587
588 privateKey.MessageEnd();
589}
590
592{
593 // https://tools.ietf.org/html/rfc8410
594 DERGeneralEncoder privateKey(bt, OCTET_STRING);
595 privateKey.Put(m_sk, SECRET_KEYLENGTH);
596 privateKey.MessageEnd();
597}
598
599void ed25519PrivateKey::SetPrivateExponent (const byte x[SECRET_KEYLENGTH])
600{
602 (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH))
603 ("DerivePublicKey", true));
604}
605
606void ed25519PrivateKey::SetPrivateExponent (const Integer &x)
607{
608 CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH);
609
610 SecByteBlock bx(SECRET_KEYLENGTH);
611 x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH);
612
614 (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false))
615 ("DerivePublicKey", true));
616}
617
618const Integer& ed25519PrivateKey::GetPrivateExponent() const
619{
620 m_x = Integer(m_sk, SECRET_KEYLENGTH, Integer::UNSIGNED, LITTLE_ENDIAN_ORDER);
621 return m_x;
622}
623
625
626ed25519Signer::ed25519Signer(const byte y[PUBLIC_KEYLENGTH], const byte x[SECRET_KEYLENGTH])
627{
629 (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH, false))
630 (Name::PublicElement(), ConstByteArrayParameter(y, PUBLIC_KEYLENGTH, false)));
631}
632
633ed25519Signer::ed25519Signer(const byte x[SECRET_KEYLENGTH])
634{
636 (Name::PrivateExponent(), ConstByteArrayParameter(x, SECRET_KEYLENGTH, false))
637 ("DerivePublicKey", true));
638}
639
641{
642 CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH);
643 CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH);
644
645 SecByteBlock by(PUBLIC_KEYLENGTH), bx(SECRET_KEYLENGTH);
646 y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH);
647 x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH);
648
650 (Name::PublicElement(), ConstByteArrayParameter(by, PUBLIC_KEYLENGTH, false))
651 (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false)));
652}
653
655{
656 CRYPTOPP_ASSERT(x.MinEncodedSize() <= SECRET_KEYLENGTH);
657
658 SecByteBlock bx(SECRET_KEYLENGTH);
659 x.Encode(bx, SECRET_KEYLENGTH); std::reverse(bx+0, bx+SECRET_KEYLENGTH);
660
662 (Name::PrivateExponent(), ConstByteArrayParameter(bx, SECRET_KEYLENGTH, false))
663 ("DerivePublicKey", true));
664}
665
667{
668 // Load all fields from the other key
669 ByteQueue queue;
670 key.Save(queue);
671 AccessPrivateKey().Load(queue);
672}
673
678
683
684size_t ed25519Signer::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
685{
686 CRYPTOPP_ASSERT(signature != NULLPTR); CRYPTOPP_UNUSED(rng);
687
688 ed25519_MessageAccumulator& accum = dynamic_cast<ed25519_MessageAccumulator&>(messageAccumulator);
689 const ed25519PrivateKey& pk = dynamic_cast<const ed25519PrivateKey&>(GetPrivateKey());
690 int ret = Donna::ed25519_sign(accum.data(), accum.size(), pk.GetPrivateKeyBytePtr(), pk.GetPublicKeyBytePtr(), signature);
691 CRYPTOPP_ASSERT(ret == 0);
692
693 if (restart)
694 accum.Restart();
695
696 return ret == 0 ? SIGNATURE_LENGTH : 0;
697}
698
699size_t ed25519Signer::SignStream (RandomNumberGenerator &rng, std::istream& stream, byte *signature) const
700{
701 CRYPTOPP_ASSERT(signature != NULLPTR); CRYPTOPP_UNUSED(rng);
702
703 const ed25519PrivateKey& pk = dynamic_cast<const ed25519PrivateKey&>(GetPrivateKey());
704 int ret = Donna::ed25519_sign(stream, pk.GetPrivateKeyBytePtr(), pk.GetPublicKeyBytePtr(), signature);
705 CRYPTOPP_ASSERT(ret == 0);
706
707 return ret == 0 ? SIGNATURE_LENGTH : 0;
708}
709
710// ******************** ed25519 Verifier ************************* //
711
712bool ed25519PublicKey::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
713{
714 if (std::strcmp(name, Name::PublicElement()) == 0)
715 {
716 this->ThrowIfTypeMismatch(name, typeid(ConstByteArrayParameter), valueType);
717 reinterpret_cast<ConstByteArrayParameter*>(pValue)->Assign(m_pk, PUBLIC_KEYLENGTH, false);
718 return true;
719 }
720
721 if (std::strcmp(name, Name::GroupOID()) == 0)
722 {
723 if (m_oid.Empty())
724 return false;
725
726 this->ThrowIfTypeMismatch(name, typeid(OID), valueType);
727 *reinterpret_cast<OID *>(pValue) = m_oid;
728 return true;
729 }
730
731 return false;
732}
733
735{
737 if (source.GetValue(Name::PublicElement(), ba))
738 {
739 std::memcpy(m_pk, ba.begin(), PUBLIC_KEYLENGTH);
740 }
741
742 OID oid;
743 if (source.GetValue(Name::GroupOID(), oid))
744 {
745 m_oid = oid;
746 }
747}
748
750{
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 OID oid(bt);
755
756 if (!m_oid.Empty() && m_oid != oid)
757 BERDecodeError(); // Only accept user specified OID
758 else if (oid == ASN1::curve25519() || oid == ASN1::Ed25519())
759 m_oid = oid; // Accept any of the ed25519PublicKey OIDs
760 else
762}
763
765{
766 BERSequenceDecoder publicKeyInfo(bt);
767
768 BERSequenceDecoder algorithm(publicKeyInfo);
769 // GetAlgorithmID().BERDecodeAndCheck(algorithm);
771 algorithm.MessageEnd();
772
773 BERDecodePublicKey(publicKeyInfo, false, (size_t)publicKeyInfo.RemainingLength());
774
775 publicKeyInfo.MessageEnd();
776}
777
779{
780 DERSequenceEncoder publicKeyInfo(bt);
781
782 DERSequenceEncoder algorithm(publicKeyInfo);
783 GetAlgorithmID().DEREncode(algorithm);
784 algorithm.MessageEnd();
785
786 DEREncodePublicKey(publicKeyInfo);
787
788 publicKeyInfo.MessageEnd();
789}
790
791void ed25519PublicKey::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t /*size*/)
792{
793 // We don't know how to decode them
794 if (parametersPresent)
796
797 SecByteBlock subjectPublicKey;
798 unsigned int unusedBits;
799 BERDecodeBitString(bt, subjectPublicKey, unusedBits);
800
801 CRYPTOPP_ASSERT(unusedBits == 0);
802 CRYPTOPP_ASSERT(subjectPublicKey.size() == PUBLIC_KEYLENGTH);
803 if (subjectPublicKey.size() != PUBLIC_KEYLENGTH)
805
806 std::memcpy(m_pk.begin(), subjectPublicKey, PUBLIC_KEYLENGTH);
807}
808
810{
811 DEREncodeBitString(bt, m_pk, PUBLIC_KEYLENGTH);
812}
813
814void ed25519PublicKey::SetPublicElement (const byte y[PUBLIC_KEYLENGTH])
815{
816 std::memcpy(m_pk, y, PUBLIC_KEYLENGTH);
817}
818
819void ed25519PublicKey::SetPublicElement (const Integer &y)
820{
821 CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH);
822
823 SecByteBlock by(PUBLIC_KEYLENGTH);
824 y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH);
825
826 std::memcpy(m_pk, by, PUBLIC_KEYLENGTH);
827}
828
829const Integer& ed25519PublicKey::GetPublicElement() const
830{
831 m_y = Integer(m_pk, PUBLIC_KEYLENGTH, Integer::UNSIGNED, LITTLE_ENDIAN_ORDER);
832 return m_y;
833}
834
835bool ed25519PublicKey::Validate(RandomNumberGenerator &rng, unsigned int level) const
836{
837 CRYPTOPP_UNUSED(rng); CRYPTOPP_UNUSED(level);
838 return true;
839}
840
842
843ed25519Verifier::ed25519Verifier(const byte y[PUBLIC_KEYLENGTH])
844{
846 (Name::PublicElement(), ConstByteArrayParameter(y, PUBLIC_KEYLENGTH)));
847}
848
850{
851 CRYPTOPP_ASSERT(y.MinEncodedSize() <= PUBLIC_KEYLENGTH);
852
853 SecByteBlock by(PUBLIC_KEYLENGTH);
854 y.Encode(by, PUBLIC_KEYLENGTH); std::reverse(by+0, by+PUBLIC_KEYLENGTH);
855
857 (Name::PublicElement(), ConstByteArrayParameter(by, PUBLIC_KEYLENGTH, false)));
858}
859
861{
862 // Load all fields from the other key
863 ByteQueue queue;
864 key.Save(queue);
865 AccessPublicKey().Load(queue);
866}
867
872
874{
875 const ed25519PrivateKey& priv = dynamic_cast<const ed25519PrivateKey&>(signer.GetPrivateKey());
877}
878
880{
881 ed25519_MessageAccumulator& accum = static_cast<ed25519_MessageAccumulator&>(messageAccumulator);
882 const ed25519PublicKey& pk = dynamic_cast<const ed25519PublicKey&>(GetPublicKey());
883 int ret = Donna::ed25519_sign_open(accum.data(), accum.size(), pk.GetPublicKeyBytePtr(), accum.signature());
884 accum.Restart();
885
886 return ret == 0;
887}
888
889bool ed25519Verifier::VerifyStream(std::istream& stream, const byte *signature, size_t signatureLen) const
890{
891 CRYPTOPP_ASSERT(signatureLen == SIGNATURE_LENGTH);
892 CRYPTOPP_UNUSED(signatureLen);
893
894 const ed25519PublicKey& pk = static_cast<const ed25519PublicKey&>(GetPublicKey());
895 int ret = Donna::ed25519_sign_open(stream, pk.GetPublicKeyBytePtr(), signature);
896
897 return ret == 0;
898}
899
900NAMESPACE_END // CryptoPP
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed=true)
Create an object that implements NameValuePairs.
Definition algparam.h:508
Classes and functions for working with ANS.1 objects.
@ CONSTRUCTED
ASN.1 Constructed flag.
Definition asn.h:94
@ CONTEXT_SPECIFIC
ASN.1 Context specific class.
Definition asn.h:98
@ OCTET_STRING
ASN.1 Octet string.
Definition asn.h:38
@ INTEGER
ASN.1 Integer.
Definition asn.h:34
void BERDecodeError()
Raises a BERDecodeErr.
Definition asn.h:104
void Save(BufferedTransformation &bt) const
DER encode ASN.1 object.
Definition asn.h:691
BER General Decoder.
Definition asn.h:380
bool EndReached() const
Determine end of stream.
Definition asn.cpp:527
lword RemainingLength() const
Determine remaining length.
Definition asn.h:412
bool IsDefiniteLength() const
Determine length encoding.
Definition asn.h:404
void MessageEnd()
Signals the end of messages to the object.
Definition asn.cpp:553
BER Sequence Decoder.
Definition asn.h:525
Interface for buffered transformations.
Definition cryptlib.h:1652
virtual size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Definition cryptlib.cpp:528
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition cryptlib.h:1673
Data structure used to store byte strings.
Definition queue.h:23
Used to pass byte array input as part of a NameValuePairs object.
Definition algparam.h:25
const byte * begin() const
Pointer to the first byte in the memory block.
Definition algparam.h:84
size_t size() const
Length of the memory block.
Definition algparam.h:88
virtual void AssignFrom(const NameValuePairs &source)=0
Assign values to this object.
virtual void Load(BufferedTransformation &bt)
Loads a key from a BufferedTransformation.
Definition cryptlib.h:2456
DER General Encoder.
Definition asn.h:491
void MessageEnd()
Signals the end of messages to the object.
Definition asn.cpp:624
DER Sequence Encoder.
Definition asn.h:557
virtual void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params=g_nullNameValuePairs)
Generate a random key or crypto parameters.
Definition cryptlib.h:2520
Multiple precision integer with arithmetic operations.
Definition integer.h:50
size_t MinEncodedSize(Signedness sign=UNSIGNED) const
Minimum number of bytes to encode this integer.
Definition integer.cpp:3412
@ UNSIGNED
an unsigned value
Definition integer.h:85
void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const
Encode in big-endian format.
Definition integer.cpp:3427
Interface for retrieving values given their names.
Definition cryptlib.h:322
bool GetValue(const char *name, T &value) const
Get a named value.
Definition cryptlib.h:379
static CRYPTOPP_DLL void CRYPTOPP_API ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving)
Ensures an expected name and type is present.
Definition cryptlib.h:454
Object Identifier.
Definition asn.h:265
void DEREncode(BufferedTransformation &bt) const
DER encode this OID.
Definition asn.cpp:333
bool Empty() const
Determine if OID is empty.
Definition asn.h:311
Interface for accumulating messages to be signed or verified.
Definition cryptlib.h:2861
Encodes and Decodes privateKeyInfo.
Definition asn.h:748
Interface for public keys.
Definition cryptlib.h:2536
Interface for random number generators.
Definition cryptlib.h:1435
virtual void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
Definition cryptlib.cpp:311
virtual void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
Definition cryptlib.h:1447
virtual bool CanIncorporateEntropy() const
Determines if a generator can accept additional entropy.
Definition cryptlib.h:1455
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition secblock.h:836
size_type size() const
Provides the count of elements in the SecBlock.
Definition secblock.h:867
Encodes and decodes subjectPublicKeyInfo.
Definition asn.h:702
x25519 with key validation
Definition xed25519.h:55
bool IsClamped(const byte x[SECRET_KEYLENGTH]) const
Determine if private key is clamped.
Definition xed25519.cpp:133
void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
Decode privateKey part of privateKeyInfo.
Definition xed25519.cpp:238
bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const
Derive agreed value.
Definition xed25519.cpp:366
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Definition xed25519.cpp:290
void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
Generate private key in this domain.
Definition xed25519.cpp:354
bool IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const
Test if a key has small order.
Definition xed25519.cpp:138
void ClampKey(byte x[SECRET_KEYLENGTH]) const
Clamp a private key.
Definition xed25519.cpp:128
void BERDecodeAndCheckAlgorithmID(BufferedTransformation &bt)
Determine if OID is valid for this object.
Definition xed25519.cpp:148
void DEREncodePrivateKey(BufferedTransformation &bt) const
Encode privateKey part of privateKeyInfo.
Definition xed25519.cpp:259
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition xed25519.h:200
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
Check this object for errors.
Definition xed25519.cpp:267
void Load(BufferedTransformation &bt)
BER decode ASN.1 object.
Definition xed25519.h:194
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition xed25519.cpp:166
x25519()
Create a x25519 object.
Definition xed25519.h:74
void AssignFrom(const NameValuePairs &source)
Assign values to this object.
Definition xed25519.cpp:319
void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
Generate a public key from a private key in this domain.
Definition xed25519.cpp:360
OID GetAlgorithmID() const
Get the Object Identifier.
Definition xed25519.h:138
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
Generate a random key or crypto parameters.
Definition xed25519.cpp:343
unsigned int word32
32-bit unsigned datatype
Definition config_int.h:62
Abstract base classes that provide a uniform interface to this library.
Implementation of BufferedTransformation's attachment interface.
Multiple precision integer with arithmetic operations.
Precompiled header file.
Common C++ header files.
ed25519 message accumulator
Definition xed25519.h:279
void Restart()
Reset the accumulator.
Definition xed25519.h:304
size_t size() const
Retrieve size of data buffer.
Definition xed25519.h:329
const byte * data() const
Retrieve pointer to data buffer.
Definition xed25519.h:323
byte * signature()
Retrieve pointer to signature buffer.
Definition xed25519.h:311
Ed25519 private key.
Definition xed25519.h:356
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Definition xed25519.cpp:410
const byte * GetPrivateKeyBytePtr() const
Retrieve private key byte array.
Definition xed25519.h:474
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
Generate a random key or crypto parameters.
Definition xed25519.cpp:466
void MakePublicKey(PublicKey &pub) const
Initializes a public key from this key.
Definition xed25519.cpp:477
OID GetAlgorithmID() const
Retrieves the OID of the algorithm.
Definition xed25519.h:377
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
Check this object for errors.
Definition xed25519.cpp:390
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition xed25519.h:429
void DEREncodePrivateKey(BufferedTransformation &bt) const
Encode privateKey part of privateKeyInfo.
Definition xed25519.cpp:591
void AssignFrom(const NameValuePairs &source)
Assign values to this object.
Definition xed25519.cpp:439
void BERDecodeAndCheckAlgorithmID(BufferedTransformation &bt)
Determine if OID is valid for this object.
Definition xed25519.cpp:484
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition xed25519.cpp:499
bool IsSmallOrder(const byte y[PUBLIC_KEYLENGTH]) const
Test if a key has small order.
Definition xed25519.cpp:385
const byte * GetPublicKeyBytePtr() const
Retrieve public key byte array.
Definition xed25519.h:481
void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
Decode privateKey part of privateKeyInfo.
Definition xed25519.cpp:570
Ed25519 public key.
Definition xed25519.h:635
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition xed25519.cpp:764
void BERDecodeAndCheckAlgorithmID(BufferedTransformation &bt)
Determine if OID is valid for this object.
Definition xed25519.cpp:749
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Definition xed25519.cpp:712
void DEREncodePublicKey(BufferedTransformation &bt) const
Encode subjectPublicKey part of subjectPublicKeyInfo.
Definition xed25519.cpp:809
void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
Decode subjectPublicKey part of subjectPublicKeyInfo.
Definition xed25519.cpp:791
const byte * GetPublicKeyBytePtr() const
Retrieve public key byte array.
Definition xed25519.h:700
OID GetAlgorithmID() const
Retrieves the OID of the algorithm.
Definition xed25519.h:643
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition xed25519.cpp:778
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
Check this object for errors.
Definition xed25519.cpp:835
void AssignFrom(const NameValuePairs &source)
Assign values to this object.
Definition xed25519.cpp:734
Ed25519 signature algorithm.
Definition xed25519.h:499
ed25519Signer()
Create an ed25519Signer object.
Definition xed25519.h:516
PrivateKey & AccessPrivateKey()
Retrieves a reference to a Private Key.
Definition xed25519.h:567
size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
Sign and restart messageAccumulator.
Definition xed25519.cpp:684
const PrivateKey & GetPrivateKey() const
Retrieves a reference to a Private Key.
Definition xed25519.h:572
size_t SignStream(RandomNumberGenerator &rng, std::istream &stream, byte *signature) const
Sign a stream.
Definition xed25519.cpp:699
bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
Check whether messageAccumulator contains a valid signature and message, and restart messageAccumulat...
Definition xed25519.cpp:879
PublicKey & AccessPublicKey()
Retrieves a reference to a Public Key.
Definition xed25519.h:760
ed25519Verifier()
Create an ed25519Verifier object.
Definition xed25519.h:721
bool VerifyStream(std::istream &stream, const byte *signature, size_t signatureLen) const
Check whether input signature is a valid signature for input message.
Definition xed25519.cpp:889
const PublicKey & GetPublicKey() const
Retrieves a reference to a Public Key.
Definition xed25519.h:765
Classes for x25519 and ed25519 operations.