1use std::{
39 fmt,
40 io::{Cursor, Write},
41 str::FromStr,
42};
43
44use lexe_byte_array::ByteArray;
45use lexe_hex::hex::{self, FromHex};
46use lexe_serde::impl_serde_hexstr_or_bytes;
47use lexe_sha256::sha256;
48use lexe_std::const_utils;
49use ref_cast::RefCast;
50use ring::signature::KeyPair as _;
51use serde_core::{de::Deserialize, ser::Serialize};
52
53#[cfg(doc)]
54use crate::ed25519;
55use crate::rng::{Crng, RngExt};
56
57pub const SECRET_KEY_LEN: usize = 32;
58pub const PUBLIC_KEY_LEN: usize = 32;
59pub const SIGNATURE_LEN: usize = 64;
60
61pub const SIGNED_STRUCT_OVERHEAD: usize = PUBLIC_KEY_LEN + SIGNATURE_LEN;
64
65pub struct KeyPair {
73 key_pair: ring::signature::Ed25519KeyPair,
75
76 seed: [u8; 32],
80}
81
82#[derive(Copy, Clone, Eq, Hash, PartialEq, RefCast)]
87#[repr(transparent)]
88pub struct PublicKey([u8; 32]);
89
90impl_serde_hexstr_or_bytes!(PublicKey);
91
92#[derive(Copy, Clone, Eq, PartialEq, RefCast)]
94#[repr(transparent)]
95pub struct Signature([u8; 64]);
96
97#[derive(Debug, Eq, PartialEq)]
100#[must_use]
101pub struct Signed<T: Signable> {
102 signer: PublicKey,
103 sig: Signature,
104 inner: T,
105}
106
107#[derive(Debug)]
108pub enum Error {
109 InvalidPkLength,
110 UnexpectedAlgorithm,
111 KeyDeserializeError,
112 PublicKeyMismatch,
113 InvalidSignature,
114 BcsDeserialize,
115 SignedTooShort,
116 UnexpectedSigner,
117}
118
119#[derive(Debug)]
120pub struct InvalidSignature;
121
122pub trait Signable {
129 const DOMAIN_SEPARATOR: [u8; 32];
132}
133
134impl<T: Signable> Signable for &T {
136 const DOMAIN_SEPARATOR: [u8; 32] = T::DOMAIN_SEPARATOR;
137}
138
139pub mod verify {
143 use super::*;
144
145 pub fn signed_struct_by_signer<'msg, T: Signable + Deserialize<'msg>>(
148 signer: &PublicKey,
149 serialized: &'msg [u8],
150 ) -> Result<Signed<T>, Error> {
151 let accept_only_signer = |s| s == signer;
152 signed_struct_with_policy(accept_only_signer, serialized)
153 }
154
155 pub fn signed_struct_by_any_signer<
158 'msg,
159 T: Signable + Deserialize<'msg>,
160 >(
161 serialized: &'msg [u8],
162 ) -> Result<Signed<T>, Error> {
163 signed_struct_with_policy(accept_any_signer, serialized)
164 }
165
166 pub fn accept_any_signer(_: &PublicKey) -> bool {
169 true
170 }
171
172 pub fn signed_struct_with_policy<'msg, T, F>(
180 is_expected_signer: F,
181 serialized: &'msg [u8],
182 ) -> Result<Signed<T>, Error>
183 where
184 T: Signable + Deserialize<'msg>,
185 F: FnOnce(&'msg PublicKey) -> bool,
186 {
187 fn deserialize_signed_struct(
191 serialized: &[u8],
192 ) -> Result<(&PublicKey, &Signature, &[u8]), Error> {
193 if serialized.len() < SIGNED_STRUCT_OVERHEAD {
194 return Err(Error::SignedTooShort);
195 }
196
197 let (signer, serialized) = serialized
199 .split_first_chunk::<PUBLIC_KEY_LEN>()
200 .expect("serialized.len() checked above");
201 let signer = PublicKey::from_ref(signer);
202
203 let (sig, ser_struct) = serialized
205 .split_first_chunk::<SIGNATURE_LEN>()
206 .expect("serialized.len() checked above");
207 let sig = Signature::from_ref(sig);
208
209 Ok((signer, sig, ser_struct))
210 }
211
212 fn verify_signed_struct_inner(
213 signer: &PublicKey,
214 sig: &Signature,
215 ser_struct: &[u8],
216 domain_separator: &[u8; 32],
217 ) -> Result<(), InvalidSignature> {
218 let msg =
223 sha256::digest_many(&[domain_separator.as_slice(), ser_struct]);
224 signed_bytes_by_signer(signer, msg.as_slice(), sig)
225 }
226
227 let (signer, sig, ser_struct) = deserialize_signed_struct(serialized)?;
228
229 if !is_expected_signer(signer) {
231 return Err(Error::UnexpectedSigner);
232 }
233
234 verify_signed_struct_inner(
237 signer,
238 sig,
239 ser_struct,
240 &T::DOMAIN_SEPARATOR,
241 )
242 .map_err(|_| Error::InvalidSignature)?;
243
244 let inner: T =
246 bcs::from_bytes(ser_struct).map_err(|_| Error::BcsDeserialize)?;
247
248 Ok(Signed {
251 signer: *signer,
252 sig: *sig,
253 inner,
254 })
255 }
256
257 pub fn signed_bytes_by_signer(
259 signer: &PublicKey,
260 msg: &[u8],
261 sig: &Signature,
262 ) -> Result<(), InvalidSignature> {
263 ring::signature::UnparsedPublicKey::new(
264 &ring::signature::ED25519,
265 signer.as_slice(),
266 )
267 .verify(msg, sig.as_slice())
268 .map_err(|_| InvalidSignature)
269 }
270}
271
272impl KeyPair {
275 pub fn from_seed(seed: &[u8; 32]) -> Self {
279 let key_pair = ring::signature::Ed25519KeyPair::from_seed_unchecked(
280 seed,
281 )
282 .expect("This should never fail, as the seed is exactly 32 bytes");
283 Self {
284 seed: *seed,
285 key_pair,
286 }
287 }
288
289 pub fn from_seed_owned(seed: [u8; 32]) -> Self {
290 let key_pair = ring::signature::Ed25519KeyPair::from_seed_unchecked(
291 &seed,
292 )
293 .expect("This should never fail, as the seed is exactly 32 bytes");
294 Self { seed, key_pair }
295 }
296
297 pub fn from_seed_and_pubkey(
301 seed: &[u8; 32],
302 expected_pubkey: &[u8; 32],
303 ) -> Result<Self, Error> {
304 let key_pair =
305 ring::signature::Ed25519KeyPair::from_seed_and_public_key(
306 seed.as_slice(),
307 expected_pubkey.as_slice(),
308 )
309 .map_err(|_| Error::PublicKeyMismatch)?;
310 Ok(Self {
311 seed: *seed,
312 key_pair,
313 })
314 }
315
316 pub fn from_rng(mut rng: &mut dyn Crng) -> Self {
321 Self::from_seed_owned(rng.gen_bytes())
322 }
323
324 pub fn to_ring(&self) -> ring::signature::Ed25519KeyPair {
330 let pkcs8_bytes = self.serialize_pkcs8_der();
331 ring::signature::Ed25519KeyPair::from_pkcs8(&pkcs8_bytes).unwrap()
332 }
333
334 pub fn into_ring(self) -> ring::signature::Ed25519KeyPair {
338 self.key_pair
339 }
340
341 pub fn for_test(id: u64) -> Self {
345 const LEN: usize = std::mem::size_of::<u64>();
346
347 let mut seed = [0u8; 32];
348 seed[0..LEN].copy_from_slice(id.to_le_bytes().as_slice());
349 Self::from_seed(&seed)
350 }
351
352 pub fn serialize_pkcs8_der(&self) -> [u8; PKCS_LEN] {
354 serialize_keypair_pkcs8_der(&self.seed, self.public_key().as_array())
355 }
356
357 pub fn deserialize_pkcs8_der(bytes: &[u8]) -> Result<Self, Error> {
359 let (seed, expected_pubkey) = deserialize_keypair_pkcs8_der(bytes)
360 .ok_or(Error::KeyDeserializeError)?;
361 Self::from_seed_and_pubkey(seed, expected_pubkey)
362 }
363
364 pub fn secret_key(&self) -> &[u8; 32] {
366 &self.seed
367 }
368
369 pub fn public_key(&self) -> &PublicKey {
371 let pubkey_bytes =
372 <&[u8; 32]>::try_from(self.key_pair.public_key().as_ref()).unwrap();
373 PublicKey::from_ref(pubkey_bytes)
374 }
375
376 pub fn sign_raw(&self, msg: &[u8]) -> Signature {
378 let sig = self.key_pair.sign(msg);
379 Signature::try_from(sig.as_ref()).unwrap()
380 }
381
382 pub fn sign_struct<'a, T: Signable + Serialize>(
395 &self,
396 value: &'a T,
397 ) -> Result<(Vec<u8>, Signed<&'a T>), bcs::Error> {
398 let signer = self.public_key();
399
400 let struct_ser_len =
401 bcs::serialized_size(value)? + SIGNED_STRUCT_OVERHEAD;
402 let mut out = Vec::with_capacity(struct_ser_len);
403
404 out.extend_from_slice(signer.as_slice());
407 out.extend_from_slice([0u8; 64].as_slice());
408 bcs::serialize_into(&mut out, value)?;
409
410 let sig = self.sign_struct_inner(
413 &out[SIGNED_STRUCT_OVERHEAD..],
414 &T::DOMAIN_SEPARATOR,
415 );
416 out[PUBLIC_KEY_LEN..SIGNED_STRUCT_OVERHEAD]
417 .copy_from_slice(sig.as_slice());
418
419 Ok((
420 out,
421 Signed {
422 signer: *signer,
423 sig,
424 inner: value,
425 },
426 ))
427 }
428
429 fn sign_struct_inner(
432 &self,
433 serialized: &[u8],
434 domain_separator: &[u8],
435 ) -> Signature {
436 let msg = sha256::digest_many(&[domain_separator, serialized]);
437 self.sign_raw(msg.as_slice())
438 }
439}
440
441impl fmt::Debug for KeyPair {
442 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443 f.debug_struct("ed25519::KeyPair")
444 .field("sk", &"..")
445 .field("pk", &hex::display(self.public_key().as_slice()))
446 .finish()
447 }
448}
449
450impl FromHex for KeyPair {
451 fn from_hex(s: &str) -> Result<Self, hex::DecodeError> {
452 <[u8; 32]>::from_hex(s).map(Self::from_seed_owned)
453 }
454}
455
456impl FromStr for KeyPair {
457 type Err = hex::DecodeError;
458 #[inline]
459 fn from_str(s: &str) -> Result<Self, Self::Err> {
460 Self::from_hex(s)
461 }
462}
463
464lexe_byte_array::impl_byte_array!(PublicKey, 32);
467lexe_byte_array::impl_fromstr_fromhex!(PublicKey, 32);
468lexe_byte_array::impl_debug_display_as_hex!(PublicKey);
469
470impl PublicKey {
471 pub const fn new(bytes: [u8; 32]) -> Self {
472 Self(bytes)
475 }
476
477 pub const fn from_ref(bytes: &[u8; 32]) -> &Self {
478 const_utils::const_ref_cast(bytes)
479 }
480}
481
482impl TryFrom<&[u8]> for PublicKey {
483 type Error = Error;
484
485 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
486 let pk =
487 <[u8; 32]>::try_from(bytes).map_err(|_| Error::InvalidPkLength)?;
488 Ok(Self::new(pk))
489 }
490}
491
492impl Signature {
495 pub const fn new(sig: [u8; 64]) -> Self {
496 Self(sig)
497 }
498
499 pub const fn from_ref(sig: &[u8; 64]) -> &Self {
500 const_utils::const_ref_cast(sig)
501 }
502
503 pub const fn as_slice(&self) -> &[u8] {
504 self.0.as_slice()
505 }
506
507 pub const fn into_inner(self) -> [u8; 64] {
508 self.0
509 }
510
511 pub const fn as_inner(&self) -> &[u8; 64] {
512 &self.0
513 }
514}
515
516impl AsRef<[u8]> for Signature {
517 fn as_ref(&self) -> &[u8] {
518 self.as_slice()
519 }
520}
521
522impl AsRef<[u8; 64]> for Signature {
523 fn as_ref(&self) -> &[u8; 64] {
524 self.as_inner()
525 }
526}
527
528impl TryFrom<&[u8]> for Signature {
529 type Error = Error;
530 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
531 <[u8; 64]>::try_from(value)
532 .map(Signature)
533 .map_err(|_| Error::InvalidSignature)
534 }
535}
536
537impl FromHex for Signature {
538 fn from_hex(s: &str) -> Result<Self, hex::DecodeError> {
539 <[u8; 64]>::from_hex(s).map(Self::new)
540 }
541}
542
543impl FromStr for Signature {
544 type Err = hex::DecodeError;
545 #[inline]
546 fn from_str(s: &str) -> Result<Self, Self::Err> {
547 Self::from_hex(s)
548 }
549}
550
551impl fmt::Display for Signature {
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553 write!(f, "{}", hex::display(self.as_slice()))
554 }
555}
556
557impl fmt::Debug for Signature {
558 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
559 f.debug_tuple("ed25519::Signature")
560 .field(&hex::display(self.as_slice()))
561 .finish()
562 }
563}
564
565impl<T: Signable> Signed<T> {
568 pub fn into_parts(self) -> (PublicKey, Signature, T) {
569 (self.signer, self.sig, self.inner)
570 }
571
572 pub fn inner(&self) -> &T {
573 &self.inner
574 }
575
576 pub fn signer(&self) -> &PublicKey {
577 &self.signer
578 }
579
580 pub fn signature(&self) -> &Signature {
581 &self.sig
582 }
583
584 pub fn as_ref(&self) -> Signed<&T> {
585 Signed {
586 signer: self.signer,
587 sig: self.sig,
588 inner: &self.inner,
589 }
590 }
591}
592
593impl<T: Signable + Serialize> Signed<T> {
594 pub fn serialize(&self) -> Result<Vec<u8>, bcs::Error> {
595 let len = bcs::serialized_size(&self.inner)? + SIGNED_STRUCT_OVERHEAD;
596 let mut out = Vec::with_capacity(len);
597 let mut writer = Cursor::new(&mut out);
598
599 writer.write_all(self.signer.as_slice()).unwrap();
602 writer.write_all(self.sig.as_slice()).unwrap();
603 bcs::serialize_into(&mut writer, &self.inner)?;
604
605 Ok(out)
606 }
607}
608
609impl<T: Signable + Clone> Signed<&T> {
610 pub fn cloned(&self) -> Signed<T> {
611 Signed {
612 signer: self.signer,
613 sig: self.sig,
614 inner: self.inner.clone(),
615 }
616 }
617}
618
619impl<T: Signable + Clone> Clone for Signed<T> {
620 fn clone(&self) -> Self {
621 Self {
622 signer: self.signer,
623 sig: self.sig,
624 inner: self.inner.clone(),
625 }
626 }
627}
628
629impl std::error::Error for Error {}
632
633impl fmt::Display for Error {
634 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635 let msg = match self {
636 Self::InvalidPkLength =>
637 "ed25519 public key must be exactly 32 bytes",
638 Self::UnexpectedAlgorithm =>
639 "the algorithm OID doesn't match the standard ed25519 OID",
640 Self::KeyDeserializeError =>
641 "failed deserializing PKCS#8-encoded key pair",
642 Self::PublicKeyMismatch =>
643 "derived public key doesn't match expected public key",
644 Self::InvalidSignature => "invalid signature",
645 Self::BcsDeserialize =>
646 "error deserializing inner struct to verify",
647 Self::SignedTooShort => "signed struct is too short",
648 Self::UnexpectedSigner =>
649 "message was signed with a different key pair than expected",
650 };
651 f.write_str(msg)
652 }
653}
654
655impl std::error::Error for InvalidSignature {}
658
659impl fmt::Display for InvalidSignature {
660 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
661 f.write_str("invalid signature")
662 }
663}
664
665#[cfg(any(test, feature = "test-utils"))]
666mod arbitrary_impls {
667 use proptest::{
668 arbitrary::{Arbitrary, any},
669 strategy::{BoxedStrategy, Strategy},
670 };
671
672 use super::*;
673
674 impl Arbitrary for KeyPair {
675 type Parameters = ();
676 type Strategy = BoxedStrategy<Self>;
677 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
678 any::<[u8; 32]>()
679 .prop_map(|seed| Self::from_seed(&seed))
680 .boxed()
681 }
682 }
683
684 impl Arbitrary for PublicKey {
685 type Parameters = ();
686 type Strategy = BoxedStrategy<Self>;
687 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
688 any::<[u8; 32]>().prop_map(Self::new).boxed()
689 }
690 }
691}
692
693const PKCS_TEMPLATE_PREFIX: &[u8] = &[
718 0x30, 0x51, 0x02, 0x01, 0x01, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70,
719 0x04, 0x22, 0x04, 0x20,
720];
721const PKCS_TEMPLATE_PREFIX_BAD: &[u8] = &[
722 0x30, 0x53, 0x02, 0x01, 0x01, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70,
723 0x04, 0x22, 0x04, 0x20,
724];
725const PKCS_TEMPLATE_MIDDLE_BAD: &[u8] = &[0xa1, 0x23, 0x03, 0x21, 0x00];
726const PKCS_TEMPLATE_MIDDLE: &[u8] = &[0x81, 0x21, 0x00];
727const PKCS_TEMPLATE_KEY_IDX: usize = 16;
728
729const PKCS_LEN: usize = PKCS_TEMPLATE_PREFIX.len()
732 + SECRET_KEY_LEN
733 + PKCS_TEMPLATE_MIDDLE.len()
734 + PUBLIC_KEY_LEN;
735const PKCS_LEN_BAD: usize = PKCS_TEMPLATE_PREFIX_BAD.len()
736 + SECRET_KEY_LEN
737 + PKCS_TEMPLATE_MIDDLE_BAD.len()
738 + PUBLIC_KEY_LEN;
739
740lexe_std::const_assert_usize_eq!(PKCS_LEN, 83);
742lexe_std::const_assert_usize_eq!(PKCS_LEN_BAD, 85);
743
744fn serialize_keypair_pkcs8_der(
750 secret_key: &[u8; 32],
751 public_key: &[u8; 32],
752) -> [u8; PKCS_LEN] {
753 let mut out = [0u8; PKCS_LEN];
754 let key_start_idx = PKCS_TEMPLATE_KEY_IDX;
755
756 let prefix = PKCS_TEMPLATE_PREFIX;
757 let middle = PKCS_TEMPLATE_MIDDLE;
758
759 let key_end_idx = key_start_idx + secret_key.len();
760 out[..key_start_idx].copy_from_slice(prefix);
761 out[key_start_idx..key_end_idx].copy_from_slice(secret_key);
762 out[key_end_idx..(key_end_idx + middle.len())].copy_from_slice(middle);
763 out[(key_end_idx + middle.len())..].copy_from_slice(public_key);
764
765 out
766}
767
768fn deserialize_keypair_pkcs8_der(
774 bytes: &[u8],
775) -> Option<(&[u8; 32], &[u8; 32])> {
776 let (seed, pubkey) = if bytes.len() == PKCS_LEN {
777 let seed_mid_pubkey = bytes.strip_prefix(PKCS_TEMPLATE_PREFIX)?;
778 let (seed, mid_pubkey) = seed_mid_pubkey.split_at(SECRET_KEY_LEN);
779 let pubkey = mid_pubkey.strip_prefix(PKCS_TEMPLATE_MIDDLE)?;
780 (seed, pubkey)
781 } else if bytes.len() == PKCS_LEN_BAD {
782 let seed_mid_pubkey = bytes.strip_prefix(PKCS_TEMPLATE_PREFIX_BAD)?;
784 let (seed, mid_pubkey) = seed_mid_pubkey.split_at(SECRET_KEY_LEN);
785 let pubkey = mid_pubkey.strip_prefix(PKCS_TEMPLATE_MIDDLE_BAD)?;
786 (seed, pubkey)
787 } else {
788 return None;
789 };
790
791 let seed = <&[u8; 32]>::try_from(seed).unwrap();
792 let pubkey = <&[u8; 32]>::try_from(pubkey).unwrap();
793
794 Some((seed, pubkey))
795}
796
797#[cfg(test)]
798mod test {
799 use lexe_std::array;
800 use proptest::{arbitrary::any, prop_assume, proptest, strategy::Strategy};
801 use proptest_derive::Arbitrary;
802 use serde::{Deserialize, Serialize};
803
804 use super::*;
805 use crate::rng::FastRng;
806
807 #[derive(Arbitrary, Serialize, Deserialize)]
808 struct SignableBytes(Vec<u8>);
809
810 impl Signable for SignableBytes {
811 const DOMAIN_SEPARATOR: [u8; 32] =
812 array::pad(*b"LEXE-REALM::SignableBytes");
813 }
814
815 impl fmt::Debug for SignableBytes {
816 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
817 f.debug_tuple("SignableBytes")
818 .field(&hex::display(&self.0))
819 .finish()
820 }
821 }
822
823 #[test]
824 fn test_serde_pkcs8_roundtrip() {
825 proptest!(|(seed in any::<[u8; 32]>())| {
826 let key_pair1 = KeyPair::from_seed(&seed);
827 let key_pair_bytes = key_pair1.serialize_pkcs8_der();
828 let key_pair2 =
829 KeyPair::deserialize_pkcs8_der(key_pair_bytes.as_slice())
830 .unwrap();
831
832 assert_eq!(key_pair1.secret_key(), key_pair2.secret_key());
833 assert_eq!(key_pair1.public_key(), key_pair2.public_key());
834 });
835 }
836
837 #[test]
838 fn test_pkcs8_der_snapshot() {
839 #[track_caller]
840 fn assert_pkcs8_roundtrip(hexstr: &str) {
841 let der = hex::decode(hexstr).unwrap();
842 let _ = KeyPair::deserialize_pkcs8_der(&der).unwrap();
843 }
844
845 assert_pkcs8_roundtrip(
847 "3053020101300506032b657004220420244ae26baa35db07ed4ea37908f111a8fa4cb81109f9897a133b8a8de6e800dca1230321007dc65033bee5975aab9bb06e1e514d29533173511446adc5a73a9540d2addbac",
848 );
849
850 assert_pkcs8_roundtrip(
852 "3051020101300506032b657004220420244ae26baa35db07ed4ea37908f111a8fa4cb81109f9897a133b8a8de6e800dc8121007dc65033bee5975aab9bb06e1e514d29533173511446adc5a73a9540d2addbac",
853 );
854 }
855
856 #[ignore]
860 #[test]
861 fn pkcs8_der_snapshot_data() {
862 let mut rng = FastRng::from_u64(202510211432);
863 let key = KeyPair::from_seed_owned(rng.gen_bytes());
864 println!("{}", hex::display(key.serialize_pkcs8_der().as_slice()));
865 }
866
867 #[test]
868 fn test_deserialize_pkcs8_different_lengths() {
869 for size in 0..=256 {
870 let bytes = vec![0x42_u8; size];
871 let _ = deserialize_keypair_pkcs8_der(&bytes);
872 }
873 }
874
875 #[test]
877 fn test_ed25519_test_vector() {
878 let sk: [u8; 32] = hex::decode_const(
879 b"c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7",
880 );
881 let pk: [u8; 32] = hex::decode_const(
882 b"fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025",
883 );
884 let msg: [u8; 2] = hex::decode_const(b"af82");
885 let sig: [u8; 64] = hex::decode_const(b"6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a");
886
887 let key_pair = KeyPair::from_seed(&sk);
888 let pubkey = key_pair.public_key();
889 assert_eq!(pubkey.as_array(), &pk);
890
891 let sig2 = key_pair.sign_raw(&msg);
892 assert_eq!(&sig, sig2.as_inner());
893
894 verify::signed_bytes_by_signer(pubkey, &msg, &sig2).unwrap();
895 }
896
897 #[test]
899 fn test_reject_truncated_sig() {
900 proptest!(|(
901 key_pair in any::<KeyPair>(),
902 msg in any::<SignableBytes>()
903 )| {
904 let pubkey = key_pair.public_key();
905
906 let (sig, signed) = key_pair.sign_struct(&msg).unwrap();
907 let sig2 = signed.serialize().unwrap();
908 assert_eq!(&sig, &sig2);
909
910 let _ = verify::signed_struct_by_signer::<SignableBytes>(pubkey, &sig)
911 .unwrap();
912
913 for trunc_len in 0..SIGNED_STRUCT_OVERHEAD {
914 verify::signed_struct_by_signer::<SignableBytes>(pubkey, &sig[..trunc_len])
915 .unwrap_err();
916 verify::signed_struct_by_signer::<SignableBytes>(pubkey, &sig[(trunc_len+1)..])
917 .unwrap_err();
918 }
919 });
920 }
921
922 #[test]
925 fn test_reject_pad_sig() {
926 let cfg = proptest::test_runner::Config::with_cases(50);
927 proptest!(cfg, |(
928 key_pair in any::<KeyPair>(),
929 msg in any::<SignableBytes>(),
930 padding in any::<Vec<u8>>(),
931 )| {
932 prop_assume!(!padding.is_empty());
933
934 let pubkey = key_pair.public_key();
935
936 let (sig, signed) = key_pair.sign_struct(&msg).unwrap();
937 let sig2 = signed.serialize().unwrap();
938 assert_eq!(&sig, &sig2);
939
940 let _ = verify::signed_struct_by_signer::<SignableBytes>(pubkey, &sig)
941 .unwrap();
942
943 let mut sig2: Vec<u8> = Vec::with_capacity(sig.len() + padding.len());
944
945 for idx in 0..=sig.len() {
946 let (left, right) = sig.split_at(idx);
947
948 sig2.clear();
951 sig2.extend_from_slice(left);
952 sig2.extend_from_slice(&padding);
953 sig2.extend_from_slice(right);
954
955 verify::signed_struct_by_signer::<SignableBytes>(pubkey, &sig2)
956 .unwrap_err();
957 }
958 });
959 }
960
961 #[test]
964 fn test_reject_modified_sig() {
965 let arb_mutation = any::<Vec<u8>>()
966 .prop_filter("can't be empty or all zeroes", |m| {
967 !m.is_empty() && !m.iter().all(|x| x == &0u8)
968 });
969
970 proptest!(|(
971 key_pair in any::<KeyPair>(),
972 msg in any::<SignableBytes>(),
973 mut_offset in any::<usize>(),
974 mut mutation in arb_mutation,
975 )| {
976 let pubkey = key_pair.public_key();
977
978 let (mut sig, signed) = key_pair.sign_struct(&msg).unwrap();
979 let sig2 = signed.serialize().unwrap();
980 assert_eq!(&sig, &sig2);
981
982 mutation.truncate(sig.len());
983 prop_assume!(!mutation.is_empty() && !mutation.iter().all(|x| x == &0));
984
985 let _ = verify::signed_struct_by_signer::<SignableBytes>(pubkey, &sig)
986 .unwrap();
987
988 for (idx_mut, m) in mutation.into_iter().enumerate() {
991 let idx_sig = idx_mut.wrapping_add(mut_offset) % sig.len();
992 sig[idx_sig] ^= m;
993 }
994
995 verify::signed_struct_by_signer::<SignableBytes>(pubkey, &sig).unwrap_err();
996 });
997 }
998
999 #[test]
1000 fn test_sign_verify() {
1001 proptest!(|(key_pair in any::<KeyPair>(), msg in any::<Vec<u8>>())| {
1002 let pubkey = key_pair.public_key();
1003
1004 let sig = key_pair.sign_raw(&msg);
1005 verify::signed_bytes_by_signer(pubkey, &msg, &sig).unwrap();
1006 });
1007 }
1008
1009 #[test]
1010 fn test_sign_verify_struct() {
1011 #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
1012 struct Foo(u32);
1013
1014 impl Signable for Foo {
1015 const DOMAIN_SEPARATOR: [u8; 32] = array::pad(*b"LEXE-REALM::Foo");
1016 }
1017
1018 #[derive(Debug, Serialize, Deserialize)]
1019 struct Bar(u32);
1020
1021 impl Signable for Bar {
1022 const DOMAIN_SEPARATOR: [u8; 32] = array::pad(*b"LEXE-REALM::Bar");
1023 }
1024
1025 fn arb_foo() -> impl Strategy<Value = Foo> {
1026 any::<u32>().prop_map(Foo)
1027 }
1028
1029 proptest!(|(key_pair in any::<KeyPair>(), foo in arb_foo())| {
1030 let signer = key_pair.public_key();
1031 let (sig, signed) =
1032 key_pair.sign_struct::<Foo>(&foo).unwrap();
1033 let sig2 = signed.serialize().unwrap();
1034 assert_eq!(&sig, &sig2);
1035
1036 let signed2 =
1037 verify::signed_struct_by_signer::<Foo>(signer, &sig).unwrap();
1038 assert_eq!(signed, signed2.as_ref());
1039
1040 verify::signed_struct_by_signer::<Bar>(signer, &sig).unwrap_err();
1044 });
1045 }
1046}