rosetta_crypto/
lib.rs

1//! Implements cryptography needed for various chains.
2#![deny(missing_docs)]
3#![deny(warnings)]
4
5use anyhow::{Context, Result};
6use ecdsa::hazmat::SignPrimitive;
7use ecdsa::signature::hazmat::PrehashSigner;
8use ecdsa::signature::{Signer as _, Verifier as _};
9use ecdsa::RecoveryId;
10use ed25519_dalek::{Signer as _, Verifier as _};
11use sha2::Digest;
12
13pub mod address;
14pub mod bip32;
15pub use bip39;
16pub mod bip44;
17
18/// Signing algorithm.
19#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
20pub enum Algorithm {
21    /// ECDSA with secp256k1.
22    EcdsaSecp256k1,
23    /// ECDSA with secp256k1 in Ethereum compatible format.
24    EcdsaRecoverableSecp256k1,
25    /// ECDSA with NIST P-256.
26    EcdsaSecp256r1,
27    /// Ed25519.
28    Ed25519,
29    /// Schnorrkel used by substrate/polkadot.
30    Sr25519,
31}
32
33impl Algorithm {
34    /// Returns true if the signer's public key is recoverable from the signature.
35    pub fn is_recoverable(&self) -> bool {
36        matches!(self, Algorithm::EcdsaRecoverableSecp256k1)
37    }
38}
39
40/// Secret key used for constructing signatures.
41pub enum SecretKey {
42    /// ECDSA with secp256k1.
43    EcdsaSecp256k1(ecdsa::SigningKey<k256::Secp256k1>),
44    /// ECDSA with secp256k1 in Ethereum compatible format.
45    EcdsaRecoverableSecp256k1(ecdsa::SigningKey<k256::Secp256k1>),
46    /// ECDSA with NIST P-256.
47    EcdsaSecp256r1(ecdsa::SigningKey<p256::NistP256>),
48    /// Ed25519.
49    Ed25519(ed25519_dalek::Keypair),
50    /// Schnorrkel used by substrate/polkadot.
51    Sr25519(schnorrkel::Keypair, Option<schnorrkel::MiniSecretKey>),
52}
53
54impl Clone for SecretKey {
55    fn clone(&self) -> Self {
56        Self::from_bytes(self.algorithm(), &self.to_bytes()).unwrap()
57    }
58}
59
60impl SecretKey {
61    /// Returns the signing algorithm.
62    pub fn algorithm(&self) -> Algorithm {
63        match self {
64            SecretKey::EcdsaSecp256k1(_) => Algorithm::EcdsaSecp256k1,
65            SecretKey::EcdsaRecoverableSecp256k1(_) => Algorithm::EcdsaRecoverableSecp256k1,
66            SecretKey::EcdsaSecp256r1(_) => Algorithm::EcdsaSecp256r1,
67            SecretKey::Ed25519(_) => Algorithm::Ed25519,
68            SecretKey::Sr25519(_, _) => Algorithm::Sr25519,
69        }
70    }
71
72    /// Creates a secret key from a byte sequence for a given signing algorithm.
73    pub fn from_bytes(algorithm: Algorithm, bytes: &[u8]) -> Result<Self> {
74        Ok(match algorithm {
75            Algorithm::EcdsaSecp256k1 => {
76                SecretKey::EcdsaSecp256k1(ecdsa::SigningKey::from_bytes(bytes.try_into()?)?)
77            }
78            Algorithm::EcdsaRecoverableSecp256k1 => SecretKey::EcdsaRecoverableSecp256k1(
79                ecdsa::SigningKey::from_bytes(bytes.try_into()?)?,
80            ),
81            Algorithm::EcdsaSecp256r1 => {
82                SecretKey::EcdsaSecp256r1(ecdsa::SigningKey::from_bytes(bytes.try_into()?)?)
83            }
84            Algorithm::Ed25519 => {
85                let secret = ed25519_dalek::SecretKey::from_bytes(bytes)?;
86                let public = ed25519_dalek::PublicKey::from(&secret);
87                let keypair = ed25519_dalek::Keypair { secret, public };
88                SecretKey::Ed25519(keypair)
89            }
90            Algorithm::Sr25519 => {
91                if bytes.len() == 32 {
92                    let minisecret = schnorrkel::MiniSecretKey::from_bytes(bytes)
93                        .map_err(|err| anyhow::anyhow!("{}", err))?;
94                    let secret =
95                        minisecret.expand_to_keypair(schnorrkel::MiniSecretKey::ED25519_MODE);
96                    SecretKey::Sr25519(secret, Some(minisecret))
97                } else {
98                    let secret = schnorrkel::SecretKey::from_bytes(bytes)
99                        .map_err(|err| anyhow::anyhow!("{}", err))?;
100                    SecretKey::Sr25519(secret.to_keypair(), None)
101                }
102            }
103        })
104    }
105
106    /// Returns a byte sequence representing the secret key.
107    pub fn to_bytes(&self) -> Vec<u8> {
108        match self {
109            SecretKey::EcdsaSecp256k1(secret) => secret.to_bytes().to_vec(),
110            SecretKey::EcdsaRecoverableSecp256k1(secret) => secret.to_bytes().to_vec(),
111            SecretKey::EcdsaSecp256r1(secret) => secret.to_bytes().to_vec(),
112            SecretKey::Ed25519(secret) => secret.secret.to_bytes().to_vec(),
113            SecretKey::Sr25519(_, Some(minisecret)) => minisecret.as_bytes().to_vec(),
114            SecretKey::Sr25519(secret, None) => secret.secret.to_bytes().to_vec(),
115        }
116    }
117
118    /// Returns the public key used for verifying signatures.
119    pub fn public_key(&self) -> PublicKey {
120        match self {
121            SecretKey::EcdsaSecp256k1(secret) => PublicKey::EcdsaSecp256k1(*secret.verifying_key()),
122            SecretKey::EcdsaRecoverableSecp256k1(secret) => {
123                PublicKey::EcdsaRecoverableSecp256k1(*secret.verifying_key())
124            }
125            SecretKey::EcdsaSecp256r1(secret) => PublicKey::EcdsaSecp256r1(*secret.verifying_key()),
126            SecretKey::Ed25519(secret) => PublicKey::Ed25519(secret.public),
127            SecretKey::Sr25519(secret, _) => PublicKey::Sr25519(secret.public),
128        }
129    }
130
131    /// Signs a message and returns it's signature.
132    pub fn sign(&self, msg: &[u8], context_param: &str) -> Signature {
133        match self {
134            SecretKey::EcdsaSecp256k1(secret) => Signature::EcdsaSecp256k1(secret.sign(msg)),
135            SecretKey::EcdsaRecoverableSecp256k1(_) => {
136                let digest = sha2::Sha256::digest(msg);
137                self.sign_prehashed(&digest).unwrap()
138            }
139            SecretKey::EcdsaSecp256r1(secret) => Signature::EcdsaSecp256r1(secret.sign(msg)),
140            SecretKey::Ed25519(secret) => Signature::Ed25519(secret.sign(msg)),
141            SecretKey::Sr25519(secret, _) => {
142                // need a signing context here for substrate
143                let context = schnorrkel::signing_context(context_param.as_bytes());
144                Signature::Sr25519(secret.sign(context.bytes(msg)))
145            }
146        }
147    }
148
149    /// Signs a prehashed message and returns it's signature.
150    pub fn sign_prehashed(&self, hash: &[u8]) -> Result<Signature> {
151        Ok(match self {
152            SecretKey::EcdsaSecp256k1(secret) => {
153                Signature::EcdsaSecp256k1(secret.sign_prehash(hash)?)
154            }
155            SecretKey::EcdsaRecoverableSecp256k1(secret) => {
156                let (sig, recid) = secret
157                    .as_nonzero_scalar()
158                    .try_sign_prehashed_rfc6979::<sha2::Sha256>(hash.try_into()?, b"")?;
159                Signature::EcdsaRecoverableSecp256k1(sig, recid.context("no recovery id")?)
160            }
161            SecretKey::EcdsaSecp256r1(secret) => {
162                Signature::EcdsaSecp256r1(secret.sign_prehash(hash)?)
163            }
164            SecretKey::Ed25519(_) => anyhow::bail!("unimplemented"),
165            SecretKey::Sr25519(_, _) => {
166                anyhow::bail!("unsupported")
167            }
168        })
169    }
170}
171
172/// Public key used for verifying signatures.
173#[derive(Clone, Copy, Debug, Eq, PartialEq)]
174pub enum PublicKey {
175    /// ECDSA with secp256k1.
176    EcdsaSecp256k1(ecdsa::VerifyingKey<k256::Secp256k1>),
177    /// ECDSA with secp256k1 in Ethereum compatible format.
178    EcdsaRecoverableSecp256k1(ecdsa::VerifyingKey<k256::Secp256k1>),
179    /// ECDSA with NIST P-256.
180    EcdsaSecp256r1(ecdsa::VerifyingKey<p256::NistP256>),
181    /// Ed25519.
182    Ed25519(ed25519_dalek::PublicKey),
183    /// Schnorrkel used by substrate/polkadot.
184    Sr25519(schnorrkel::PublicKey),
185}
186
187impl PublicKey {
188    /// Returns the signing algorithm.
189    pub fn algorithm(&self) -> Algorithm {
190        match self {
191            PublicKey::EcdsaSecp256k1(_) => Algorithm::EcdsaSecp256k1,
192            PublicKey::EcdsaRecoverableSecp256k1(_) => Algorithm::EcdsaRecoverableSecp256k1,
193            PublicKey::EcdsaSecp256r1(_) => Algorithm::EcdsaSecp256r1,
194            PublicKey::Ed25519(_) => Algorithm::Ed25519,
195            PublicKey::Sr25519(_) => Algorithm::Sr25519,
196        }
197    }
198
199    /// Creates a public key from a byte sequence for a given signing algorithm.
200    pub fn from_bytes(algorithm: Algorithm, bytes: &[u8]) -> Result<Self> {
201        Ok(match algorithm {
202            Algorithm::EcdsaSecp256k1 => {
203                PublicKey::EcdsaSecp256k1(ecdsa::VerifyingKey::from_sec1_bytes(bytes)?)
204            }
205            Algorithm::EcdsaRecoverableSecp256k1 => {
206                PublicKey::EcdsaRecoverableSecp256k1(ecdsa::VerifyingKey::from_sec1_bytes(bytes)?)
207            }
208            Algorithm::EcdsaSecp256r1 => {
209                PublicKey::EcdsaSecp256r1(ecdsa::VerifyingKey::from_sec1_bytes(bytes)?)
210            }
211            Algorithm::Ed25519 => PublicKey::Ed25519(ed25519_dalek::PublicKey::from_bytes(bytes)?),
212            Algorithm::Sr25519 => {
213                let public = schnorrkel::PublicKey::from_bytes(bytes)
214                    .map_err(|err| anyhow::anyhow!("{}", err))?;
215                PublicKey::Sr25519(public)
216            }
217        })
218    }
219
220    /// Returns a byte sequence representing the public key.
221    pub fn to_bytes(&self) -> Vec<u8> {
222        match self {
223            PublicKey::EcdsaSecp256k1(public) => public.to_encoded_point(true).as_bytes().to_vec(),
224            PublicKey::EcdsaRecoverableSecp256k1(public) => {
225                public.to_encoded_point(true).as_bytes().to_vec()
226            }
227            PublicKey::EcdsaSecp256r1(public) => public.to_encoded_point(true).as_bytes().to_vec(),
228            PublicKey::Ed25519(public) => public.to_bytes().to_vec(),
229            PublicKey::Sr25519(public) => public.to_bytes().to_vec(),
230        }
231    }
232
233    /// Returns an uncompressed byte sequence representing the public key.
234    pub fn to_uncompressed_bytes(&self) -> Vec<u8> {
235        match self {
236            PublicKey::EcdsaSecp256k1(public) => public.to_encoded_point(false).as_bytes().to_vec(),
237            PublicKey::EcdsaRecoverableSecp256k1(public) => {
238                public.to_encoded_point(false).as_bytes().to_vec()
239            }
240            PublicKey::EcdsaSecp256r1(public) => public.to_encoded_point(false).as_bytes().to_vec(),
241            PublicKey::Ed25519(public) => public.to_bytes().to_vec(),
242            PublicKey::Sr25519(public) => public.to_bytes().to_vec(),
243        }
244    }
245
246    /// Verifies a signature.
247    pub fn verify(&self, msg: &[u8], sig: &Signature) -> Result<()> {
248        match (self, &sig) {
249            (PublicKey::EcdsaSecp256k1(public), Signature::EcdsaSecp256k1(sig)) => {
250                public.verify(msg, sig)?
251            }
252            (
253                PublicKey::EcdsaRecoverableSecp256k1(public),
254                Signature::EcdsaRecoverableSecp256k1(sig, _),
255            ) => public.verify(msg, sig)?,
256            (PublicKey::EcdsaSecp256r1(public), Signature::EcdsaSecp256r1(sig)) => {
257                public.verify(msg, sig)?
258            }
259            (PublicKey::Ed25519(public), Signature::Ed25519(sig)) => public.verify(msg, sig)?,
260            (PublicKey::Sr25519(public), Signature::Sr25519(sig)) => {
261                public
262                    .verify_simple(&[], msg, sig)
263                    .map_err(|err| anyhow::anyhow!("{}", err))?;
264            }
265            (_, _) => anyhow::bail!("unsupported signature scheme"),
266        };
267        Ok(())
268    }
269}
270
271/// Signature.
272#[derive(Clone, Copy, Debug, Eq, PartialEq)]
273pub enum Signature {
274    /// ECDSA with secp256k1.
275    EcdsaSecp256k1(ecdsa::Signature<k256::Secp256k1>),
276    /// ECDSA with secp256k1 in Ethereum compatible format.
277    EcdsaRecoverableSecp256k1(ecdsa::Signature<k256::Secp256k1>, RecoveryId),
278    /// ECDSA with NIST P-256.
279    EcdsaSecp256r1(ecdsa::Signature<p256::NistP256>),
280    /// Ed25519.
281    Ed25519(ed25519_dalek::Signature),
282    /// Schnorrkel used by substrate/polkadot.
283    Sr25519(schnorrkel::Signature),
284}
285
286impl Signature {
287    /// Returns the signing algorithm.
288    pub fn algorithm(&self) -> Algorithm {
289        match self {
290            Signature::EcdsaSecp256k1(_) => Algorithm::EcdsaSecp256k1,
291            Signature::EcdsaRecoverableSecp256k1(_, _) => Algorithm::EcdsaRecoverableSecp256k1,
292            Signature::EcdsaSecp256r1(_) => Algorithm::EcdsaSecp256r1,
293            Signature::Ed25519(_) => Algorithm::Ed25519,
294            Signature::Sr25519(_) => Algorithm::Sr25519,
295        }
296    }
297
298    /// Creates a signature from a byte sequence for a given signing algorithm.
299    pub fn from_bytes(algorithm: Algorithm, bytes: &[u8]) -> Result<Self> {
300        Ok(match algorithm {
301            Algorithm::EcdsaSecp256k1 => {
302                Signature::EcdsaSecp256k1(ecdsa::Signature::try_from(bytes)?)
303            }
304            Algorithm::EcdsaRecoverableSecp256k1 => Signature::EcdsaRecoverableSecp256k1(
305                ecdsa::Signature::try_from(&bytes[..64])?,
306                RecoveryId::from_byte(bytes[64]).context("invalid signature")?,
307            ),
308            Algorithm::EcdsaSecp256r1 => {
309                Signature::EcdsaSecp256r1(ecdsa::Signature::try_from(bytes)?)
310            }
311            Algorithm::Ed25519 => Signature::Ed25519(ed25519_dalek::Signature::from_bytes(bytes)?),
312            Algorithm::Sr25519 => {
313                let sig = schnorrkel::Signature::from_bytes(bytes)
314                    .map_err(|err| anyhow::anyhow!("{}", err))?;
315                Signature::Sr25519(sig)
316            }
317        })
318    }
319
320    /// Returns a byte sequence representing the signature.
321    pub fn to_bytes(&self) -> Vec<u8> {
322        match self {
323            Signature::EcdsaSecp256k1(sig) => sig.to_vec(),
324            Signature::EcdsaRecoverableSecp256k1(sig, recovery_id) => {
325                let mut bytes = Vec::with_capacity(65);
326                bytes.extend(sig.to_bytes());
327                bytes.push(recovery_id.to_byte());
328                bytes
329            }
330            Signature::EcdsaSecp256r1(sig) => sig.to_vec(),
331            Signature::Ed25519(sig) => sig.to_bytes().to_vec(),
332            Signature::Sr25519(sig) => sig.to_bytes().to_vec(),
333        }
334    }
335
336    /// Returns the recovered public key if supported.
337    pub fn recover(&self, msg: &[u8]) -> Result<Option<PublicKey>> {
338        if let Signature::EcdsaRecoverableSecp256k1(signature, recovery_id) = self {
339            let recovered_key =
340                ecdsa::VerifyingKey::recover_from_msg(msg, signature, *recovery_id)?;
341            Ok(Some(PublicKey::EcdsaRecoverableSecp256k1(recovered_key)))
342        } else {
343            Ok(None)
344        }
345    }
346
347    /// Returns the recovered public key if supported.
348    pub fn recover_prehashed(&self, hash: &[u8]) -> Result<Option<PublicKey>> {
349        if let Signature::EcdsaRecoverableSecp256k1(signature, recovery_id) = self {
350            let recovered_key =
351                ecdsa::VerifyingKey::recover_from_prehash(hash, signature, *recovery_id)?;
352            Ok(Some(PublicKey::EcdsaRecoverableSecp256k1(recovered_key)))
353        } else {
354            Ok(None)
355        }
356    }
357}
358
359#[cfg(test)]
360mod tests {
361    use super::*;
362    use rand::{thread_rng, RngCore};
363
364    const ALGORITHMS: &[Algorithm] = &[
365        Algorithm::EcdsaSecp256k1,
366        Algorithm::EcdsaRecoverableSecp256k1,
367        Algorithm::EcdsaSecp256r1,
368        Algorithm::Ed25519,
369        Algorithm::Sr25519,
370    ];
371
372    #[test]
373    fn secret_key_bytes() -> Result<()> {
374        let mut rng = thread_rng();
375        let mut secret = [0; 32];
376        rng.fill_bytes(&mut secret);
377        for curve in ALGORITHMS {
378            let secret_key = SecretKey::from_bytes(*curve, &secret[..])?;
379            let secret2 = secret_key.to_bytes();
380            assert_eq!(&secret[..], secret2);
381        }
382        Ok(())
383    }
384
385    #[test]
386    fn public_key_bytes() -> Result<()> {
387        let mut rng = thread_rng();
388        let mut secret = [0; 32];
389        rng.fill_bytes(&mut secret);
390        for algorithm in ALGORITHMS {
391            let secret_key = SecretKey::from_bytes(*algorithm, &secret[..])?;
392            let public_key = secret_key.public_key();
393            let public = public_key.to_bytes();
394            let public_key2 = PublicKey::from_bytes(*algorithm, &public)?;
395            assert_eq!(public_key, public_key2);
396        }
397        Ok(())
398    }
399
400    #[test]
401    fn signature_bytes() -> Result<()> {
402        let mut rng = thread_rng();
403        let mut secret = [0; 32];
404        rng.fill_bytes(&mut secret);
405        let mut msg = [0; 32];
406        rng.fill_bytes(&mut msg);
407        for algorithm in ALGORITHMS {
408            let secret_key = SecretKey::from_bytes(*algorithm, &secret[..])?;
409            let signature = secret_key.sign(&msg, "");
410            let sig = signature.to_bytes();
411            let signature2 = Signature::from_bytes(*algorithm, &sig[..])?;
412            assert_eq!(signature, signature2);
413        }
414        Ok(())
415    }
416
417    #[test]
418    fn sign_verify() -> Result<()> {
419        let mut rng = thread_rng();
420        let mut secret = [0; 32];
421        rng.fill_bytes(&mut secret);
422        let mut msg = [0; 32];
423        rng.fill_bytes(&mut msg);
424        for algorithm in ALGORITHMS {
425            let secret_key = SecretKey::from_bytes(*algorithm, &secret[..])?;
426            let public_key = secret_key.public_key();
427            let signature = secret_key.sign(&msg, "");
428            public_key.verify(&msg, &signature)?;
429        }
430        Ok(())
431    }
432
433    #[test]
434    fn sign_recover_pubkey() -> Result<()> {
435        let mut rng = thread_rng();
436        let mut secret = [0; 32];
437        rng.fill_bytes(&mut secret);
438        let mut msg = [0; 32];
439        rng.fill_bytes(&mut msg);
440        let secret_key = SecretKey::from_bytes(Algorithm::EcdsaRecoverableSecp256k1, &secret[..])?;
441        let public_key = secret_key.public_key();
442        let signature = secret_key.sign(&msg, "");
443        let recovered_key = signature.recover(&msg)?.unwrap();
444        assert_eq!(public_key, recovered_key);
445        Ok(())
446    }
447}