1use core::marker::PhantomData;
21
22use crate::crypto::{
23 ByteArray, CryptoType, DeriveError, DeriveJunction, Pair as PairT, Public as PublicT,
24 PublicBytes, SecretStringError, Signature as SignatureT, SignatureBytes, UncheckedFrom,
25};
26
27use alloc::vec::Vec;
28
29#[cfg(feature = "bls-experimental")]
31pub mod ecdsa_bls377 {
32 use crate::{bls377, crypto::CryptoTypeId, ecdsa};
33 #[cfg(feature = "full_crypto")]
34 use crate::{
35 crypto::{Pair as PairT, UncheckedFrom},
36 Hasher,
37 };
38
39 pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecb7");
41
42 const PUBLIC_KEY_LEN: usize =
43 ecdsa::PUBLIC_KEY_SERIALIZED_SIZE + bls377::PUBLIC_KEY_SERIALIZED_SIZE;
44 const SIGNATURE_LEN: usize =
45 ecdsa::SIGNATURE_SERIALIZED_SIZE + bls377::SIGNATURE_SERIALIZED_SIZE;
46
47 #[doc(hidden)]
48 pub struct EcdsaBls377Tag(ecdsa::EcdsaTag, bls377::Bls377Tag);
49
50 impl super::PairedCryptoSubTagBound for EcdsaBls377Tag {}
51
52 pub type Pair =
54 super::Pair<ecdsa::Pair, bls377::Pair, PUBLIC_KEY_LEN, SIGNATURE_LEN, EcdsaBls377Tag>;
55
56 pub type Public = super::Public<PUBLIC_KEY_LEN, EcdsaBls377Tag>;
58
59 pub type Signature = super::Signature<SIGNATURE_LEN, EcdsaBls377Tag>;
61
62 impl super::CryptoType for Public {
63 type Pair = Pair;
64 }
65
66 impl super::CryptoType for Signature {
67 type Pair = Pair;
68 }
69
70 impl super::CryptoType for Pair {
71 type Pair = Pair;
72 }
73
74 #[cfg(feature = "full_crypto")]
75 impl Pair {
76 pub fn sign_with_hasher<H>(&self, message: &[u8]) -> Signature
82 where
83 H: Hasher,
84 H::Out: Into<[u8; 32]>,
85 {
86 let msg_hash = H::hash(message).into();
87
88 let mut raw: [u8; SIGNATURE_LEN] = [0u8; SIGNATURE_LEN];
89 raw[..ecdsa::SIGNATURE_SERIALIZED_SIZE]
90 .copy_from_slice(self.left.sign_prehashed(&msg_hash).as_ref());
91 raw[ecdsa::SIGNATURE_SERIALIZED_SIZE..]
92 .copy_from_slice(self.right.sign(message).as_ref());
93 <Self as PairT>::Signature::unchecked_from(raw)
94 }
95
96 pub fn verify_with_hasher<H>(sig: &Signature, message: &[u8], public: &Public) -> bool
102 where
103 H: Hasher,
104 H::Out: Into<[u8; 32]>,
105 {
106 let msg_hash = H::hash(message).into();
107
108 let Ok(left_pub) = public.0[..ecdsa::PUBLIC_KEY_SERIALIZED_SIZE].try_into() else {
109 return false
110 };
111 let Ok(left_sig) = sig.0[..ecdsa::SIGNATURE_SERIALIZED_SIZE].try_into() else {
112 return false
113 };
114 if !ecdsa::Pair::verify_prehashed(&left_sig, &msg_hash, &left_pub) {
115 return false
116 }
117
118 let Ok(right_pub) = public.0[ecdsa::PUBLIC_KEY_SERIALIZED_SIZE..].try_into() else {
119 return false
120 };
121 let Ok(right_sig) = sig.0[ecdsa::SIGNATURE_SERIALIZED_SIZE..].try_into() else {
122 return false
123 };
124 bls377::Pair::verify(&right_sig, message, &right_pub)
125 }
126 }
127}
128
129#[cfg(feature = "bls-experimental")]
131pub mod ecdsa_bls381 {
132 use crate::{bls381, crypto::CryptoTypeId, ecdsa};
133 #[cfg(feature = "full_crypto")]
134 use crate::{
135 crypto::{Pair as PairT, UncheckedFrom},
136 Hasher,
137 };
138
139 pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecb8");
141
142 const PUBLIC_KEY_LEN: usize =
143 ecdsa::PUBLIC_KEY_SERIALIZED_SIZE + bls381::PUBLIC_KEY_SERIALIZED_SIZE;
144 const SIGNATURE_LEN: usize =
145 ecdsa::SIGNATURE_SERIALIZED_SIZE + bls381::SIGNATURE_SERIALIZED_SIZE;
146
147 #[doc(hidden)]
148 pub struct EcdsaBls381Tag(ecdsa::EcdsaTag, bls381::Bls381Tag);
149
150 impl super::PairedCryptoSubTagBound for EcdsaBls381Tag {}
151
152 pub type Pair =
154 super::Pair<ecdsa::Pair, bls381::Pair, PUBLIC_KEY_LEN, SIGNATURE_LEN, EcdsaBls381Tag>;
155
156 pub type Public = super::Public<PUBLIC_KEY_LEN, EcdsaBls381Tag>;
158
159 pub type Signature = super::Signature<SIGNATURE_LEN, EcdsaBls381Tag>;
161
162 impl super::CryptoType for Public {
163 type Pair = Pair;
164 }
165
166 impl super::CryptoType for Signature {
167 type Pair = Pair;
168 }
169
170 impl super::CryptoType for Pair {
171 type Pair = Pair;
172 }
173
174 #[cfg(feature = "full_crypto")]
175 impl Pair {
176 pub fn sign_with_hasher<H>(&self, message: &[u8]) -> Signature
182 where
183 H: Hasher,
184 H::Out: Into<[u8; 32]>,
185 {
186 let msg_hash = H::hash(message).into();
187
188 let mut raw: [u8; SIGNATURE_LEN] = [0u8; SIGNATURE_LEN];
189 raw[..ecdsa::SIGNATURE_SERIALIZED_SIZE]
190 .copy_from_slice(self.left.sign_prehashed(&msg_hash).as_ref());
191 raw[ecdsa::SIGNATURE_SERIALIZED_SIZE..]
192 .copy_from_slice(self.right.sign(message).as_ref());
193 <Self as PairT>::Signature::unchecked_from(raw)
194 }
195
196 pub fn verify_with_hasher<H>(sig: &Signature, message: &[u8], public: &Public) -> bool
202 where
203 H: Hasher,
204 H::Out: Into<[u8; 32]>,
205 {
206 let msg_hash = H::hash(message).into();
207
208 let Ok(left_pub) = public.0[..ecdsa::PUBLIC_KEY_SERIALIZED_SIZE].try_into() else {
209 return false
210 };
211 let Ok(left_sig) = sig.0[..ecdsa::SIGNATURE_SERIALIZED_SIZE].try_into() else {
212 return false
213 };
214 if !ecdsa::Pair::verify_prehashed(&left_sig, &msg_hash, &left_pub) {
215 return false
216 }
217
218 let Ok(right_pub) = public.0[ecdsa::PUBLIC_KEY_SERIALIZED_SIZE..].try_into() else {
219 return false
220 };
221 let Ok(right_sig) = sig.0[ecdsa::SIGNATURE_SERIALIZED_SIZE..].try_into() else {
222 return false
223 };
224 bls381::Pair::verify(&right_sig, message, &right_pub)
225 }
226 }
227}
228
229const SECURE_SEED_LEN: usize = 32;
233
234type Seed = [u8; SECURE_SEED_LEN];
240
241#[doc(hidden)]
242pub trait PairedCryptoSubTagBound {}
243#[doc(hidden)]
244pub struct PairedCryptoTag;
245
246pub type Public<const LEFT_PLUS_RIGHT_LEN: usize, SubTag> =
248 PublicBytes<LEFT_PLUS_RIGHT_LEN, (PairedCryptoTag, SubTag)>;
249
250impl<
251 LeftPair: PairT,
252 RightPair: PairT,
253 const LEFT_PLUS_RIGHT_PUBLIC_LEN: usize,
254 const SIGNATURE_LEN: usize,
255 SubTag: PairedCryptoSubTagBound,
256 > From<Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN, SubTag>>
257 for Public<LEFT_PLUS_RIGHT_PUBLIC_LEN, SubTag>
258where
259 Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN, SubTag>:
260 PairT<Public = Public<LEFT_PLUS_RIGHT_PUBLIC_LEN, SubTag>>,
261{
262 fn from(
263 x: Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN, SubTag>,
264 ) -> Self {
265 x.public()
266 }
267}
268
269pub type Signature<const LEFT_PLUS_RIGHT_LEN: usize, SubTag> =
271 SignatureBytes<LEFT_PLUS_RIGHT_LEN, (PairedCryptoTag, SubTag)>;
272
273pub struct Pair<
275 LeftPair: PairT,
276 RightPair: PairT,
277 const PUBLIC_KEY_LEN: usize,
278 const SIGNATURE_LEN: usize,
279 SubTag,
280> {
281 left: LeftPair,
282 right: RightPair,
283 _phantom: PhantomData<fn() -> SubTag>,
284}
285
286impl<
287 LeftPair: PairT + Clone,
288 RightPair: PairT + Clone,
289 const PUBLIC_KEY_LEN: usize,
290 const SIGNATURE_LEN: usize,
291 SubTag,
292 > Clone for Pair<LeftPair, RightPair, PUBLIC_KEY_LEN, SIGNATURE_LEN, SubTag>
293{
294 fn clone(&self) -> Self {
295 Self { left: self.left.clone(), right: self.right.clone(), _phantom: PhantomData }
296 }
297}
298
299impl<
300 LeftPair: PairT,
301 RightPair: PairT,
302 const PUBLIC_KEY_LEN: usize,
303 const SIGNATURE_LEN: usize,
304 SubTag: PairedCryptoSubTagBound,
305 > PairT for Pair<LeftPair, RightPair, PUBLIC_KEY_LEN, SIGNATURE_LEN, SubTag>
306where
307 Pair<LeftPair, RightPair, PUBLIC_KEY_LEN, SIGNATURE_LEN, SubTag>: CryptoType,
308 Public<PUBLIC_KEY_LEN, SubTag>: PublicT,
309 Signature<SIGNATURE_LEN, SubTag>: SignatureT,
310 LeftPair::Seed: From<Seed> + Into<Seed>,
311 RightPair::Seed: From<Seed> + Into<Seed>,
312{
313 type Seed = Seed;
314 type Public = Public<PUBLIC_KEY_LEN, SubTag>;
315 type Signature = Signature<SIGNATURE_LEN, SubTag>;
316
317 fn from_seed_slice(seed_slice: &[u8]) -> Result<Self, SecretStringError> {
318 if seed_slice.len() != SECURE_SEED_LEN {
319 return Err(SecretStringError::InvalidSeedLength)
320 }
321 let left = LeftPair::from_seed_slice(&seed_slice)?;
322 let right = RightPair::from_seed_slice(&seed_slice)?;
323 Ok(Pair { left, right, _phantom: PhantomData })
324 }
325
326 fn derive<Iter: Iterator<Item = DeriveJunction>>(
331 &self,
332 path: Iter,
333 seed: Option<Self::Seed>,
334 ) -> Result<(Self, Option<Self::Seed>), DeriveError> {
335 let left_path: Vec<_> = path.collect();
336 let right_path: Vec<_> = left_path.clone();
337
338 let left = self.left.derive(left_path.into_iter(), seed.map(|s| s.into()))?;
339 let right = self.right.derive(right_path.into_iter(), seed.map(|s| s.into()))?;
340
341 let seed = match (left.1, right.1) {
342 (Some(l), Some(r)) if l.as_ref() == r.as_ref() => Some(l.into()),
343 _ => None,
344 };
345
346 Ok((Self { left: left.0, right: right.0, _phantom: PhantomData }, seed))
347 }
348
349 fn public(&self) -> Self::Public {
350 let mut raw = [0u8; PUBLIC_KEY_LEN];
351 let left_pub = self.left.public();
352 let right_pub = self.right.public();
353 raw[..LeftPair::Public::LEN].copy_from_slice(left_pub.as_ref());
354 raw[LeftPair::Public::LEN..].copy_from_slice(right_pub.as_ref());
355 Self::Public::unchecked_from(raw)
356 }
357
358 #[cfg(feature = "full_crypto")]
359 fn sign(&self, message: &[u8]) -> Self::Signature {
360 let mut raw: [u8; SIGNATURE_LEN] = [0u8; SIGNATURE_LEN];
361 raw[..LeftPair::Signature::LEN].copy_from_slice(self.left.sign(message).as_ref());
362 raw[LeftPair::Signature::LEN..].copy_from_slice(self.right.sign(message).as_ref());
363 Self::Signature::unchecked_from(raw)
364 }
365
366 fn verify<Msg: AsRef<[u8]>>(
367 sig: &Self::Signature,
368 message: Msg,
369 public: &Self::Public,
370 ) -> bool {
371 let Ok(left_pub) = public.0[..LeftPair::Public::LEN].try_into() else { return false };
372 let Ok(left_sig) = sig.0[0..LeftPair::Signature::LEN].try_into() else { return false };
373 if !LeftPair::verify(&left_sig, message.as_ref(), &left_pub) {
374 return false
375 }
376
377 let Ok(right_pub) = public.0[LeftPair::Public::LEN..].try_into() else { return false };
378 let Ok(right_sig) = sig.0[LeftPair::Signature::LEN..].try_into() else { return false };
379 RightPair::verify(&right_sig, message.as_ref(), &right_pub)
380 }
381
382 fn to_raw_vec(&self) -> Vec<u8> {
384 let mut raw = self.left.to_raw_vec();
385 raw.extend(self.right.to_raw_vec());
386 raw
387 }
388}
389
390#[cfg(all(test, feature = "bls-experimental"))]
392mod tests {
393 use super::*;
394 #[cfg(feature = "serde")]
395 use crate::crypto::Ss58Codec;
396 use crate::{bls377, crypto::DEV_PHRASE, ecdsa, KeccakHasher};
397 use codec::{Decode, Encode};
398 use ecdsa_bls377::{Pair, Signature};
399
400 #[test]
401 fn test_length_of_paired_ecdsa_and_bls377_public_key_and_signature_is_correct() {
402 assert_eq!(
403 <Pair as PairT>::Public::LEN,
404 <ecdsa::Pair as PairT>::Public::LEN + <bls377::Pair as PairT>::Public::LEN
405 );
406 assert_eq!(
407 <Pair as PairT>::Signature::LEN,
408 <ecdsa::Pair as PairT>::Signature::LEN + <bls377::Pair as PairT>::Signature::LEN
409 );
410 }
411
412 #[test]
413 fn default_phrase_should_be_used() {
414 assert_eq!(
415 Pair::from_string("//Alice///password", None).unwrap().public(),
416 Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password"))
417 .unwrap()
418 .public(),
419 );
420 }
421
422 #[test]
423 fn generate_with_phrase_should_be_recoverable_with_from_string() {
424 let (pair, phrase, seed) = Pair::generate_with_phrase(None);
425 let repair_seed = Pair::from_seed_slice(seed.as_ref()).expect("seed slice is valid");
426 assert_eq!(pair.public(), repair_seed.public());
427 assert_eq!(pair.to_raw_vec(), repair_seed.to_raw_vec());
428
429 let (repair_phrase, reseed) =
430 Pair::from_phrase(phrase.as_ref(), None).expect("seed slice is valid");
431 assert_eq!(seed, reseed);
432 assert_eq!(pair.public(), repair_phrase.public());
433 assert_eq!(pair.to_raw_vec(), repair_seed.to_raw_vec());
434 let repair_string = Pair::from_string(phrase.as_str(), None).expect("seed slice is valid");
435 assert_eq!(pair.public(), repair_string.public());
436 assert_eq!(pair.to_raw_vec(), repair_seed.to_raw_vec());
437 }
438
439 #[test]
440 fn seed_and_derive_should_work() {
441 let seed_for_right_and_left: [u8; SECURE_SEED_LEN] = array_bytes::hex2array_unchecked(
442 "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
443 );
444 let pair = Pair::from_seed(&seed_for_right_and_left);
445 let path = vec![DeriveJunction::Hard([0u8; 32])];
448 let derived = pair.derive(path.into_iter(), None).ok().unwrap().0;
449 assert_eq!(
450 derived.to_raw_vec(),
451 [
452 array_bytes::hex2array_unchecked::<&str, SECURE_SEED_LEN>(
453 "b8eefc4937200a8382d00050e050ced2d4ab72cc2ef1b061477afb51564fdd61"
454 ),
455 array_bytes::hex2array_unchecked::<&str, SECURE_SEED_LEN>(
456 "3a0626d095148813cd1642d38254f1cfff7eb8cc1a2fc83b2a135377c3554c12"
457 )
458 ]
459 .concat()
460 );
461 }
462
463 #[test]
464 fn test_vector_should_work() {
465 let seed_left_and_right: [u8; SECURE_SEED_LEN] = array_bytes::hex2array_unchecked(
466 "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
467 );
468 let pair = Pair::from_seed(&([seed_left_and_right].concat()[..].try_into().unwrap()));
469 let public = pair.public();
470 assert_eq!(
471 public,
472 Public::unchecked_from(
473 array_bytes::hex2array_unchecked("028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd917a84ca8ce4c37c93c95ecee6a3c0c9a7b9c225093cf2f12dc4f69cbfb847ef9424a18f5755d5a742247d386ff2aabb806bcf160eff31293ea9616976628f77266c8a8cc1d8753be04197bd6cdd8c5c87a148f782c4c1568d599b48833fd539001e580cff64bbc71850605433fcd051f3afc3b74819786f815ffb5272030a8d03e5df61e6183f8fd8ea85f26defa83400"),
474 ),
475 );
476 let message = b"";
477 let signature =
478 array_bytes::hex2array_unchecked("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00d1e3013161991e142d8751017d4996209c2ff8a9ee160f373733eda3b4b785ba6edce9f45f87104bbe07aa6aa6eb2780aa705efb2c13d3b317d6409d159d23bdc7cdd5c2a832d1551cf49d811d49c901495e527dbd532e3a462335ce2686009104aba7bc11c5b22be78f3198d2727a0b"
479 );
480 let signature = Signature::unchecked_from(signature);
481 assert!(pair.sign(&message[..]) == signature);
482 assert!(Pair::verify(&signature, &message[..], &public));
483 }
484
485 #[test]
486 fn test_vector_by_string_should_work() {
487 let pair = Pair::from_string(
488 "0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
489 None,
490 )
491 .unwrap();
492 let public = pair.public();
493 assert_eq!(
494 public,
495 Public::unchecked_from(
496 array_bytes::hex2array_unchecked("028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd917a84ca8ce4c37c93c95ecee6a3c0c9a7b9c225093cf2f12dc4f69cbfb847ef9424a18f5755d5a742247d386ff2aabb806bcf160eff31293ea9616976628f77266c8a8cc1d8753be04197bd6cdd8c5c87a148f782c4c1568d599b48833fd539001e580cff64bbc71850605433fcd051f3afc3b74819786f815ffb5272030a8d03e5df61e6183f8fd8ea85f26defa83400"
497 ),
498 ),
499 );
500 let message = b"";
501 let signature =
502 array_bytes::hex2array_unchecked("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00d1e3013161991e142d8751017d4996209c2ff8a9ee160f373733eda3b4b785ba6edce9f45f87104bbe07aa6aa6eb2780aa705efb2c13d3b317d6409d159d23bdc7cdd5c2a832d1551cf49d811d49c901495e527dbd532e3a462335ce2686009104aba7bc11c5b22be78f3198d2727a0b"
503 );
504 let signature = Signature::unchecked_from(signature);
505 assert!(pair.sign(&message[..]) == signature);
506 assert!(Pair::verify(&signature, &message[..], &public));
507 }
508
509 #[test]
510 fn generated_pair_should_work() {
511 let (pair, _) = Pair::generate();
512 let public = pair.public();
513 let message = b"Something important";
514 let signature = pair.sign(&message[..]);
515 assert!(Pair::verify(&signature, &message[..], &public));
516 assert!(!Pair::verify(&signature, b"Something else", &public));
517 }
518
519 #[test]
520 fn seeded_pair_should_work() {
521 let pair =
522 Pair::from_seed(&(b"12345678901234567890123456789012".as_slice().try_into().unwrap()));
523 let public = pair.public();
524 assert_eq!(
525 public,
526 Public::unchecked_from(
527 array_bytes::hex2array_unchecked("035676109c54b9a16d271abeb4954316a40a32bcce023ac14c8e26e958aa68fba9754d2f2bbfa67df54d7e0e951979a18a1e0f45948857752cc2bac6bbb0b1d05e8e48bcc453920bf0c4bbd5993212480112a1fb433f04d74af0a8b700d93dc957ab3207f8d071e948f5aca1a7632c00bdf6d06be05b43e2e6216dccc8a5d55a0071cb2313cfd60b7e9114619cd17c06843b352f0b607a99122f6651df8f02e1ad3697bd208e62af047ddd7b942ba80080")
528 ),
529 );
530 let message =
531 array_bytes::hex2bytes_unchecked("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"
532 );
533 let signature = pair.sign(&message[..]);
534 println!("Correct signature: {:?}", signature);
535 assert!(Pair::verify(&signature, &message[..], &public));
536 assert!(!Pair::verify(&signature, "Other message", &public));
537 }
538
539 #[test]
540 fn generate_with_phrase_recovery_possible() {
541 let (pair1, phrase, _) = Pair::generate_with_phrase(None);
542 let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap();
543
544 assert_eq!(pair1.public(), pair2.public());
545 }
546
547 #[test]
548 fn generate_with_password_phrase_recovery_possible() {
549 let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password"));
550 let (pair2, _) = Pair::from_phrase(&phrase, Some("password")).unwrap();
551
552 assert_eq!(pair1.public(), pair2.public());
553 }
554
555 #[test]
556 fn password_does_something() {
557 let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password"));
558 let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap();
559
560 assert_ne!(pair1.public(), pair2.public());
561 assert_ne!(pair1.to_raw_vec(), pair2.to_raw_vec());
562 }
563
564 #[test]
565 fn ss58check_roundtrip_works() {
566 let pair =
567 Pair::from_seed(&(b"12345678901234567890123456789012".as_slice().try_into().unwrap()));
568 let public = pair.public();
569 let s = public.to_ss58check();
570 println!("Correct: {}", s);
571 let cmp = Public::from_ss58check(&s).unwrap();
572 assert_eq!(cmp, public);
573 }
574
575 #[test]
576 fn sign_and_verify_with_hasher_works() {
577 let pair =
578 Pair::from_seed(&(b"12345678901234567890123456789012".as_slice().try_into().unwrap()));
579 let message = b"Something important";
580 let signature = pair.sign_with_hasher::<KeccakHasher>(&message[..]);
581
582 assert!(Pair::verify_with_hasher::<KeccakHasher>(&signature, &message[..], &pair.public()));
583 }
584
585 #[test]
586 fn signature_serialization_works() {
587 let pair =
588 Pair::from_seed(&(b"12345678901234567890123456789012".as_slice().try_into().unwrap()));
589 let message = b"Something important";
590 let signature = pair.sign(&message[..]);
591
592 let serialized_signature = serde_json::to_string(&signature).unwrap();
593 println!("{:?} -- {:}", signature.0, serialized_signature);
594 assert_eq!(serialized_signature.len(), 356);
596 let signature = serde_json::from_str(&serialized_signature).unwrap();
597 assert!(Pair::verify(&signature, &message[..], &pair.public()));
598 }
599
600 #[test]
601 fn signature_serialization_doesnt_panic() {
602 fn deserialize_signature(text: &str) -> Result<Signature, serde_json::error::Error> {
603 serde_json::from_str(text)
604 }
605 assert!(deserialize_signature("Not valid json.").is_err());
606 assert!(deserialize_signature("\"Not an actual signature.\"").is_err());
607 assert!(deserialize_signature("\"abc123\"").is_err());
609 }
610
611 #[test]
612 fn encode_and_decode_public_key_works() {
613 let pair =
614 Pair::from_seed(&(b"12345678901234567890123456789012".as_slice().try_into().unwrap()));
615 let public = pair.public();
616 let encoded_public = public.encode();
617 let decoded_public = Public::decode(&mut encoded_public.as_slice()).unwrap();
618 assert_eq!(public, decoded_public)
619 }
620
621 #[test]
622 fn encode_and_decode_signature_works() {
623 let pair =
624 Pair::from_seed(&(b"12345678901234567890123456789012".as_slice().try_into().unwrap()));
625 let message = b"Something important";
626 let signature = pair.sign(&message[..]);
627 let encoded_signature = signature.encode();
628 let decoded_signature = Signature::decode(&mut encoded_signature.as_slice()).unwrap();
629 assert_eq!(signature, decoded_signature)
630 }
631}