1#[cfg(feature = "full_crypto")]
23use tetcore_std::vec::Vec;
24
25use tetcore_std::cmp::Ordering;
26use codec::{Encode, Decode};
27
28#[cfg(feature = "full_crypto")]
29use core::convert::{TryFrom, TryInto};
30#[cfg(feature = "std")]
31use tetcore_bip39::seed_from_entropy;
32#[cfg(feature = "std")]
33use bip39::{Mnemonic, Language, MnemonicType};
34#[cfg(feature = "full_crypto")]
35use crate::{hashing::blake2_256, crypto::{Pair as TraitPair, DeriveJunction, SecretStringError}};
36#[cfg(feature = "std")]
37use crate::crypto::Ss58Codec;
38#[cfg(feature = "std")]
39use serde::{de, Serializer, Serialize, Deserializer, Deserialize};
40use crate::crypto::{Public as TraitPublic, CryptoTypePublicPair, UncheckedFrom, CryptoType, Derive, CryptoTypeId};
41use tp_runtime_interface::pass_by::PassByInner;
42#[cfg(feature = "full_crypto")]
43use secp256k1::{PublicKey, SecretKey};
44
45pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds");
47
48#[cfg(feature = "full_crypto")]
52type Seed = [u8; 32];
53
54#[derive(Clone, Encode, Decode, PassByInner)]
56pub struct Public(pub [u8; 33]);
57
58impl PartialOrd for Public {
59 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
60 Some(self.cmp(other))
61 }
62}
63
64impl Ord for Public {
65 fn cmp(&self, other: &Self) -> Ordering {
66 self.as_ref().cmp(&other.as_ref())
67 }
68}
69
70impl PartialEq for Public {
71 fn eq(&self, other: &Self) -> bool {
72 self.as_ref() == other.as_ref()
73 }
74}
75
76impl Eq for Public {}
77
78#[cfg(feature = "std")]
80#[derive(Clone, Copy, Eq, PartialEq, Debug)]
81pub enum PublicError {
82 BadBase58,
84 BadLength,
86 UnknownVersion,
88 InvalidChecksum,
90}
91
92impl Public {
93 pub fn from_raw(data: [u8; 33]) -> Self {
98 Self(data)
99 }
100
101 #[cfg(feature = "std")]
105 pub fn from_full(full: &[u8]) -> Result<Self, ()> {
106 secp256k1::PublicKey::parse_slice(full, None)
107 .map(|k| k.serialize_compressed())
108 .map(Self)
109 .map_err(|_| ())
110 }
111}
112
113impl TraitPublic for Public {
114 fn from_slice(data: &[u8]) -> Self {
119 let mut r = [0u8; 33];
120 r.copy_from_slice(data);
121 Self(r)
122 }
123
124 fn to_public_crypto_pair(&self) -> CryptoTypePublicPair {
125 CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec())
126 }
127}
128
129impl From<Public> for CryptoTypePublicPair {
130 fn from(key: Public) -> Self {
131 (&key).into()
132 }
133}
134
135impl From<&Public> for CryptoTypePublicPair {
136 fn from(key: &Public) -> Self {
137 CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec())
138 }
139}
140
141impl Derive for Public {}
142
143impl Default for Public {
144 fn default() -> Self {
145 Public([0u8; 33])
146 }
147}
148
149impl AsRef<[u8]> for Public {
150 fn as_ref(&self) -> &[u8] {
151 &self.0[..]
152 }
153}
154
155impl AsMut<[u8]> for Public {
156 fn as_mut(&mut self) -> &mut [u8] {
157 &mut self.0[..]
158 }
159}
160
161impl tetcore_std::convert::TryFrom<&[u8]> for Public {
162 type Error = ();
163
164 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
165 if data.len() == 33 {
166 Ok(Self::from_slice(data))
167 } else {
168
169 Err(())
170 }
171 }
172}
173
174#[cfg(feature = "full_crypto")]
175impl From<Pair> for Public {
176 fn from(x: Pair) -> Self {
177 x.public()
178 }
179}
180
181impl UncheckedFrom<[u8; 33]> for Public {
182 fn unchecked_from(x: [u8; 33]) -> Self {
183 Public(x)
184 }
185}
186
187#[cfg(feature = "std")]
188impl std::fmt::Display for Public {
189 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
190 write!(f, "{}", self.to_ss58check())
191 }
192}
193
194impl tetcore_std::fmt::Debug for Public {
195 #[cfg(feature = "std")]
196 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
197 let s = self.to_ss58check();
198 write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.as_ref()), &s[0..8])
199 }
200
201 #[cfg(not(feature = "std"))]
202 fn fmt(&self, _: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
203 Ok(())
204 }
205}
206
207#[cfg(feature = "std")]
208impl Serialize for Public {
209 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
210 serializer.serialize_str(&self.to_ss58check())
211 }
212}
213
214#[cfg(feature = "std")]
215impl<'de> Deserialize<'de> for Public {
216 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
217 Public::from_ss58check(&String::deserialize(deserializer)?)
218 .map_err(|e| de::Error::custom(format!("{:?}", e)))
219 }
220}
221
222#[cfg(feature = "full_crypto")]
223impl tetcore_std::hash::Hash for Public {
224 fn hash<H: tetcore_std::hash::Hasher>(&self, state: &mut H) {
225 self.as_ref().hash(state);
226 }
227}
228
229#[derive(Encode, Decode, PassByInner)]
231pub struct Signature(pub [u8; 65]);
232
233impl tetcore_std::convert::TryFrom<&[u8]> for Signature {
234 type Error = ();
235
236 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
237 if data.len() == 65 {
238 let mut inner = [0u8; 65];
239 inner.copy_from_slice(data);
240 Ok(Signature(inner))
241 } else {
242 Err(())
243 }
244 }
245}
246
247#[cfg(feature = "std")]
248impl Serialize for Signature {
249 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
250 serializer.serialize_str(&hex::encode(self))
251 }
252}
253
254#[cfg(feature = "std")]
255impl<'de> Deserialize<'de> for Signature {
256 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
257 let signature_hex = hex::decode(&String::deserialize(deserializer)?)
258 .map_err(|e| de::Error::custom(format!("{:?}", e)))?;
259 Ok(Signature::try_from(signature_hex.as_ref())
260 .map_err(|e| de::Error::custom(format!("{:?}", e)))?)
261 }
262}
263
264impl Clone for Signature {
265 fn clone(&self) -> Self {
266 let mut r = [0u8; 65];
267 r.copy_from_slice(&self.0[..]);
268 Signature(r)
269 }
270}
271
272impl Default for Signature {
273 fn default() -> Self {
274 Signature([0u8; 65])
275 }
276}
277
278impl PartialEq for Signature {
279 fn eq(&self, b: &Self) -> bool {
280 self.0[..] == b.0[..]
281 }
282}
283
284impl Eq for Signature {}
285
286impl From<Signature> for [u8; 65] {
287 fn from(v: Signature) -> [u8; 65] {
288 v.0
289 }
290}
291
292impl AsRef<[u8; 65]> for Signature {
293 fn as_ref(&self) -> &[u8; 65] {
294 &self.0
295 }
296}
297
298impl AsRef<[u8]> for Signature {
299 fn as_ref(&self) -> &[u8] {
300 &self.0[..]
301 }
302}
303
304impl AsMut<[u8]> for Signature {
305 fn as_mut(&mut self) -> &mut [u8] {
306 &mut self.0[..]
307 }
308}
309
310impl tetcore_std::fmt::Debug for Signature {
311 #[cfg(feature = "std")]
312 fn fmt(&self, f: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
313 write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0))
314 }
315
316 #[cfg(not(feature = "std"))]
317 fn fmt(&self, _: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
318 Ok(())
319 }
320}
321
322#[cfg(feature = "full_crypto")]
323impl tetcore_std::hash::Hash for Signature {
324 fn hash<H: tetcore_std::hash::Hasher>(&self, state: &mut H) {
325 tetcore_std::hash::Hash::hash(&self.0[..], state);
326 }
327}
328
329impl Signature {
330 pub fn from_raw(data: [u8; 65]) -> Signature {
335 Signature(data)
336 }
337
338 pub fn from_slice(data: &[u8]) -> Self {
343 let mut r = [0u8; 65];
344 r.copy_from_slice(data);
345 Signature(r)
346 }
347
348 #[cfg(feature = "full_crypto")]
350 pub fn recover<M: AsRef<[u8]>>(&self, message: M) -> Option<Public> {
351 let message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
352 let sig: (_, _) = self.try_into().ok()?;
353 secp256k1::recover(&message, &sig.0, &sig.1)
354 .ok()
355 .map(|recovered| Public(recovered.serialize_compressed()))
356 }
357}
358
359#[cfg(feature = "full_crypto")]
360impl From<(secp256k1::Signature, secp256k1::RecoveryId)> for Signature {
361 fn from(x: (secp256k1::Signature, secp256k1::RecoveryId)) -> Signature {
362 let mut r = Self::default();
363 r.0[0..64].copy_from_slice(&x.0.serialize()[..]);
364 r.0[64] = x.1.serialize();
365 r
366 }
367}
368
369#[cfg(feature = "full_crypto")]
370impl<'a> TryFrom<&'a Signature> for (secp256k1::Signature, secp256k1::RecoveryId) {
371 type Error = ();
372 fn try_from(x: &'a Signature) -> Result<(secp256k1::Signature, secp256k1::RecoveryId), Self::Error> {
373 Ok((
374 secp256k1::Signature::parse_slice(&x.0[0..64]).expect("hardcoded to 64 bytes; qed"),
375 secp256k1::RecoveryId::parse(x.0[64]).map_err(|_| ())?,
376 ))
377 }
378}
379
380#[cfg(feature = "full_crypto")]
382fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed {
383 ("Secp256k1HDKD", secret_seed, cc).using_encoded(|data| {
384 let mut res = [0u8; 32];
385 res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes());
386 res
387 })
388}
389
390#[cfg(feature = "full_crypto")]
392pub enum DeriveError {
393 SoftKeyInPath,
395}
396
397#[cfg(feature = "full_crypto")]
399#[derive(Clone)]
400pub struct Pair {
401 public: PublicKey,
402 secret: SecretKey,
403}
404
405#[cfg(feature = "full_crypto")]
406impl TraitPair for Pair {
407 type Public = Public;
408 type Seed = Seed;
409 type Signature = Signature;
410 type DeriveError = DeriveError;
411
412 #[cfg(feature = "std")]
416 fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) {
417 let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English);
418 let phrase = mnemonic.phrase();
419 let (pair, seed) = Self::from_phrase(phrase, password)
420 .expect("All phrases generated by Mnemonic are valid; qed");
421 (
422 pair,
423 phrase.to_owned(),
424 seed,
425 )
426 }
427
428 #[cfg(feature = "std")]
430 fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> {
431 let big_seed = seed_from_entropy(
432 Mnemonic::from_phrase(phrase, Language::English)
433 .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(),
434 password.unwrap_or(""),
435 ).map_err(|_| SecretStringError::InvalidSeed)?;
436 let mut seed = Seed::default();
437 seed.copy_from_slice(&big_seed[0..32]);
438 Self::from_seed_slice(&big_seed[0..32]).map(|x| (x, seed))
439 }
440
441 fn from_seed(seed: &Seed) -> Pair {
445 Self::from_seed_slice(&seed[..]).expect("seed has valid length; qed")
446 }
447
448 fn from_seed_slice(seed_slice: &[u8]) -> Result<Pair, SecretStringError> {
453 let secret = SecretKey::parse_slice(seed_slice)
454 .map_err(|_| SecretStringError::InvalidSeedLength)?;
455 let public = PublicKey::from_secret_key(&secret);
456 Ok(Pair{ secret, public })
457 }
458
459 fn derive<Iter: Iterator<Item=DeriveJunction>>(&self,
461 path: Iter,
462 _seed: Option<Seed>
463 ) -> Result<(Pair, Option<Seed>), DeriveError> {
464 let mut acc = self.secret.serialize();
465 for j in path {
466 match j {
467 DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath),
468 DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc),
469 }
470 }
471 Ok((Self::from_seed(&acc), Some(acc)))
472 }
473
474 fn public(&self) -> Public {
476 Public(self.public.serialize_compressed())
477 }
478
479 fn sign(&self, message: &[u8]) -> Signature {
481 let message = secp256k1::Message::parse(&blake2_256(message));
482 secp256k1::sign(&message, &self.secret).into()
483 }
484
485 fn verify<M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool {
487 let message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
488 let sig: (_, _) = match sig.try_into() { Ok(x) => x, _ => return false };
489 match secp256k1::recover(&message, &sig.0, &sig.1) {
490 Ok(actual) => &pubkey.0[..] == &actual.serialize_compressed()[..],
491 _ => false,
492 }
493 }
494
495 fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool {
500 let message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
501 if sig.len() != 65 { return false }
502 let ri = match secp256k1::RecoveryId::parse(sig[64]) { Ok(x) => x, _ => return false };
503 let sig = match secp256k1::Signature::parse_slice(&sig[0..64]) { Ok(x) => x, _ => return false };
504 match secp256k1::recover(&message, &sig, &ri) {
505 Ok(actual) => pubkey.as_ref() == &actual.serialize()[1..],
506 _ => false,
507 }
508 }
509
510 fn to_raw_vec(&self) -> Vec<u8> {
512 self.seed().to_vec()
513 }
514}
515
516#[cfg(feature = "full_crypto")]
517impl Pair {
518 pub fn seed(&self) -> Seed {
520 self.secret.serialize()
521 }
522
523 #[cfg(feature = "std")]
526 pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair {
527 Self::from_string(s, password_override).unwrap_or_else(|_| {
528 let mut padded_seed: Seed = [' ' as u8; 32];
529 let len = s.len().min(32);
530 padded_seed[..len].copy_from_slice(&s.as_bytes()[..len]);
531 Self::from_seed(&padded_seed)
532 })
533 }
534}
535
536impl CryptoType for Public {
537 #[cfg(feature="full_crypto")]
538 type Pair = Pair;
539}
540
541impl CryptoType for Signature {
542 #[cfg(feature="full_crypto")]
543 type Pair = Pair;
544}
545
546#[cfg(feature="full_crypto")]
547impl CryptoType for Pair {
548 type Pair = Pair;
549}
550
551#[cfg(test)]
552mod test {
553 use super::*;
554 use hex_literal::hex;
555 use crate::crypto::{DEV_PHRASE, set_default_ss58_version};
556 use serde_json;
557
558 #[test]
559 fn default_phrase_should_be_used() {
560 assert_eq!(
561 Pair::from_string("//Alice///password", None).unwrap().public(),
562 Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(),
563 );
564 }
565
566 #[test]
567 fn seed_and_derive_should_work() {
568 let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60");
569 let pair = Pair::from_seed(&seed);
570 assert_eq!(pair.seed(), seed);
571 let path = vec![DeriveJunction::Hard([0u8; 32])];
572 let derived = pair.derive(path.into_iter(), None).ok().unwrap();
573 assert_eq!(
574 derived.0.seed(),
575 hex!("b8eefc4937200a8382d00050e050ced2d4ab72cc2ef1b061477afb51564fdd61")
576 );
577 }
578
579 #[test]
580 fn test_vector_should_work() {
581 let pair = Pair::from_seed(
582 &hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
583 );
584 let public = pair.public();
585 assert_eq!(
586 public,
587 Public::from_full(
588 &hex!("8db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd913ebbe148dd17c56551a52952371071a6c604b3f3abe8f2c8fa742158ea6dd7d4")[..],
589 ).unwrap(),
590 );
591 let message = b"";
592 let signature = hex!("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00");
593 let signature = Signature::from_raw(signature);
594 assert!(&pair.sign(&message[..]) == &signature);
595 assert!(Pair::verify(&signature, &message[..], &public));
596 }
597
598 #[test]
599 fn test_vector_by_string_should_work() {
600 let pair = Pair::from_string(
601 "0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
602 None
603 ).unwrap();
604 let public = pair.public();
605 assert_eq!(
606 public,
607 Public::from_full(
608 &hex!("8db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd913ebbe148dd17c56551a52952371071a6c604b3f3abe8f2c8fa742158ea6dd7d4")[..],
609 ).unwrap(),
610 );
611 let message = b"";
612 let signature = hex!("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00");
613 let signature = Signature::from_raw(signature);
614 assert!(&pair.sign(&message[..]) == &signature);
615 assert!(Pair::verify(&signature, &message[..], &public));
616 }
617
618 #[test]
619 fn generated_pair_should_work() {
620 let (pair, _) = Pair::generate();
621 let public = pair.public();
622 let message = b"Something important";
623 let signature = pair.sign(&message[..]);
624 assert!(Pair::verify(&signature, &message[..], &public));
625 assert!(!Pair::verify(&signature, b"Something else", &public));
626 }
627
628 #[test]
629 fn seeded_pair_should_work() {
630 let pair = Pair::from_seed(b"12345678901234567890123456789012");
631 let public = pair.public();
632 assert_eq!(
633 public,
634 Public::from_full(
635 &hex!("5676109c54b9a16d271abeb4954316a40a32bcce023ac14c8e26e958aa68fba995840f3de562156558efbfdac3f16af0065e5f66795f4dd8262a228ef8c6d813")[..],
636 ).unwrap(),
637 );
638 let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000");
639 let signature = pair.sign(&message[..]);
640 println!("Correct signature: {:?}", signature);
641 assert!(Pair::verify(&signature, &message[..], &public));
642 assert!(!Pair::verify(&signature, "Other message", &public));
643 }
644
645 #[test]
646 fn generate_with_phrase_recovery_possible() {
647 let (pair1, phrase, _) = Pair::generate_with_phrase(None);
648 let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap();
649
650 assert_eq!(pair1.public(), pair2.public());
651 }
652
653 #[test]
654 fn generate_with_password_phrase_recovery_possible() {
655 let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password"));
656 let (pair2, _) = Pair::from_phrase(&phrase, Some("password")).unwrap();
657
658 assert_eq!(pair1.public(), pair2.public());
659 }
660
661 #[test]
662 fn password_does_something() {
663 let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password"));
664 let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap();
665
666 assert_ne!(pair1.public(), pair2.public());
667 }
668
669 #[test]
670 fn ss58check_roundtrip_works() {
671 let pair = Pair::from_seed(b"12345678901234567890123456789012");
672 let public = pair.public();
673 let s = public.to_ss58check();
674 println!("Correct: {}", s);
675 let cmp = Public::from_ss58check(&s).unwrap();
676 assert_eq!(cmp, public);
677 }
678
679 #[test]
680 fn ss58check_custom_format_works() {
681 if std::env::var("RUN_CUSTOM_FORMAT_TEST") == Ok("1".into()) {
684 use crate::crypto::Ss58AddressFormat;
685 let default_format = Ss58AddressFormat::default();
687 set_default_ss58_version(Ss58AddressFormat::Custom(200));
689 let addr = "2X64kMNEWAW5KLZMSKcGKEc96MyuaRsRUku7vomuYxKgqjVCRj";
691 Public::from_ss58check(&addr).unwrap();
692 set_default_ss58_version(default_format);
693 let addr = "KWAfgC2aRG5UVD6CpbPQXCx4YZZUhvWqqAJE6qcYc9Rtr6g5C";
695 Public::from_ss58check(&addr).unwrap();
696
697 println!("CUSTOM_FORMAT_SUCCESSFUL");
698 } else {
699 let executable = std::env::current_exe().unwrap();
700 let output = std::process::Command::new(executable)
701 .env("RUN_CUSTOM_FORMAT_TEST", "1")
702 .args(&["--nocapture", "ss58check_custom_format_works"])
703 .output()
704 .unwrap();
705
706 let output = String::from_utf8(output.stdout).unwrap();
707 assert!(output.contains("CUSTOM_FORMAT_SUCCESSFUL"));
708 }
709 }
710
711 #[test]
712 fn signature_serialization_works() {
713 let pair = Pair::from_seed(b"12345678901234567890123456789012");
714 let message = b"Something important";
715 let signature = pair.sign(&message[..]);
716 let serialized_signature = serde_json::to_string(&signature).unwrap();
717 assert_eq!(serialized_signature.len(), 132);
719 let signature = serde_json::from_str(&serialized_signature).unwrap();
720 assert!(Pair::verify(&signature, &message[..], &pair.public()));
721 }
722
723 #[test]
724 fn signature_serialization_doesnt_panic() {
725 fn deserialize_signature(text: &str) -> Result<Signature, serde_json::error::Error> {
726 Ok(serde_json::from_str(text)?)
727 }
728 assert!(deserialize_signature("Not valid json.").is_err());
729 assert!(deserialize_signature("\"Not an actual signature.\"").is_err());
730 assert!(deserialize_signature("\"abc123\"").is_err());
732 }
733}