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