commonware_cryptography/ed25519/
scheme.rs

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/// Ed25519 Private Key.
28#[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/// Ed25519 Public Key.
165#[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/// Ed25519 Signature.
277#[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/// Ed25519 Batch Verifier.
382#[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/// Test vectors sourced from https://datatracker.ietf.org/doc/html/rfc8032#section-7.1.
434#[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            // secret key
483            parse_private_key(
484                "
485                9d61b19deffd5a60ba844af492ec2cc4
486                4449c5697b326919703bac031cae7f60
487                ",
488            ),
489            // public key
490            parse_public_key(
491                "
492                d75a980182b10ab7d54bfed3c964073a
493                0ee172f3daa62325af021a68f707511a
494                ",
495            ),
496            // message
497            b"".to_vec(),
498            // signature
499            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            // secret key
513            parse_private_key(
514                "
515                4ccd089b28ff96da9db6c346ec114e0f
516                5b8a319f35aba624da8cf6ed4fb8a6fb
517                ",
518            ),
519            // public key
520            parse_public_key(
521                "
522                3d4017c3e843895a92b70aa74d1b7ebc
523                9c982ccf2ec4968cc0cd55f12af4660c
524                ",
525            ),
526            // message
527            [0x72].to_vec(),
528            // signature
529            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    // sanity check the test infra rejects bad signatures
591    #[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    // sanity check the test infra rejects non-matching messages
601    #[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; // make S non-canonical
817        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; // invalid R component
827        }
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}