timegraph_identity/
signer.rs

1extern crate bs58;
2extern crate multibase;
3
4use rosetta_crypto::{
5    address::Ss58AddressFormatRegistry,
6    bip32::DerivedSecretKey,
7    bip39::{Language, Mnemonic},
8};
9pub use rosetta_crypto::{Algorithm, PublicKey, SecretKey, Signature};
10use std::fmt::{Debug, Formatter};
11
12pub const SIGNING_CONTEXT: &str = "substrate";
13
14pub fn bytes_decode(str: &str) -> anyhow::Result<Vec<u8>> {
15    Ok(bs58::decode(str).into_vec()?)
16}
17pub fn bytes_encode(bs: &[u8]) -> anyhow::Result<String> {
18    Ok(bs58::encode(bs).into_string())
19}
20
21pub fn bytes_decode_lower32(str: &str) -> anyhow::Result<Vec<u8>> {
22    Ok(multibase::Base::Base32Lower.decode(str)?)
23}
24pub fn bytes_encode_lower32(bs: &[u8]) -> anyhow::Result<String> {
25    Ok(multibase::Base::Base32Lower.encode(bs))
26}
27
28pub fn generate_mnemonic() -> anyhow::Result<Mnemonic> {
29    let mut entropy = [0; 32];
30    getrandom::getrandom(&mut entropy)?;
31    let mnemonic = Mnemonic::from_entropy_in(Language::English, &entropy)?;
32    Ok(mnemonic)
33}
34
35#[derive(Clone)]
36pub struct Signer(pub SecretKey);
37
38impl Debug for Signer {
39    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40        self.address()
41            .map_err(|_| std::fmt::Error)
42            .and_then(|x| write!(f, "Signer('{}')", x))
43    }
44}
45
46impl Signer {
47    pub fn from_mnemonic(mnemonic: &Mnemonic, password: &str) -> anyhow::Result<Self> {
48        let sk = DerivedSecretKey::substrate(mnemonic, password, Algorithm::Sr25519)?
49            .secret_key()
50            .clone();
51        Ok(Signer(sk))
52    }
53
54    pub fn from_bytes(bs: &[u8]) -> anyhow::Result<Self> {
55        let sk = SecretKey::from_bytes(Algorithm::Sr25519, bs)?;
56        Ok(Self(sk))
57    }
58
59    pub fn verifier_from_bytes(bs: &[u8]) -> anyhow::Result<Verifier> {
60        let pubk = PublicKey::from_bytes(Algorithm::Sr25519, bs)?;
61        Ok(Verifier(pubk))
62    }
63
64    pub fn signature_from_bytes(bs: &[u8]) -> anyhow::Result<Signature> {
65        Signature::from_bytes(Algorithm::Sr25519, bs)
66    }
67
68    pub fn pubkey_from_bytes(bs: &[u8]) -> anyhow::Result<PublicKey> {
69        PublicKey::from_bytes(Algorithm::Sr25519, bs)
70    }
71
72    pub fn pubkey_to_address(pubk: &PublicKey) -> anyhow::Result<String> {
73        let format = Ss58AddressFormatRegistry::SubstrateAccount.into();
74        Ok(pubk.to_address(format).address().to_string())
75    }
76
77    pub fn address(&self) -> anyhow::Result<String> {
78        Self::pubkey_to_address(&self.public_key())
79    }
80
81    pub fn pubkey_from_address(address: &str) -> anyhow::Result<PublicKey> {
82        let bs = bytes_decode(address)?;
83        match bs.len() {
84            32 => PublicKey::from_bytes(Algorithm::Sr25519, &bs),
85            35 => match bs.split_first() {
86                Some((x, y)) if *x == 42 => {
87                    // Substrate Address
88                    PublicKey::from_bytes(Algorithm::Sr25519, &y[0..32])
89                }
90                _ => Err(anyhow::anyhow!("invalid public key format")),
91            },
92            _ => Err(anyhow::anyhow!("invalid public key format")),
93        }
94    }
95
96    pub fn to_bytes(&self) -> anyhow::Result<Vec<u8>> {
97        Ok(self.0.to_bytes())
98    }
99
100    pub fn new() -> anyhow::Result<Self> {
101        let mnemonic = generate_mnemonic()?;
102        Self::from_mnemonic(&mnemonic, "")
103    }
104
105    pub fn secret_key(&self) -> &SecretKey {
106        &self.0
107    }
108
109    pub fn public_key(&self) -> PublicKey {
110        self.0.public_key()
111    }
112
113    pub fn stringify(&self) -> anyhow::Result<String> {
114        bytes_encode(&self.0.to_bytes())
115    }
116
117    pub fn stringify_public_key(&self) -> anyhow::Result<String> {
118        bytes_encode(&self.0.public_key().to_bytes())
119    }
120
121    pub fn sign_msg(&self, msg: &[u8], context: &str) -> anyhow::Result<Signature> {
122        Ok(self.0.sign(msg, context))
123    }
124
125    pub fn verify_msg(
126        &self,
127        msg: &[u8],
128        context: &str,
129        signature: &Signature,
130    ) -> anyhow::Result<()> {
131        Verifier(self.public_key()).verify_msg(msg, context, signature)
132    }
133}
134
135pub struct Verifier(pub PublicKey);
136
137impl Verifier {
138    pub fn verify_msg(
139        &self,
140        msg: &[u8],
141        context: &str,
142        signature: &Signature,
143    ) -> anyhow::Result<()> {
144        if let (PublicKey::Sr25519(pubk), Signature::Sr25519(sg)) = (self.0, signature) {
145            pubk.verify_simple(context.as_bytes(), msg, sg)
146                .map_err(|e| anyhow::anyhow!("{e}"))
147        } else {
148            anyhow::bail!("unsupported public key")
149        }
150    }
151}
152
153#[test]
154fn test_address_hex() -> anyhow::Result<()> {
155    // succeeded
156    Signer::pubkey_from_address("5GYRuocV6B8WJpkJDgtiM2RTct54PquWLoP2cnEuujc343z1")?;
157    // failed
158    assert!(
159        Signer::pubkey_from_address("1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg").is_err()
160    );
161    Ok(())
162}
163
164#[test]
165fn test_pubkey_to_address() -> anyhow::Result<()> {
166    let signer = Signer::new()?;
167    let address = signer.address()?;
168    let bs1 = signer.public_key();
169    let bs2 = Signer::pubkey_from_address(&address)?;
170    assert_eq!(bs1, bs2);
171    Ok(())
172}