1use crate::{Array, BatchScheme, Error, Scheme};
2use commonware_utils::{hex, union_unique, SizedSerialize};
3use ed25519_consensus::{self, VerificationKey};
4use rand::{CryptoRng, Rng, RngCore};
5use std::borrow::Cow;
6use std::fmt::{Debug, Display};
7use std::hash::{Hash, Hasher};
8use std::ops::Deref;
9
10const PRIVATE_KEY_LENGTH: usize = 32;
11const PUBLIC_KEY_LENGTH: usize = 32;
12const SIGNATURE_LENGTH: usize = 64;
13
14#[derive(Clone)]
16pub struct Ed25519 {
17 signer: ed25519_consensus::SigningKey,
18 verifier: ed25519_consensus::VerificationKey,
19}
20
21impl Scheme for Ed25519 {
22 type PrivateKey = PrivateKey;
23 type PublicKey = PublicKey;
24 type Signature = Signature;
25
26 fn new<R: CryptoRng + Rng>(r: &mut R) -> Self {
27 let signer = ed25519_consensus::SigningKey::new(r);
28 let verifier = signer.verification_key();
29 Self { signer, verifier }
30 }
31
32 fn from(private_key: PrivateKey) -> Option<Self> {
33 let signer = private_key.key;
34 let verifier = signer.verification_key();
35 Some(Self { signer, verifier })
36 }
37
38 fn private_key(&self) -> PrivateKey {
39 PrivateKey::from(self.signer.clone())
40 }
41
42 fn public_key(&self) -> PublicKey {
43 PublicKey::from(self.verifier)
44 }
45
46 fn sign(&mut self, namespace: Option<&[u8]>, message: &[u8]) -> Signature {
47 let sig = match namespace {
48 Some(namespace) => self.signer.sign(&union_unique(namespace, message)),
49 None => self.signer.sign(message),
50 };
51 Signature::from(sig)
52 }
53
54 fn verify(
55 namespace: Option<&[u8]>,
56 message: &[u8],
57 public_key: &Self::PublicKey,
58 signature: &Self::Signature,
59 ) -> bool {
60 match namespace {
61 Some(namespace) => {
62 let payload = union_unique(namespace, message);
63 public_key
64 .key
65 .verify(&signature.signature, &payload)
66 .is_ok()
67 }
68 None => public_key.key.verify(&signature.signature, message).is_ok(),
69 }
70 }
71}
72
73pub struct Ed25519Batch {
75 verifier: ed25519_consensus::batch::Verifier,
76}
77
78impl BatchScheme for Ed25519Batch {
79 type PublicKey = PublicKey;
80 type Signature = Signature;
81
82 fn new() -> Self {
83 Ed25519Batch {
84 verifier: ed25519_consensus::batch::Verifier::new(),
85 }
86 }
87
88 fn add(
89 &mut self,
90 namespace: Option<&[u8]>,
91 message: &[u8],
92 public_key: &Self::PublicKey,
93 signature: &Self::Signature,
94 ) -> bool {
95 let payload = match namespace {
96 Some(namespace) => Cow::Owned(union_unique(namespace, message)),
97 None => Cow::Borrowed(message),
98 };
99 let item = ed25519_consensus::batch::Item::from((
100 public_key.key.into(),
101 signature.signature,
102 &payload,
103 ));
104 self.verifier.queue(item);
105 true
106 }
107
108 fn verify<R: RngCore + CryptoRng>(self, rng: &mut R) -> bool {
109 self.verifier.verify(rng).is_ok()
110 }
111}
112
113#[derive(Clone)]
115pub struct PrivateKey {
116 raw: [u8; PRIVATE_KEY_LENGTH],
117 key: ed25519_consensus::SigningKey,
118}
119
120impl Array for PrivateKey {}
121
122impl SizedSerialize for PrivateKey {
123 const SERIALIZED_LEN: usize = PRIVATE_KEY_LENGTH;
124}
125
126impl Eq for PrivateKey {}
127
128impl Hash for PrivateKey {
129 fn hash<H: Hasher>(&self, state: &mut H) {
130 self.raw.hash(state);
131 }
132}
133
134impl PartialEq for PrivateKey {
135 fn eq(&self, other: &Self) -> bool {
136 self.raw == other.raw
137 }
138}
139
140impl Ord for PrivateKey {
141 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
142 self.raw.cmp(&other.raw)
143 }
144}
145
146impl PartialOrd for PrivateKey {
147 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
148 Some(self.cmp(other))
149 }
150}
151
152impl AsRef<[u8]> for PrivateKey {
153 fn as_ref(&self) -> &[u8] {
154 &self.raw
155 }
156}
157
158impl Deref for PrivateKey {
159 type Target = [u8];
160 fn deref(&self) -> &[u8] {
161 &self.raw
162 }
163}
164
165impl From<ed25519_consensus::SigningKey> for PrivateKey {
166 fn from(key: ed25519_consensus::SigningKey) -> Self {
167 let raw = key.to_bytes();
168 Self { raw, key }
169 }
170}
171
172impl TryFrom<&[u8]> for PrivateKey {
173 type Error = Error;
174 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
175 let raw: [u8; PRIVATE_KEY_LENGTH] = value
176 .try_into()
177 .map_err(|_| Error::InvalidPrivateKeyLength)?;
178 let key = ed25519_consensus::SigningKey::from(raw);
179 Ok(Self { raw, key })
180 }
181}
182
183impl TryFrom<&Vec<u8>> for PrivateKey {
184 type Error = Error;
185 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
186 Self::try_from(value.as_slice())
187 }
188}
189
190impl TryFrom<Vec<u8>> for PrivateKey {
191 type Error = Error;
192 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
193 Self::try_from(value.as_slice())
194 }
195}
196
197impl Debug for PrivateKey {
198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199 write!(f, "{}", hex(&self.raw))
200 }
201}
202
203impl Display for PrivateKey {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 write!(f, "{}", hex(&self.raw))
206 }
207}
208
209#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
211pub struct PublicKey {
212 raw: [u8; PUBLIC_KEY_LENGTH],
213 key: ed25519_consensus::VerificationKey,
214}
215
216impl Array for PublicKey {}
217
218impl SizedSerialize for PublicKey {
219 const SERIALIZED_LEN: usize = PUBLIC_KEY_LENGTH;
220}
221
222impl AsRef<[u8]> for PublicKey {
223 fn as_ref(&self) -> &[u8] {
224 &self.raw
225 }
226}
227
228impl Deref for PublicKey {
229 type Target = [u8];
230 fn deref(&self) -> &[u8] {
231 &self.raw
232 }
233}
234
235impl From<VerificationKey> for PublicKey {
236 fn from(key: VerificationKey) -> Self {
237 let raw = key.to_bytes();
238 Self { raw, key }
239 }
240}
241
242impl TryFrom<&[u8]> for PublicKey {
243 type Error = Error;
244 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
245 let raw: [u8; PUBLIC_KEY_LENGTH] = value
246 .try_into()
247 .map_err(|_| Error::InvalidPublicKeyLength)?;
248 let key = VerificationKey::try_from(value).map_err(|_| Error::InvalidPublicKey)?;
249 Ok(Self { raw, key })
250 }
251}
252
253impl TryFrom<&Vec<u8>> for PublicKey {
254 type Error = Error;
255 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
256 Self::try_from(value.as_slice())
257 }
258}
259
260impl TryFrom<Vec<u8>> for PublicKey {
261 type Error = Error;
262 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
263 Self::try_from(value.as_slice())
264 }
265}
266
267impl Debug for PublicKey {
268 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269 write!(f, "{}", hex(&self.raw))
270 }
271}
272
273impl Display for PublicKey {
274 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275 write!(f, "{}", hex(&self.raw))
276 }
277}
278
279#[derive(Clone, Eq, PartialEq)]
281pub struct Signature {
282 raw: [u8; SIGNATURE_LENGTH],
283 signature: ed25519_consensus::Signature,
284}
285
286impl Array for Signature {}
287
288impl SizedSerialize for Signature {
289 const SERIALIZED_LEN: usize = SIGNATURE_LENGTH;
290}
291
292impl Hash for Signature {
293 fn hash<H: Hasher>(&self, state: &mut H) {
294 self.raw.hash(state);
295 }
296}
297
298impl Ord for Signature {
299 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
300 self.raw.cmp(&other.raw)
301 }
302}
303
304impl PartialOrd for Signature {
305 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
306 Some(self.cmp(other))
307 }
308}
309
310impl AsRef<[u8]> for Signature {
311 fn as_ref(&self) -> &[u8] {
312 &self.raw
313 }
314}
315
316impl Deref for Signature {
317 type Target = [u8];
318 fn deref(&self) -> &[u8] {
319 &self.raw
320 }
321}
322
323impl From<ed25519_consensus::Signature> for Signature {
324 fn from(value: ed25519_consensus::Signature) -> Self {
325 let raw = value.to_bytes();
326 Self {
327 raw,
328 signature: value,
329 }
330 }
331}
332
333impl TryFrom<&[u8]> for Signature {
334 type Error = Error;
335 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
336 let raw: [u8; SIGNATURE_LENGTH] = value
337 .try_into()
338 .map_err(|_| Error::InvalidSignatureLength)?;
339 let signature = ed25519_consensus::Signature::from(raw);
340 Ok(Self { raw, signature })
341 }
342}
343
344impl TryFrom<&Vec<u8>> for Signature {
345 type Error = Error;
346 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
347 Self::try_from(value.as_slice())
348 }
349}
350
351impl TryFrom<Vec<u8>> for Signature {
352 type Error = Error;
353 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
354 Self::try_from(value.as_slice())
355 }
356}
357
358impl Debug for Signature {
359 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360 write!(f, "{}", hex(&self.raw))
361 }
362}
363
364impl Display for Signature {
365 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
366 write!(f, "{}", hex(&self.raw))
367 }
368}
369
370#[cfg(test)]
372mod tests {
373 use super::*;
374 use rand::rngs::OsRng;
375
376 fn test_sign_and_verify(
377 private_key: PrivateKey,
378 public_key: PublicKey,
379 message: &[u8],
380 signature: Signature,
381 ) {
382 let mut signer = <Ed25519 as Scheme>::from(private_key).unwrap();
383 let computed_signature = signer.sign(None, message);
384 assert_eq!(computed_signature, signature);
385 assert!(Ed25519::verify(
386 None,
387 message,
388 &PublicKey::try_from(public_key.to_vec()).unwrap(),
389 &computed_signature
390 ));
391 }
392
393 fn parse_private_key(private_key: &str) -> PrivateKey {
394 PrivateKey::try_from(commonware_utils::from_hex_formatted(private_key).unwrap()).unwrap()
395 }
396
397 fn parse_public_key(public_key: &str) -> PublicKey {
398 PublicKey::try_from(commonware_utils::from_hex_formatted(public_key).unwrap()).unwrap()
399 }
400
401 fn parse_signature(signature: &str) -> Signature {
402 Signature::try_from(commonware_utils::from_hex_formatted(signature).unwrap()).unwrap()
403 }
404
405 fn vector_1() -> (PrivateKey, PublicKey, Vec<u8>, Signature) {
406 (
407 parse_private_key(
409 "
410 9d61b19deffd5a60ba844af492ec2cc4
411 4449c5697b326919703bac031cae7f60
412 ",
413 ),
414 parse_public_key(
416 "
417 d75a980182b10ab7d54bfed3c964073a
418 0ee172f3daa62325af021a68f707511a
419 ",
420 ),
421 b"".to_vec(),
423 parse_signature(
425 "
426 e5564300c360ac729086e2cc806e828a
427 84877f1eb8e5d974d873e06522490155
428 5fb8821590a33bacc61e39701cf9b46b
429 d25bf5f0595bbe24655141438e7a100b
430 ",
431 ),
432 )
433 }
434
435 fn vector_2() -> (PrivateKey, PublicKey, Vec<u8>, Signature) {
436 (
437 parse_private_key(
439 "
440 4ccd089b28ff96da9db6c346ec114e0f
441 5b8a319f35aba624da8cf6ed4fb8a6fb
442 ",
443 ),
444 parse_public_key(
446 "
447 3d4017c3e843895a92b70aa74d1b7ebc
448 9c982ccf2ec4968cc0cd55f12af4660c
449 ",
450 ),
451 [0x72].to_vec(),
453 parse_signature(
455 "
456 92a009a9f0d4cab8720e820b5f642540
457 a2b27b5416503f8fb3762223ebdb69da
458 085ac1e43e15996e458f3613d0f11d8c
459 387b2eaeb4302aeeb00d291612bb0c00
460 ",
461 ),
462 )
463 }
464
465 #[test]
466 fn rfc8032_test_vector_1() {
467 let (private_key, public_key, message, signature) = vector_1();
468 test_sign_and_verify(private_key, public_key, &message, signature)
469 }
470
471 #[test]
473 #[should_panic]
474 fn bad_signature() {
475 let (private_key, public_key, message, _) = vector_1();
476 let mut signer = <Ed25519 as Scheme>::new(&mut OsRng);
477 let bad_signature = signer.sign(None, message.as_ref());
478 test_sign_and_verify(private_key, public_key, &message, bad_signature);
479 }
480
481 #[test]
483 #[should_panic]
484 fn different_message() {
485 let (private_key, public_key, _, signature) = vector_1();
486 let different_message = b"this is a different message".to_vec();
487 test_sign_and_verify(private_key, public_key, &different_message, signature);
488 }
489
490 #[test]
491 fn rfc8032_test_vector_2() {
492 let (private_key, public_key, message, signature) = vector_2();
493 test_sign_and_verify(private_key, public_key, &message, signature)
494 }
495
496 #[test]
497 fn rfc8032_test_vector_3() {
498 let private_key = parse_private_key(
499 "
500 c5aa8df43f9f837bedb7442f31dcb7b1
501 66d38535076f094b85ce3a2e0b4458f7
502 ",
503 );
504 let public_key = parse_public_key(
505 "
506 fc51cd8e6218a1a38da47ed00230f058
507 0816ed13ba3303ac5deb911548908025
508 ",
509 );
510 let message: [u8; 2] = [0xaf, 0x82];
511 let signature = parse_signature(
512 "
513 6291d657deec24024827e69c3abe01a3
514 0ce548a284743a445e3680d7db5ac3ac
515 18ff9b538d16f290ae67f760984dc659
516 4a7c15e9716ed28dc027beceea1ec40a
517 ",
518 );
519 test_sign_and_verify(private_key, public_key, &message, signature)
520 }
521
522 #[test]
523 fn rfc8032_test_vector_1024() {
524 let private_key = parse_private_key(
525 "
526 f5e5767cf153319517630f226876b86c
527 8160cc583bc013744c6bf255f5cc0ee5
528 ",
529 );
530 let public_key = parse_public_key(
531 "
532 278117fc144c72340f67d0f2316e8386
533 ceffbf2b2428c9c51fef7c597f1d426e
534 ",
535 );
536 let message = commonware_utils::from_hex_formatted(
537 "
538 08b8b2b733424243760fe426a4b54908
539 632110a66c2f6591eabd3345e3e4eb98
540 fa6e264bf09efe12ee50f8f54e9f77b1
541 e355f6c50544e23fb1433ddf73be84d8
542 79de7c0046dc4996d9e773f4bc9efe57
543 38829adb26c81b37c93a1b270b20329d
544 658675fc6ea534e0810a4432826bf58c
545 941efb65d57a338bbd2e26640f89ffbc
546 1a858efcb8550ee3a5e1998bd177e93a
547 7363c344fe6b199ee5d02e82d522c4fe
548 ba15452f80288a821a579116ec6dad2b
549 3b310da903401aa62100ab5d1a36553e
550 06203b33890cc9b832f79ef80560ccb9
551 a39ce767967ed628c6ad573cb116dbef
552 efd75499da96bd68a8a97b928a8bbc10
553 3b6621fcde2beca1231d206be6cd9ec7
554 aff6f6c94fcd7204ed3455c68c83f4a4
555 1da4af2b74ef5c53f1d8ac70bdcb7ed1
556 85ce81bd84359d44254d95629e9855a9
557 4a7c1958d1f8ada5d0532ed8a5aa3fb2
558 d17ba70eb6248e594e1a2297acbbb39d
559 502f1a8c6eb6f1ce22b3de1a1f40cc24
560 554119a831a9aad6079cad88425de6bd
561 e1a9187ebb6092cf67bf2b13fd65f270
562 88d78b7e883c8759d2c4f5c65adb7553
563 878ad575f9fad878e80a0c9ba63bcbcc
564 2732e69485bbc9c90bfbd62481d9089b
565 eccf80cfe2df16a2cf65bd92dd597b07
566 07e0917af48bbb75fed413d238f5555a
567 7a569d80c3414a8d0859dc65a46128ba
568 b27af87a71314f318c782b23ebfe808b
569 82b0ce26401d2e22f04d83d1255dc51a
570 ddd3b75a2b1ae0784504df543af8969b
571 e3ea7082ff7fc9888c144da2af58429e
572 c96031dbcad3dad9af0dcbaaaf268cb8
573 fcffead94f3c7ca495e056a9b47acdb7
574 51fb73e666c6c655ade8297297d07ad1
575 ba5e43f1bca32301651339e22904cc8c
576 42f58c30c04aafdb038dda0847dd988d
577 cda6f3bfd15c4b4c4525004aa06eeff8
578 ca61783aacec57fb3d1f92b0fe2fd1a8
579 5f6724517b65e614ad6808d6f6ee34df
580 f7310fdc82aebfd904b01e1dc54b2927
581 094b2db68d6f903b68401adebf5a7e08
582 d78ff4ef5d63653a65040cf9bfd4aca7
583 984a74d37145986780fc0b16ac451649
584 de6188a7dbdf191f64b5fc5e2ab47b57
585 f7f7276cd419c17a3ca8e1b939ae49e4
586 88acba6b965610b5480109c8b17b80e1
587 b7b750dfc7598d5d5011fd2dcc5600a3
588 2ef5b52a1ecc820e308aa342721aac09
589 43bf6686b64b2579376504ccc493d97e
590 6aed3fb0f9cd71a43dd497f01f17c0e2
591 cb3797aa2a2f256656168e6c496afc5f
592 b93246f6b1116398a346f1a641f3b041
593 e989f7914f90cc2c7fff357876e506b5
594 0d334ba77c225bc307ba537152f3f161
595 0e4eafe595f6d9d90d11faa933a15ef1
596 369546868a7f3a45a96768d40fd9d034
597 12c091c6315cf4fde7cb68606937380d
598 b2eaaa707b4c4185c32eddcdd306705e
599 4dc1ffc872eeee475a64dfac86aba41c
600 0618983f8741c5ef68d3a101e8a3b8ca
601 c60c905c15fc910840b94c00a0b9d0
602 ",
603 )
604 .unwrap();
605 let signature = parse_signature(
606 "
607 0aab4c900501b3e24d7cdf4663326a3a
608 87df5e4843b2cbdb67cbf6e460fec350
609 aa5371b1508f9f4528ecea23c436d94b
610 5e8fcd4f681e30a6ac00a9704a188a03
611 ",
612 );
613 test_sign_and_verify(private_key, public_key, &message, signature)
614 }
615
616 #[test]
617 fn rfc8032_test_vector_sha() {
618 let private_key = commonware_utils::from_hex_formatted(
619 "
620 833fe62409237b9d62ec77587520911e
621 9a759cec1d19755b7da901b96dca3d42
622 ",
623 )
624 .unwrap();
625 let public_key = commonware_utils::from_hex_formatted(
626 "
627 ec172b93ad5e563bf4932c70e1245034
628 c35467ef2efd4d64ebf819683467e2bf
629 ",
630 )
631 .unwrap();
632 let message = commonware_utils::from_hex_formatted(
633 "
634 ddaf35a193617abacc417349ae204131
635 12e6fa4e89a97ea20a9eeee64b55d39a
636 2192992a274fc1a836ba3c23a3feebbd
637 454d4423643ce80e2a9ac94fa54ca49f
638 ",
639 )
640 .unwrap();
641 let signature = commonware_utils::from_hex_formatted(
642 "
643 dc2a4459e7369633a52b1bf277839a00
644 201009a3efbf3ecb69bea2186c26b589
645 09351fc9ac90b3ecfdfbc7c66431e030
646 3dca179c138ac17ad9bef1177331a704
647 ",
648 )
649 .unwrap();
650 test_sign_and_verify(
651 PrivateKey::try_from(private_key).unwrap(),
652 PublicKey::try_from(public_key).unwrap(),
653 &message,
654 Signature::try_from(signature).unwrap(),
655 )
656 }
657
658 #[test]
659 fn batch_verify_valid() {
660 let v1 = vector_1();
661 let v2 = vector_2();
662 let mut batch = Ed25519Batch::new();
663 assert!(batch.add(None, &v1.2, &v1.1, &v1.3));
664 assert!(batch.add(None, &v2.2, &v2.1, &v2.3));
665 assert!(batch.verify(&mut rand::thread_rng()));
666 }
667
668 #[test]
669 fn batch_verify_invalid() {
670 let v1 = vector_1();
671 let v2 = vector_2();
672 let mut bad_signature = v2.3.to_vec();
673 bad_signature[3] = 0xff;
674
675 let mut batch = Ed25519Batch::new();
676 assert!(batch.add(None, &v1.2, &v1.1, &v1.3));
677 assert!(batch.add(
678 None,
679 &v2.2,
680 &v2.1,
681 &Signature::try_from(bad_signature).unwrap()
682 ));
683 assert!(!batch.verify(&mut rand::thread_rng()));
684 }
685}