1use crate::{Array, BatchVerifier};
2#[cfg(not(feature = "std"))]
3use alloc::{
4 borrow::{Cow, ToOwned},
5 vec::Vec,
6};
7use bytes::{Buf, BufMut};
8use commonware_codec::{Error as CodecError, FixedSize, Read, ReadExt, Write};
9use commonware_math::algebra::Random;
10use commonware_utils::{hex, union_unique, Span};
11use core::{
12 fmt::{Debug, Display},
13 hash::{Hash, Hasher},
14 ops::Deref,
15};
16use ed25519_consensus::{self, VerificationKey};
17use rand_core::CryptoRngCore;
18#[cfg(feature = "std")]
19use std::borrow::{Cow, ToOwned};
20use zeroize::{Zeroize, ZeroizeOnDrop};
21
22const CURVE_NAME: &str = "ed25519";
23const PRIVATE_KEY_LENGTH: usize = 32;
24const PUBLIC_KEY_LENGTH: usize = 32;
25const SIGNATURE_LENGTH: usize = 64;
26
27#[derive(Clone, Zeroize, ZeroizeOnDrop)]
29pub struct PrivateKey {
30 raw: [u8; PRIVATE_KEY_LENGTH],
31 key: ed25519_consensus::SigningKey,
32}
33
34impl crate::PrivateKey for PrivateKey {}
35
36impl crate::Signer for PrivateKey {
37 type Signature = Signature;
38 type PublicKey = PublicKey;
39
40 fn sign(&self, namespace: &[u8], msg: &[u8]) -> Self::Signature {
41 self.sign_inner(Some(namespace), msg)
42 }
43
44 fn public_key(&self) -> Self::PublicKey {
45 let raw = self.key.verification_key().to_bytes();
46 Self::PublicKey {
47 raw,
48 key: self.key.verification_key().to_owned(),
49 }
50 }
51}
52
53impl PrivateKey {
54 #[inline(always)]
55 fn sign_inner(&self, namespace: Option<&[u8]>, msg: &[u8]) -> Signature {
56 let payload = namespace
57 .map(|namespace| Cow::Owned(union_unique(namespace, msg)))
58 .unwrap_or_else(|| Cow::Borrowed(msg));
59 let sig = self.key.sign(&payload);
60 Signature::from(sig)
61 }
62}
63
64impl Random for PrivateKey {
65 fn random(rng: impl CryptoRngCore) -> Self {
66 let key = ed25519_consensus::SigningKey::new(rng);
67 let raw = key.to_bytes();
68 Self { raw, key }
69 }
70}
71
72impl Write for PrivateKey {
73 fn write(&self, buf: &mut impl BufMut) {
74 self.raw.write(buf);
75 }
76}
77
78impl Read for PrivateKey {
79 type Cfg = ();
80
81 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
82 let raw = <[u8; Self::SIZE]>::read(buf)?;
83 let key = ed25519_consensus::SigningKey::from(raw);
84 Ok(Self { raw, key })
85 }
86}
87
88impl FixedSize for PrivateKey {
89 const SIZE: usize = PRIVATE_KEY_LENGTH;
90}
91
92impl Span for PrivateKey {}
93
94impl Array for PrivateKey {}
95
96impl Eq for PrivateKey {}
97
98impl Hash for PrivateKey {
99 fn hash<H: Hasher>(&self, state: &mut H) {
100 self.raw.hash(state);
101 }
102}
103
104impl PartialEq for PrivateKey {
105 fn eq(&self, other: &Self) -> bool {
106 self.raw == other.raw
107 }
108}
109
110impl Ord for PrivateKey {
111 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
112 self.raw.cmp(&other.raw)
113 }
114}
115
116impl PartialOrd for PrivateKey {
117 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
118 Some(self.cmp(other))
119 }
120}
121
122impl AsRef<[u8]> for PrivateKey {
123 fn as_ref(&self) -> &[u8] {
124 &self.raw
125 }
126}
127
128impl Deref for PrivateKey {
129 type Target = [u8];
130 fn deref(&self) -> &[u8] {
131 &self.raw
132 }
133}
134
135impl From<ed25519_consensus::SigningKey> for PrivateKey {
136 fn from(key: ed25519_consensus::SigningKey) -> Self {
137 let raw = key.to_bytes();
138 Self { raw, key }
139 }
140}
141
142impl Debug for PrivateKey {
143 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
144 write!(f, "{}", hex(&self.raw))
145 }
146}
147
148impl Display for PrivateKey {
149 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
150 write!(f, "{}", hex(&self.raw))
151 }
152}
153
154#[cfg(feature = "arbitrary")]
155impl arbitrary::Arbitrary<'_> for PrivateKey {
156 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
157 use rand::{rngs::StdRng, SeedableRng};
158
159 let mut rand = StdRng::from_seed(u.arbitrary::<[u8; 32]>()?);
160 Ok(Self::random(&mut rand))
161 }
162}
163
164#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
166pub struct PublicKey {
167 raw: [u8; PUBLIC_KEY_LENGTH],
168 key: ed25519_consensus::VerificationKey,
169}
170
171impl From<PrivateKey> for PublicKey {
172 fn from(value: PrivateKey) -> Self {
173 let raw = value.key.verification_key().to_bytes();
174 Self {
175 raw,
176 key: value.key.verification_key(),
177 }
178 }
179}
180
181impl crate::PublicKey for PublicKey {}
182
183impl crate::Verifier for PublicKey {
184 type Signature = Signature;
185
186 fn verify(&self, namespace: &[u8], msg: &[u8], sig: &Self::Signature) -> bool {
187 self.verify_inner(Some(namespace), msg, sig)
188 }
189}
190
191impl PublicKey {
192 #[inline(always)]
193 fn verify_inner(&self, namespace: Option<&[u8]>, msg: &[u8], sig: &Signature) -> bool {
194 let payload = namespace
195 .map(|namespace| Cow::Owned(union_unique(namespace, msg)))
196 .unwrap_or_else(|| Cow::Borrowed(msg));
197 self.key.verify(&sig.signature, &payload).is_ok()
198 }
199}
200
201impl Write for PublicKey {
202 fn write(&self, buf: &mut impl BufMut) {
203 self.raw.write(buf);
204 }
205}
206
207impl Read for PublicKey {
208 type Cfg = ();
209
210 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
211 let raw = <[u8; Self::SIZE]>::read(buf)?;
212 let result = VerificationKey::try_from(raw);
213 #[cfg(feature = "std")]
214 let key = result.map_err(|e| CodecError::Wrapped(CURVE_NAME, e.into()))?;
215 #[cfg(not(feature = "std"))]
216 let key = result
217 .map_err(|e| CodecError::Wrapped(CURVE_NAME, alloc::format!("{:?}", e).into()))?;
218
219 Ok(Self { raw, key })
220 }
221}
222
223impl FixedSize for PublicKey {
224 const SIZE: usize = PUBLIC_KEY_LENGTH;
225}
226
227impl Span for PublicKey {}
228
229impl Array for PublicKey {}
230
231impl AsRef<[u8]> for PublicKey {
232 fn as_ref(&self) -> &[u8] {
233 &self.raw
234 }
235}
236
237impl Deref for PublicKey {
238 type Target = [u8];
239 fn deref(&self) -> &[u8] {
240 &self.raw
241 }
242}
243
244impl From<VerificationKey> for PublicKey {
245 fn from(key: VerificationKey) -> Self {
246 let raw = key.to_bytes();
247 Self { raw, key }
248 }
249}
250
251impl Debug for PublicKey {
252 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
253 write!(f, "{}", hex(&self.raw))
254 }
255}
256
257impl Display for PublicKey {
258 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
259 write!(f, "{}", hex(&self.raw))
260 }
261}
262
263#[cfg(feature = "arbitrary")]
264impl arbitrary::Arbitrary<'_> for PublicKey {
265 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
266 use crate::Signer;
267 use commonware_math::algebra::Random;
268 use rand::{rngs::StdRng, SeedableRng};
269
270 let mut rand = StdRng::from_seed(u.arbitrary::<[u8; 32]>()?);
271 let private_key = PrivateKey::random(&mut rand);
272 Ok(private_key.public_key())
273 }
274}
275
276#[derive(Clone, Eq, PartialEq)]
278pub struct Signature {
279 raw: [u8; SIGNATURE_LENGTH],
280 signature: ed25519_consensus::Signature,
281}
282
283impl crate::Signature for Signature {}
284
285impl Write for Signature {
286 fn write(&self, buf: &mut impl BufMut) {
287 self.raw.write(buf);
288 }
289}
290
291impl Read for Signature {
292 type Cfg = ();
293
294 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
295 let raw = <[u8; Self::SIZE]>::read(buf)?;
296 let signature = ed25519_consensus::Signature::from(raw);
297 Ok(Self { raw, signature })
298 }
299}
300
301impl FixedSize for Signature {
302 const SIZE: usize = SIGNATURE_LENGTH;
303}
304
305impl Span for Signature {}
306
307impl Array for Signature {}
308
309impl Hash for Signature {
310 fn hash<H: Hasher>(&self, state: &mut H) {
311 self.raw.hash(state);
312 }
313}
314
315impl Ord for Signature {
316 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
317 self.raw.cmp(&other.raw)
318 }
319}
320
321impl PartialOrd for Signature {
322 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
323 Some(self.cmp(other))
324 }
325}
326
327impl AsRef<[u8]> for Signature {
328 fn as_ref(&self) -> &[u8] {
329 &self.raw
330 }
331}
332
333impl Deref for Signature {
334 type Target = [u8];
335 fn deref(&self) -> &[u8] {
336 &self.raw
337 }
338}
339
340impl From<ed25519_consensus::Signature> for Signature {
341 fn from(value: ed25519_consensus::Signature) -> Self {
342 let raw = value.to_bytes();
343 Self {
344 raw,
345 signature: value,
346 }
347 }
348}
349
350impl Debug for Signature {
351 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
352 write!(f, "{}", hex(&self.raw))
353 }
354}
355
356impl Display for Signature {
357 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
358 write!(f, "{}", hex(&self.raw))
359 }
360}
361
362#[cfg(feature = "arbitrary")]
363impl arbitrary::Arbitrary<'_> for Signature {
364 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
365 use crate::Signer;
366 use commonware_math::algebra::Random;
367 use rand::{rngs::StdRng, SeedableRng};
368
369 let mut rand = StdRng::from_seed(u.arbitrary::<[u8; 32]>()?);
370 let private_key = PrivateKey::random(&mut rand);
371 let len = u.arbitrary::<usize>()? % 256;
372 let message = u
373 .arbitrary_iter()?
374 .take(len)
375 .collect::<Result<Vec<_>, _>>()?;
376
377 Ok(private_key.sign(&[], &message))
378 }
379}
380
381#[cfg(feature = "std")]
383pub struct Batch {
384 verifier: ed25519_consensus::batch::Verifier,
385}
386
387#[cfg(feature = "std")]
388impl BatchVerifier<PublicKey> for Batch {
389 fn new() -> Self {
390 Self {
391 verifier: ed25519_consensus::batch::Verifier::new(),
392 }
393 }
394
395 fn add(
396 &mut self,
397 namespace: &[u8],
398 message: &[u8],
399 public_key: &PublicKey,
400 signature: &Signature,
401 ) -> bool {
402 self.add_inner(Some(namespace), message, public_key, signature)
403 }
404
405 fn verify<R: CryptoRngCore>(self, rng: &mut R) -> bool {
406 self.verifier.verify(rng).is_ok()
407 }
408}
409
410#[cfg(feature = "std")]
411impl Batch {
412 #[inline(always)]
413 fn add_inner(
414 &mut self,
415 namespace: Option<&[u8]>,
416 message: &[u8],
417 public_key: &PublicKey,
418 signature: &Signature,
419 ) -> bool {
420 let payload = namespace
421 .map(|ns| Cow::Owned(union_unique(ns, message)))
422 .unwrap_or_else(|| Cow::Borrowed(message));
423 let item = ed25519_consensus::batch::Item::from((
424 public_key.key.into(),
425 signature.signature,
426 &payload,
427 ));
428 self.verifier.queue(item);
429 true
430 }
431}
432
433#[cfg(test)]
435mod tests {
436 use super::*;
437 use crate::ed25519;
438 use commonware_codec::{DecodeExt, Encode};
439 use commonware_math::algebra::Random;
440 use rand::rngs::OsRng;
441
442 fn test_sign_and_verify(
443 private_key: PrivateKey,
444 public_key: PublicKey,
445 message: &[u8],
446 signature: Signature,
447 ) {
448 let computed_signature = private_key.sign_inner(None, message);
449 assert_eq!(computed_signature, signature);
450 assert!(public_key.verify_inner(None, message, &computed_signature));
451 }
452
453 fn parse_private_key(private_key: &str) -> PrivateKey {
454 PrivateKey::decode(
455 commonware_utils::from_hex_formatted(private_key)
456 .unwrap()
457 .as_ref(),
458 )
459 .unwrap()
460 }
461
462 fn parse_public_key(public_key: &str) -> PublicKey {
463 PublicKey::decode(
464 commonware_utils::from_hex_formatted(public_key)
465 .unwrap()
466 .as_ref(),
467 )
468 .unwrap()
469 }
470
471 fn parse_signature(signature: &str) -> Signature {
472 Signature::decode(
473 commonware_utils::from_hex_formatted(signature)
474 .unwrap()
475 .as_ref(),
476 )
477 .unwrap()
478 }
479
480 fn vector_1() -> (PrivateKey, PublicKey, Vec<u8>, Signature) {
481 (
482 parse_private_key(
484 "
485 9d61b19deffd5a60ba844af492ec2cc4
486 4449c5697b326919703bac031cae7f60
487 ",
488 ),
489 parse_public_key(
491 "
492 d75a980182b10ab7d54bfed3c964073a
493 0ee172f3daa62325af021a68f707511a
494 ",
495 ),
496 b"".to_vec(),
498 parse_signature(
500 "
501 e5564300c360ac729086e2cc806e828a
502 84877f1eb8e5d974d873e06522490155
503 5fb8821590a33bacc61e39701cf9b46b
504 d25bf5f0595bbe24655141438e7a100b
505 ",
506 ),
507 )
508 }
509
510 fn vector_2() -> (PrivateKey, PublicKey, Vec<u8>, Signature) {
511 (
512 parse_private_key(
514 "
515 4ccd089b28ff96da9db6c346ec114e0f
516 5b8a319f35aba624da8cf6ed4fb8a6fb
517 ",
518 ),
519 parse_public_key(
521 "
522 3d4017c3e843895a92b70aa74d1b7ebc
523 9c982ccf2ec4968cc0cd55f12af4660c
524 ",
525 ),
526 [0x72].to_vec(),
528 parse_signature(
530 "
531 92a009a9f0d4cab8720e820b5f642540
532 a2b27b5416503f8fb3762223ebdb69da
533 085ac1e43e15996e458f3613d0f11d8c
534 387b2eaeb4302aeeb00d291612bb0c00
535 ",
536 ),
537 )
538 }
539
540 #[test]
541 fn test_codec_private_key() {
542 let private_key = parse_private_key(
543 "
544 9d61b19deffd5a60ba844af492ec2cc4
545 4449c5697b326919703bac031cae7f60
546 ",
547 );
548 let encoded = private_key.encode();
549 assert_eq!(encoded.len(), PRIVATE_KEY_LENGTH);
550 let decoded = PrivateKey::decode(encoded).unwrap();
551 assert_eq!(private_key, decoded);
552 }
553
554 #[test]
555 fn test_codec_public_key() {
556 let public_key = parse_public_key(
557 "
558 d75a980182b10ab7d54bfed3c964073a
559 0ee172f3daa62325af021a68f707511a
560 ",
561 );
562 let encoded = public_key.encode();
563 assert_eq!(encoded.len(), PUBLIC_KEY_LENGTH);
564 let decoded = PublicKey::decode(encoded).unwrap();
565 assert_eq!(public_key, decoded);
566 }
567
568 #[test]
569 fn test_codec_signature() {
570 let signature = parse_signature(
571 "
572 e5564300c360ac729086e2cc806e828a
573 84877f1eb8e5d974d873e06522490155
574 5fb8821590a33bacc61e39701cf9b46b
575 d25bf5f0595bbe24655141438e7a100b
576 ",
577 );
578 let encoded = signature.encode();
579 assert_eq!(encoded.len(), SIGNATURE_LENGTH);
580 let decoded = Signature::decode(encoded).unwrap();
581 assert_eq!(signature, decoded);
582 }
583
584 #[test]
585 fn rfc8032_test_vector_1() {
586 let (private_key, public_key, message, signature) = vector_1();
587 test_sign_and_verify(private_key, public_key, &message, signature)
588 }
589
590 #[test]
592 #[should_panic]
593 fn bad_signature() {
594 let (private_key, public_key, message, _) = vector_1();
595 let private_key_2 = PrivateKey::random(&mut OsRng);
596 let bad_signature = private_key_2.sign_inner(None, message.as_ref());
597 test_sign_and_verify(private_key, public_key, &message, bad_signature);
598 }
599
600 #[test]
602 #[should_panic]
603 fn different_message() {
604 let (private_key, public_key, _, signature) = vector_1();
605 let different_message = b"this is a different message".to_vec();
606 test_sign_and_verify(private_key, public_key, &different_message, signature);
607 }
608
609 #[test]
610 fn rfc8032_test_vector_2() {
611 let (private_key, public_key, message, signature) = vector_2();
612 test_sign_and_verify(private_key, public_key, &message, signature)
613 }
614
615 #[test]
616 fn rfc8032_test_vector_3() {
617 let private_key = parse_private_key(
618 "
619 c5aa8df43f9f837bedb7442f31dcb7b1
620 66d38535076f094b85ce3a2e0b4458f7
621 ",
622 );
623 let public_key = parse_public_key(
624 "
625 fc51cd8e6218a1a38da47ed00230f058
626 0816ed13ba3303ac5deb911548908025
627 ",
628 );
629 let message = hex!("0xaf82");
630 let signature = parse_signature(
631 "
632 6291d657deec24024827e69c3abe01a3
633 0ce548a284743a445e3680d7db5ac3ac
634 18ff9b538d16f290ae67f760984dc659
635 4a7c15e9716ed28dc027beceea1ec40a
636 ",
637 );
638 test_sign_and_verify(private_key, public_key, &message, signature)
639 }
640
641 #[test]
642 fn rfc8032_test_vector_1024() {
643 let private_key = parse_private_key(
644 "
645 f5e5767cf153319517630f226876b86c
646 8160cc583bc013744c6bf255f5cc0ee5
647 ",
648 );
649 let public_key = parse_public_key(
650 "
651 278117fc144c72340f67d0f2316e8386
652 ceffbf2b2428c9c51fef7c597f1d426e
653 ",
654 );
655 let message = commonware_utils::from_hex_formatted(
656 "
657 08b8b2b733424243760fe426a4b54908
658 632110a66c2f6591eabd3345e3e4eb98
659 fa6e264bf09efe12ee50f8f54e9f77b1
660 e355f6c50544e23fb1433ddf73be84d8
661 79de7c0046dc4996d9e773f4bc9efe57
662 38829adb26c81b37c93a1b270b20329d
663 658675fc6ea534e0810a4432826bf58c
664 941efb65d57a338bbd2e26640f89ffbc
665 1a858efcb8550ee3a5e1998bd177e93a
666 7363c344fe6b199ee5d02e82d522c4fe
667 ba15452f80288a821a579116ec6dad2b
668 3b310da903401aa62100ab5d1a36553e
669 06203b33890cc9b832f79ef80560ccb9
670 a39ce767967ed628c6ad573cb116dbef
671 efd75499da96bd68a8a97b928a8bbc10
672 3b6621fcde2beca1231d206be6cd9ec7
673 aff6f6c94fcd7204ed3455c68c83f4a4
674 1da4af2b74ef5c53f1d8ac70bdcb7ed1
675 85ce81bd84359d44254d95629e9855a9
676 4a7c1958d1f8ada5d0532ed8a5aa3fb2
677 d17ba70eb6248e594e1a2297acbbb39d
678 502f1a8c6eb6f1ce22b3de1a1f40cc24
679 554119a831a9aad6079cad88425de6bd
680 e1a9187ebb6092cf67bf2b13fd65f270
681 88d78b7e883c8759d2c4f5c65adb7553
682 878ad575f9fad878e80a0c9ba63bcbcc
683 2732e69485bbc9c90bfbd62481d9089b
684 eccf80cfe2df16a2cf65bd92dd597b07
685 07e0917af48bbb75fed413d238f5555a
686 7a569d80c3414a8d0859dc65a46128ba
687 b27af87a71314f318c782b23ebfe808b
688 82b0ce26401d2e22f04d83d1255dc51a
689 ddd3b75a2b1ae0784504df543af8969b
690 e3ea7082ff7fc9888c144da2af58429e
691 c96031dbcad3dad9af0dcbaaaf268cb8
692 fcffead94f3c7ca495e056a9b47acdb7
693 51fb73e666c6c655ade8297297d07ad1
694 ba5e43f1bca32301651339e22904cc8c
695 42f58c30c04aafdb038dda0847dd988d
696 cda6f3bfd15c4b4c4525004aa06eeff8
697 ca61783aacec57fb3d1f92b0fe2fd1a8
698 5f6724517b65e614ad6808d6f6ee34df
699 f7310fdc82aebfd904b01e1dc54b2927
700 094b2db68d6f903b68401adebf5a7e08
701 d78ff4ef5d63653a65040cf9bfd4aca7
702 984a74d37145986780fc0b16ac451649
703 de6188a7dbdf191f64b5fc5e2ab47b57
704 f7f7276cd419c17a3ca8e1b939ae49e4
705 88acba6b965610b5480109c8b17b80e1
706 b7b750dfc7598d5d5011fd2dcc5600a3
707 2ef5b52a1ecc820e308aa342721aac09
708 43bf6686b64b2579376504ccc493d97e
709 6aed3fb0f9cd71a43dd497f01f17c0e2
710 cb3797aa2a2f256656168e6c496afc5f
711 b93246f6b1116398a346f1a641f3b041
712 e989f7914f90cc2c7fff357876e506b5
713 0d334ba77c225bc307ba537152f3f161
714 0e4eafe595f6d9d90d11faa933a15ef1
715 369546868a7f3a45a96768d40fd9d034
716 12c091c6315cf4fde7cb68606937380d
717 b2eaaa707b4c4185c32eddcdd306705e
718 4dc1ffc872eeee475a64dfac86aba41c
719 0618983f8741c5ef68d3a101e8a3b8ca
720 c60c905c15fc910840b94c00a0b9d0
721 ",
722 )
723 .unwrap();
724 let signature = parse_signature(
725 "
726 0aab4c900501b3e24d7cdf4663326a3a
727 87df5e4843b2cbdb67cbf6e460fec350
728 aa5371b1508f9f4528ecea23c436d94b
729 5e8fcd4f681e30a6ac00a9704a188a03
730 ",
731 );
732 test_sign_and_verify(private_key, public_key, &message, signature)
733 }
734
735 #[test]
736 fn rfc8032_test_vector_sha() {
737 let private_key = commonware_utils::from_hex_formatted(
738 "
739 833fe62409237b9d62ec77587520911e
740 9a759cec1d19755b7da901b96dca3d42
741 ",
742 )
743 .unwrap();
744 let public_key = commonware_utils::from_hex_formatted(
745 "
746 ec172b93ad5e563bf4932c70e1245034
747 c35467ef2efd4d64ebf819683467e2bf
748 ",
749 )
750 .unwrap();
751 let message = commonware_utils::from_hex_formatted(
752 "
753 ddaf35a193617abacc417349ae204131
754 12e6fa4e89a97ea20a9eeee64b55d39a
755 2192992a274fc1a836ba3c23a3feebbd
756 454d4423643ce80e2a9ac94fa54ca49f
757 ",
758 )
759 .unwrap();
760 let signature = commonware_utils::from_hex_formatted(
761 "
762 dc2a4459e7369633a52b1bf277839a00
763 201009a3efbf3ecb69bea2186c26b589
764 09351fc9ac90b3ecfdfbc7c66431e030
765 3dca179c138ac17ad9bef1177331a704
766 ",
767 )
768 .unwrap();
769 test_sign_and_verify(
770 PrivateKey::decode(private_key.as_ref()).unwrap(),
771 PublicKey::decode(public_key.as_ref()).unwrap(),
772 &message,
773 Signature::decode(signature.as_ref()).unwrap(),
774 )
775 }
776
777 #[test]
778 fn batch_verify_valid() {
779 let v1 = vector_1();
780 let v2 = vector_2();
781 let mut batch = ed25519::Batch::new();
782 assert!(batch.add_inner(None, &v1.2, &v1.1, &v1.3));
783 assert!(batch.add_inner(None, &v2.2, &v2.1, &v2.3));
784 assert!(batch.verify(&mut rand::thread_rng()));
785 }
786
787 #[test]
788 fn batch_verify_invalid() {
789 let v1 = vector_1();
790 let v2 = vector_2();
791 let mut bad_signature = v2.3.to_vec();
792 bad_signature[3] = 0xff;
793
794 let mut batch = Batch::new();
795 assert!(batch.add_inner(None, &v1.2, &v1.1, &v1.3));
796 assert!(batch.add_inner(
797 None,
798 &v2.2,
799 &v2.1,
800 &Signature::decode(bad_signature.as_ref()).unwrap()
801 ));
802 assert!(!batch.verify(&mut rand::thread_rng()));
803 }
804
805 #[test]
806 fn test_zero_signature_fails() {
807 let (_, public_key, message, _) = vector_1();
808 let zero_sig = Signature::decode(vec![0u8; Signature::SIZE].as_ref()).unwrap();
809 assert!(!public_key.verify_inner(None, &message, &zero_sig));
810 }
811
812 #[test]
813 fn test_high_s_fails() {
814 let (_, public_key, message, signature) = vector_1();
815 let mut bad_signature = signature.to_vec();
816 bad_signature[63] |= 0x80; let bad_signature = Signature::decode(bad_signature.as_ref()).unwrap();
818 assert!(!public_key.verify_inner(None, &message, &bad_signature));
819 }
820
821 #[test]
822 fn test_invalid_r_fails() {
823 let (_, public_key, message, signature) = vector_1();
824 let mut bad_signature = signature.to_vec();
825 for b in bad_signature.iter_mut().take(32) {
826 *b = 0xff; }
828 let bad_signature = Signature::decode(bad_signature.as_ref()).unwrap();
829 assert!(!public_key.verify_inner(None, &message, &bad_signature));
830 }
831
832 #[cfg(feature = "arbitrary")]
833 mod conformance {
834 use super::*;
835 use commonware_codec::conformance::CodecConformance;
836
837 commonware_conformance::conformance_tests! {
838 CodecConformance<PrivateKey>,
839 CodecConformance<PublicKey>,
840 CodecConformance<Signature>,
841 }
842 }
843}