rosetta_crypto/
bip32.rs

1//! BIP32 implementation.
2use crate::bip39::Mnemonic;
3use crate::bip44::ChildNumber;
4use crate::{Algorithm, PublicKey, SecretKey};
5use anyhow::Result;
6use hmac::{Hmac, Mac};
7use sha2::Sha512;
8
9impl Algorithm {
10    /// If the algorithm supports BIP32. ECDSA and Ed25519 do, but schnorrkel
11    /// uses it's own hierarchical key derivation algorithm.
12    fn supports_bip32(self) -> bool {
13        !matches!(self, Algorithm::Sr25519)
14    }
15
16    /// If the algorithm supports soft key derivations. ECDSA and schnorrkel
17    /// do, but ed25519 does not.
18    fn supports_non_hardened_derivation(self) -> bool {
19        !matches!(self, Algorithm::Ed25519)
20    }
21
22    /// BIP32 defines a retry procedure for secp256k1.
23    fn uses_bip32_retry(self) -> bool {
24        matches!(
25            self,
26            Algorithm::EcdsaSecp256k1 | Algorithm::EcdsaRecoverableSecp256k1
27        )
28    }
29
30    /// SLIP0010 defines a retry procedure for secp256r1.
31    fn uses_slip10_retry(self) -> bool {
32        matches!(self, Algorithm::EcdsaSecp256r1)
33    }
34}
35
36impl SecretKey {
37    fn tweak_add(&self, secret_key: &SecretKey) -> Result<Option<Self>> {
38        use ecdsa::elliptic_curve::NonZeroScalar;
39        match (self, secret_key) {
40            (SecretKey::EcdsaSecp256k1(secret), SecretKey::EcdsaSecp256k1(secret2))
41            | (
42                SecretKey::EcdsaRecoverableSecp256k1(secret),
43                SecretKey::EcdsaRecoverableSecp256k1(secret2),
44            ) => {
45                let scalar = secret.as_nonzero_scalar().as_ref();
46                let tweak = secret2.as_nonzero_scalar().as_ref();
47                let scalar: Option<NonZeroScalar<_>> =
48                    Option::from(NonZeroScalar::new(scalar + tweak));
49                let signing_key = match scalar {
50                    Some(scalar) => ecdsa::SigningKey::from(scalar),
51                    None => return Ok(None),
52                };
53                Ok(Some(if self.algorithm().is_recoverable() {
54                    SecretKey::EcdsaRecoverableSecp256k1(signing_key)
55                } else {
56                    SecretKey::EcdsaSecp256k1(signing_key)
57                }))
58            }
59            (SecretKey::EcdsaSecp256r1(secret), SecretKey::EcdsaSecp256r1(secret2)) => {
60                let scalar = secret.as_nonzero_scalar().as_ref();
61                let tweak = secret2.as_nonzero_scalar().as_ref();
62                let scalar: Option<NonZeroScalar<_>> =
63                    Option::from(NonZeroScalar::new(scalar + tweak));
64                match scalar {
65                    Some(scalar) => Ok(Some(SecretKey::EcdsaSecp256r1(ecdsa::SigningKey::from(
66                        scalar,
67                    )))),
68                    None => Ok(None),
69                }
70            }
71            _ => anyhow::bail!("unsupported key type"),
72        }
73    }
74}
75
76impl PublicKey {
77    fn tweak_add(&self, tweak: [u8; 32]) -> Result<Option<Self>> {
78        match self {
79            PublicKey::EcdsaSecp256k1(public) | PublicKey::EcdsaRecoverableSecp256k1(public) => {
80                Ok((|| {
81                    let parent_key = k256::ProjectivePoint::from(public.as_affine());
82                    let tweak = k256::NonZeroScalar::try_from(&tweak[..]).ok()?;
83                    let mut tweak_point = k256::ProjectivePoint::GENERATOR * tweak.as_ref();
84                    tweak_point += parent_key;
85                    let public = ecdsa::VerifyingKey::from_affine(tweak_point.to_affine()).ok()?;
86                    Some(if self.algorithm().is_recoverable() {
87                        PublicKey::EcdsaRecoverableSecp256k1(public)
88                    } else {
89                        PublicKey::EcdsaSecp256k1(public)
90                    })
91                })())
92            }
93            PublicKey::EcdsaSecp256r1(public) => Ok((|| {
94                let parent_key = p256::ProjectivePoint::from(public.as_affine());
95                let tweak = p256::NonZeroScalar::try_from(&tweak[..]).ok()?;
96                let mut tweak_point = p256::ProjectivePoint::GENERATOR * tweak.as_ref();
97                tweak_point += parent_key;
98                let public = ecdsa::VerifyingKey::from_affine(tweak_point.to_affine()).ok()?;
99                Some(PublicKey::EcdsaSecp256r1(public))
100            })()),
101            _ => anyhow::bail!("unsupported key type"),
102        }
103    }
104}
105
106/// Secret key and chain code used for hierarchical key derivation.
107#[derive(Clone)]
108pub struct DerivedSecretKey {
109    secret_key: SecretKey,
110    chain_code: [u8; 32],
111}
112
113impl DerivedSecretKey {
114    /// Derives a master key from a mnemonic.
115    pub fn new(mnemonic: &Mnemonic, password: &str, algorithm: Algorithm) -> Result<Self> {
116        if algorithm == Algorithm::Sr25519 {
117            Self::substrate(mnemonic, password, algorithm)
118        } else {
119            Self::bip39(mnemonic, password, algorithm)
120        }
121    }
122
123    /// Derives a master key and chain code from a mnemonic using BIP39.
124    pub fn bip39(mnemonic: &Mnemonic, password: &str, algorithm: Algorithm) -> Result<Self> {
125        let seed = mnemonic.to_seed(password);
126        Self::bip32_master_key(&seed[..], algorithm)
127    }
128
129    /// Derives a BIP32 master key. See SLIP0010 for extension to secp256r1 and ed25519 curves.
130    fn bip32_master_key(seed: &[u8], algorithm: Algorithm) -> Result<Self> {
131        let curve_name = match algorithm {
132            Algorithm::EcdsaSecp256k1 => &b"Bitcoin seed"[..],
133            Algorithm::EcdsaRecoverableSecp256k1 => &b"Bitcoin seed"[..],
134            Algorithm::EcdsaSecp256r1 => &b"Nist256p1 seed"[..],
135            Algorithm::Ed25519 => &b"ed25519 seed"[..],
136            Algorithm::Sr25519 => anyhow::bail!("sr25519 does not support bip32 derivation"),
137        };
138        let mut retry: Option<[u8; 64]> = None;
139        loop {
140            let mut hmac: Hmac<Sha512> = Hmac::new_from_slice(curve_name)?;
141            if let Some(retry) = &retry {
142                hmac.update(retry);
143            } else {
144                hmac.update(seed);
145            }
146            let result = hmac.finalize().into_bytes();
147            let (secret_key, chain_code) = result.split_at(32);
148            let secret_key = if let Ok(secret_key) = SecretKey::from_bytes(algorithm, secret_key) {
149                secret_key
150            } else if algorithm.uses_slip10_retry() {
151                retry = Some(result.into());
152                continue;
153            } else {
154                anyhow::bail!("failed to derive a valid secret key");
155            };
156            return Ok(Self {
157                secret_key,
158                chain_code: chain_code.try_into()?,
159            });
160        }
161    }
162
163    /// Derives a master key and chain code from a mnemonic. This avoids the complex BIP39
164    /// seed generation algorithm which was intended to support brain wallets. Instead it
165    /// uses pbkdf2 using the entropy as the key and password as the salt.
166    pub fn substrate(mnemonic: &Mnemonic, password: &str, algorithm: Algorithm) -> Result<Self> {
167        let (entropy, len) = mnemonic.to_entropy_array();
168        let seed = substrate_bip39::seed_from_entropy(&entropy[..len], password)
169            .map_err(|_| anyhow::anyhow!("invalid entropy"))?;
170        anyhow::ensure!(matches!(algorithm, Algorithm::Ed25519 | Algorithm::Sr25519));
171        let (secret_key, chain_code) = seed.split_at(32);
172        Ok(Self {
173            secret_key: SecretKey::from_bytes(algorithm, secret_key)?,
174            chain_code: chain_code.try_into()?,
175        })
176    }
177
178    /// The secret key used to sign messages.
179    pub fn secret_key(&self) -> &SecretKey {
180        &self.secret_key
181    }
182
183    /// The chain code used to derive child keys.
184    pub fn chain_code(&self) -> &[u8; 32] {
185        &self.chain_code
186    }
187
188    /// Returns the derived public key used for verifying signatures.
189    pub fn public_key(&self) -> DerivedPublicKey {
190        DerivedPublicKey::new(self.secret_key.public_key(), self.chain_code)
191    }
192
193    /// Derive a child key using BIP32. See SLIP0010 for extension to secp256r1 and ed25519
194    /// curves.
195    fn bip32_derive(&self, child: ChildNumber) -> Result<Self> {
196        let algorithm = self.secret_key.algorithm();
197        anyhow::ensure!(algorithm.supports_bip32(), "doesn't support bip32");
198        let mut retry: Option<[u8; 32]> = None;
199        loop {
200            let mut hmac: Hmac<Sha512> = Hmac::new_from_slice(&self.chain_code[..])?;
201            if let Some(retry) = &retry {
202                hmac.update(&[1]);
203                hmac.update(retry);
204            } else if child.is_hardened() {
205                hmac.update(&[0]);
206                hmac.update(&self.secret_key.to_bytes()[..]);
207            } else {
208                anyhow::ensure!(
209                    algorithm.supports_non_hardened_derivation(),
210                    "doesn't support soft derivation"
211                );
212                hmac.update(&self.secret_key.public_key().to_bytes()[..]);
213            }
214            hmac.update(&child.to_bytes());
215
216            let result = hmac.finalize().into_bytes();
217            let (secret_key, chain_code) = result.split_at(32);
218            let chain_code: [u8; 32] = chain_code.try_into()?;
219            retry = Some(chain_code);
220
221            let mut secret_key =
222                if let Ok(secret_key) = SecretKey::from_bytes(algorithm, secret_key) {
223                    secret_key
224                } else if algorithm.uses_slip10_retry() {
225                    continue;
226                } else if algorithm.uses_bip32_retry() {
227                    return self.bip32_derive(child + 1);
228                } else {
229                    anyhow::bail!("failed to derive a valid secret key");
230                };
231
232            if algorithm.supports_non_hardened_derivation() {
233                if let Some(tweaked_secret_key) = secret_key.tweak_add(&self.secret_key)? {
234                    secret_key = tweaked_secret_key;
235                } else if algorithm.uses_slip10_retry() {
236                    continue;
237                } else if algorithm.uses_bip32_retry() {
238                    return self.bip32_derive(child + 1);
239                } else {
240                    anyhow::bail!("invalid tweak");
241                }
242            }
243
244            return Ok(Self {
245                secret_key,
246                chain_code,
247            });
248        }
249    }
250
251    /// Derives a child secret key.
252    pub fn derive(&self, child: ChildNumber) -> Result<Self> {
253        match &self.secret_key {
254            SecretKey::Sr25519(secret, _) => {
255                use schnorrkel::derive::Derivation;
256                let chain_code = schnorrkel::derive::ChainCode(child.to_substrate_chain_code());
257                let (secret, minisecret) = if child.is_hardened() {
258                    let (minisecret, _) = secret.hard_derive_mini_secret_key(Some(chain_code), b"");
259                    let secret =
260                        minisecret.expand_to_keypair(schnorrkel::MiniSecretKey::ED25519_MODE);
261                    (secret, Some(minisecret))
262                } else {
263                    let (secret, _) = secret.derived_key_simple(chain_code, b"");
264                    (secret, None)
265                };
266                Ok(Self {
267                    secret_key: SecretKey::Sr25519(secret, minisecret),
268                    chain_code: chain_code.0,
269                })
270            }
271            _ => self.bip32_derive(child),
272        }
273    }
274}
275
276/// Public key and chain code used for hierarchical key derivation.
277#[derive(Clone, Copy, Debug, Eq, PartialEq)]
278pub struct DerivedPublicKey {
279    public_key: PublicKey,
280    chain_code: [u8; 32],
281}
282
283impl DerivedPublicKey {
284    /// Constructs a derived public key from a public key and a chain code.
285    pub fn new(public_key: PublicKey, chain_code: [u8; 32]) -> Self {
286        Self {
287            public_key,
288            chain_code,
289        }
290    }
291
292    /// The public key used to verify messages.
293    pub fn public_key(&self) -> &PublicKey {
294        &self.public_key
295    }
296
297    /// The chain code used to derive child keys.
298    pub fn chain_code(&self) -> &[u8; 32] {
299        &self.chain_code
300    }
301
302    /// Derive a child key using BIP32. See SLIP0010 for extension to secp256r1 and ed25519
303    /// curves.
304    fn bip32_derive(&self, child: ChildNumber) -> Result<Self> {
305        anyhow::ensure!(child.is_normal(), "can't derive a hardened public key");
306        let algorithm = self.public_key.algorithm();
307        anyhow::ensure!(algorithm.supports_bip32(), "doesn't support bip32");
308        anyhow::ensure!(
309            algorithm.supports_non_hardened_derivation(),
310            "doesn't support soft derivation"
311        );
312        let mut retry: Option<[u8; 32]> = None;
313        loop {
314            let mut hmac: Hmac<Sha512> = Hmac::new_from_slice(&self.chain_code[..])?;
315            if let Some(retry) = &retry {
316                hmac.update(&[1]);
317                hmac.update(retry);
318            } else {
319                hmac.update(&self.public_key.to_bytes()[..]);
320            }
321            hmac.update(&child.to_bytes());
322            let result = hmac.finalize().into_bytes();
323            let (public_key, chain_code) = result.split_at(32);
324            let public_key: [u8; 32] = public_key.try_into()?;
325            let chain_code: [u8; 32] = chain_code.try_into()?;
326
327            let public_key = if let Some(public_key) = self.public_key.tweak_add(public_key)? {
328                public_key
329            } else if algorithm.uses_slip10_retry() {
330                retry = Some(chain_code);
331                continue;
332            } else if algorithm.uses_bip32_retry() {
333                return self.bip32_derive(child + 1);
334            } else {
335                anyhow::bail!("failed to derive a valid public key");
336            };
337
338            return Ok(Self {
339                public_key,
340                chain_code,
341            });
342        }
343    }
344
345    /// Derives a child public key.
346    pub fn derive(&self, child: ChildNumber) -> Result<Self> {
347        anyhow::ensure!(child.is_normal(), "can't derive a hardened public key");
348        match &self.public_key {
349            PublicKey::Sr25519(public) => {
350                use schnorrkel::derive::Derivation;
351                let chain_code = schnorrkel::derive::ChainCode(child.to_substrate_chain_code());
352                let (public, _) = public.derived_key_simple(chain_code, b"");
353                Ok(Self {
354                    public_key: PublicKey::Sr25519(public),
355                    chain_code: chain_code.0,
356                })
357            }
358            _ => self.bip32_derive(child),
359        }
360    }
361}
362
363#[cfg(test)]
364mod tests {
365    use super::*;
366    use bip39::Language;
367
368    struct DerivedKey {
369        secret: DerivedSecretKey,
370        public: DerivedPublicKey,
371    }
372
373    impl DerivedKey {
374        fn new(algorithm: Algorithm, mnemonic: &str) -> Result<Self> {
375            let mnemonic = Mnemonic::parse_in(Language::English, mnemonic)?;
376            let secret = DerivedSecretKey::new(&mnemonic, "", algorithm)?;
377            let public = secret.public_key();
378            Ok(Self { secret, public })
379        }
380
381        fn bip32_master_key(algorithm: Algorithm, seed: &str) -> Result<Self> {
382            let secret = DerivedSecretKey::bip32_master_key(&hex::decode(seed)?[..], algorithm)?;
383            let public = secret.public_key();
384            Ok(Self { secret, public })
385        }
386
387        fn bip32_derive(&self, child: ChildNumber) -> Result<Self> {
388            let secret = self.secret.derive(child)?;
389            let public = secret.public_key();
390            if child.is_normal() {
391                let public2 = self.public.derive(child)?;
392                assert_eq!(public, public2);
393            }
394            Ok(Self { secret, public })
395        }
396
397        fn assert(&self, chain_code: &str, private: &str, public: &str) {
398            assert_eq!(
399                hex::encode(self.secret.chain_code()),
400                chain_code,
401                "secret chain code"
402            );
403            assert_eq!(
404                // in sr25519 soft derivations the nonce part of the secret key is computed
405                // randomly so only the first 32 bytes are deterministic. all other keys are
406                // 32 bytes long.
407                hex::encode(&self.secret.secret_key().to_bytes()[..32]),
408                private,
409                "secret key"
410            );
411            assert_eq!(
412                hex::encode(self.public.chain_code()),
413                chain_code,
414                "secret chain code"
415            );
416            assert_eq!(
417                hex::encode(self.public.public_key().to_bytes()),
418                public,
419                "public key"
420            );
421        }
422
423        fn assert_bip32(&self, xprv: &str, xpub: &str) {
424            assert_eq!(&xprv[..4], "xprv");
425            assert_eq!(&xpub[..4], "xpub");
426            let xprv = bs58::decode(xprv)
427                .with_alphabet(bs58::Alphabet::BITCOIN)
428                .into_vec()
429                .unwrap();
430            let xpub = bs58::decode(xpub)
431                .with_alphabet(bs58::Alphabet::BITCOIN)
432                .into_vec()
433                .unwrap();
434            let chain_code1 = &xprv[13..45];
435            let chain_code2 = &xpub[13..45];
436            assert_eq!(chain_code1, chain_code2);
437            let chain_code = hex::encode(chain_code1);
438            let private = hex::encode(&xprv[46..78]);
439            let public = hex::encode(&xpub[45..78]);
440            self.assert(&chain_code, &private, &public);
441        }
442    }
443
444    #[test]
445    fn bip32_derive_secp256k1_1() -> Result<()> {
446        // test vectors from SLIP0010
447        for algorithm in [
448            Algorithm::EcdsaSecp256k1,
449            Algorithm::EcdsaRecoverableSecp256k1,
450        ] {
451            let key = DerivedKey::bip32_master_key(algorithm, "000102030405060708090a0b0c0d0e0f")?;
452            key.assert(
453                "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508",
454                "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35",
455                "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2",
456            );
457            let key = key.bip32_derive(ChildNumber::hardened_from_u32(0))?;
458            key.assert(
459                "47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141",
460                "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea",
461                "035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56",
462            );
463            let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(1))?;
464            key.assert(
465                "2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19",
466                "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368",
467                "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c",
468            );
469            let key = key.bip32_derive(ChildNumber::hardened_from_u32(2))?;
470            key.assert(
471                "04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f",
472                "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca",
473                "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2",
474            );
475            let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(2))?;
476            key.assert(
477                "cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd",
478                "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4",
479                "02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29",
480            );
481            let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(1000000000))?;
482            key.assert(
483                "c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e",
484                "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8",
485                "022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011",
486            );
487        }
488        Ok(())
489    }
490
491    #[test]
492    fn bip32_derive_secp256r1_1() -> Result<()> {
493        // test vectors from SLIP0010
494        let key = DerivedKey::bip32_master_key(
495            Algorithm::EcdsaSecp256r1,
496            "000102030405060708090a0b0c0d0e0f",
497        )?;
498        key.assert(
499            "beeb672fe4621673f722f38529c07392fecaa61015c80c34f29ce8b41b3cb6ea",
500            "612091aaa12e22dd2abef664f8a01a82cae99ad7441b7ef8110424915c268bc2",
501            "0266874dc6ade47b3ecd096745ca09bcd29638dd52c2c12117b11ed3e458cfa9e8",
502        );
503        let key = key.bip32_derive(ChildNumber::hardened_from_u32(0))?;
504        key.assert(
505            "3460cea53e6a6bb5fb391eeef3237ffd8724bf0a40e94943c98b83825342ee11",
506            "6939694369114c67917a182c59ddb8cafc3004e63ca5d3b84403ba8613debc0c",
507            "0384610f5ecffe8fda089363a41f56a5c7ffc1d81b59a612d0d649b2d22355590c",
508        );
509        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(1))?;
510        key.assert(
511            "4187afff1aafa8445010097fb99d23aee9f599450c7bd140b6826ac22ba21d0c",
512            "284e9d38d07d21e4e281b645089a94f4cf5a5a81369acf151a1c3a57f18b2129",
513            "03526c63f8d0b4bbbf9c80df553fe66742df4676b241dabefdef67733e070f6844",
514        );
515        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2))?;
516        key.assert(
517            "98c7514f562e64e74170cc3cf304ee1ce54d6b6da4f880f313e8204c2a185318",
518            "694596e8a54f252c960eb771a3c41e7e32496d03b954aeb90f61635b8e092aa7",
519            "0359cf160040778a4b14c5f4d7b76e327ccc8c4a6086dd9451b7482b5a4972dda0",
520        );
521        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(2))?;
522        key.assert(
523            "ba96f776a5c3907d7fd48bde5620ee374d4acfd540378476019eab70790c63a0",
524            "5996c37fd3dd2679039b23ed6f70b506c6b56b3cb5e424681fb0fa64caf82aaa",
525            "029f871f4cb9e1c97f9f4de9ccd0d4a2f2a171110c61178f84430062230833ff20",
526        );
527        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(1000000000))?;
528        key.assert(
529            "b9b7b82d326bb9cb5b5b121066feea4eb93d5241103c9e7a18aad40f1dde8059",
530            "21c4f269ef0a5fd1badf47eeacebeeaa3de22eb8e5b0adcd0f27dd99d34d0119",
531            "02216cd26d31147f72427a453c443ed2cde8a1e53c9cc44e5ddf739725413fe3f4",
532        );
533        Ok(())
534    }
535
536    #[test]
537    fn bip32_derive_ed25519_1() -> Result<()> {
538        // test vectors from SLIP0010
539        let key =
540            DerivedKey::bip32_master_key(Algorithm::Ed25519, "000102030405060708090a0b0c0d0e0f")?;
541        key.assert(
542            "90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb",
543            "2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7",
544            "a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed",
545        );
546        let key = key.bip32_derive(ChildNumber::hardened_from_u32(0))?;
547        key.assert(
548            "8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69",
549            "68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3",
550            "8c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c",
551        );
552        let key = key.bip32_derive(ChildNumber::hardened_from_u32(1))?;
553        key.assert(
554            "a320425f77d1b5c2505a6b1b27382b37368ee640e3557c315416801243552f14",
555            "b1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2",
556            "1932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187",
557        );
558        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2))?;
559        key.assert(
560            "2e69929e00b5ab250f49c3fb1c12f252de4fed2c1db88387094a0f8c4c9ccd6c",
561            "92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9",
562            "ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1",
563        );
564        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2))?;
565        key.assert(
566            "8f6d87f93d750e0efccda017d662a1b31a266e4a6f5993b15f5c1f07f74dd5cc",
567            "30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662",
568            "8abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c",
569        );
570        let key = key.bip32_derive(ChildNumber::hardened_from_u32(1000000000))?;
571        key.assert(
572            "68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230",
573            "8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793",
574            "3c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a",
575        );
576        Ok(())
577    }
578
579    #[test]
580    fn bip32_derive_sr25519_1() -> Result<()> {
581        // test vectors generated with subkey
582        let key = DerivedKey::new(
583            Algorithm::Sr25519,
584            "clip pulse sausage soap mom era engine trip hammer leg genre figure",
585        )?;
586        key.assert(
587            "7c7bf55246e1fa6905060b061524fc67a827862f7f296d703fdbb8b9f331415c",
588            "2c7e70992e4d2490ede2d341669ac3f8ae526bd6e58ba520a5066485cc7a0007",
589            "849570b7449e65a5adc6baf48e44720a55aabf567d37e0313b9ed8c93c80736e",
590        );
591        let key = key.bip32_derive(ChildNumber::hardened_from_u32(0))?;
592        key.assert(
593            "0000000000000000000000000000000000000000000000000000000000000000",
594            "4652b03d0cd6e166849641bd08e70334d75a4ec29c7b8320ab269785724a5674",
595            "f6bb71fdfdbbc8f20cce86c1e46883d17afe929271768ce5e7c075e420e3e120",
596        );
597        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(1))?;
598        key.assert(
599            "0100000000000000000000000000000000000000000000000000000000000000",
600            "7b0c8366993f9c22cf34e099f0b8cfa70fc43dca186d3590651c00f67daa8504",
601            "baf3a16c76aaff29d82cf0e5cda6e2af6c780f34a5d2af787591941ec7b5530e",
602        );
603        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2))?;
604        key.assert(
605            "0200000000000000000000000000000000000000000000000000000000000000",
606            "6e8562fe4330e3d106ff914da8d1832255f18da375831eddd61b5542bb466708",
607            "38c099de5c3faa4829605532b8a6a2d1731ae823dd1dd90549c813042d3cc23b",
608        );
609        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(2))?;
610        key.assert(
611            "0200000000000000000000000000000000000000000000000000000000000000",
612            "5bdcd9d165e7e7f2c27c3e98edd10cc5f50a07dbd69b0e49171f531dae11890e",
613            "da7b3bb8a92351f89c4a996561c8323fd534c9a6a6f713ffce316e0e95169c58",
614        );
615        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(1000000000))?;
616        key.assert(
617            "00ca9a3b00000000000000000000000000000000000000000000000000000000",
618            "8800b77abcbe366d2afa4c65e1c47884e5cd0ff81824d7cb10b8a3aa2a044a0f",
619            "34f13d95d72cbe597ca298eaa18f27f3e4d75217a8ab1230b243f7ebae29e45b",
620        );
621        Ok(())
622    }
623
624    const SEED2: &str = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542";
625
626    #[test]
627    fn bip32_derive_secp256k1_2() -> Result<()> {
628        // test vectors from SLIP0010
629        for algorithm in [
630            Algorithm::EcdsaSecp256k1,
631            Algorithm::EcdsaRecoverableSecp256k1,
632        ] {
633            let key = DerivedKey::bip32_master_key(algorithm, SEED2)?;
634            key.assert(
635                "60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689",
636                "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e",
637                "03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7",
638            );
639            let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(0))?;
640            key.assert(
641                "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c",
642                "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e",
643                "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea",
644            );
645            let key = key.bip32_derive(ChildNumber::hardened_from_u32(2147483647))?;
646            key.assert(
647                "be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9",
648                "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93",
649                "03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b",
650            );
651            let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(1))?;
652            key.assert(
653                "f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb",
654                "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7",
655                "03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9",
656            );
657            let key = key.bip32_derive(ChildNumber::hardened_from_u32(2147483646))?;
658            key.assert(
659                "637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29",
660                "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d",
661                "02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0",
662            );
663            let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(2))?;
664            key.assert(
665                "9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271",
666                "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23",
667                "024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c",
668            );
669        }
670        Ok(())
671    }
672
673    #[test]
674    fn bip32_derive_secp256r1_2() -> Result<()> {
675        // test vectors from SLIP0010
676        let key = DerivedKey::bip32_master_key(Algorithm::EcdsaSecp256r1, SEED2)?;
677        key.assert(
678            "96cd4465a9644e31528eda3592aa35eb39a9527769ce1855beafc1b81055e75d",
679            "eaa31c2e46ca2962227cf21d73a7ef0ce8b31c756897521eb6c7b39796633357",
680            "02c9e16154474b3ed5b38218bb0463e008f89ee03e62d22fdcc8014beab25b48fa",
681        );
682        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(0))?;
683        key.assert(
684            "84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a",
685            "d7d065f63a62624888500cdb4f88b6d59c2927fee9e6d0cdff9cad555884df6e",
686            "039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc",
687        );
688        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2147483647))?;
689        key.assert(
690            "f235b2bc5c04606ca9c30027a84f353acf4e4683edbd11f635d0dcc1cd106ea6",
691            "96d2ec9316746a75e7793684ed01e3d51194d81a42a3276858a5b7376d4b94b9",
692            "02f89c5deb1cae4fedc9905f98ae6cbf6cbab120d8cb85d5bd9a91a72f4c068c76",
693        );
694        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(1))?;
695        key.assert(
696            "7c0b833106235e452eba79d2bdd58d4086e663bc8cc55e9773d2b5eeda313f3b",
697            "974f9096ea6873a915910e82b29d7c338542ccde39d2064d1cc228f371542bbc",
698            "03abe0ad54c97c1d654c1852dfdc32d6d3e487e75fa16f0fd6304b9ceae4220c64",
699        );
700        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2147483646))?;
701        key.assert(
702            "5794e616eadaf33413aa309318a26ee0fd5163b70466de7a4512fd4b1a5c9e6a",
703            "da29649bbfaff095cd43819eda9a7be74236539a29094cd8336b07ed8d4eff63",
704            "03cb8cb067d248691808cd6b5a5a06b48e34ebac4d965cba33e6dc46fe13d9b933",
705        );
706        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(2))?;
707        key.assert(
708            "3bfb29ee8ac4484f09db09c2079b520ea5616df7820f071a20320366fbe226a7",
709            "bb0a77ba01cc31d77205d51d08bd313b979a71ef4de9b062f8958297e746bd67",
710            "020ee02e18967237cf62672983b253ee62fa4dd431f8243bfeccdf39dbe181387f",
711        );
712        Ok(())
713    }
714
715    #[test]
716    fn bip32_derive_ed25519_2() -> Result<()> {
717        // test vectors from SLIP0010
718        let key = DerivedKey::bip32_master_key(Algorithm::Ed25519, SEED2)?;
719        key.assert(
720            "ef70a74db9c3a5af931b5fe73ed8e1a53464133654fd55e7a66f8570b8e33c3b",
721            "171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012",
722            "8fe9693f8fa62a4305a140b9764c5ee01e455963744fe18204b4fb948249308a",
723        );
724        let key = key.bip32_derive(ChildNumber::hardened_from_u32(0))?;
725        key.assert(
726            "0b78a3226f915c082bf118f83618a618ab6dec793752624cbeb622acb562862d",
727            "1559eb2bbec5790b0c65d8693e4d0875b1747f4970ae8b650486ed7470845635",
728            "86fab68dcb57aa196c77c5f264f215a112c22a912c10d123b0d03c3c28ef1037",
729        );
730        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2147483647))?;
731        key.assert(
732            "138f0b2551bcafeca6ff2aa88ba8ed0ed8de070841f0c4ef0165df8181eaad7f",
733            "ea4f5bfe8694d8bb74b7b59404632fd5968b774ed545e810de9c32a4fb4192f4",
734            "5ba3b9ac6e90e83effcd25ac4e58a1365a9e35a3d3ae5eb07b9e4d90bcf7506d",
735        );
736        let key = key.bip32_derive(ChildNumber::hardened_from_u32(1))?;
737        key.assert(
738            "73bd9fff1cfbde33a1b846c27085f711c0fe2d66fd32e139d3ebc28e5a4a6b90",
739            "3757c7577170179c7868353ada796c839135b3d30554bbb74a4b1e4a5a58505c",
740            "2e66aa57069c86cc18249aecf5cb5a9cebbfd6fadeab056254763874a9352b45",
741        );
742        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2147483646))?;
743        key.assert(
744            "0902fe8a29f9140480a00ef244bd183e8a13288e4412d8389d140aac1794825a",
745            "5837736c89570de861ebc173b1086da4f505d4adb387c6a1b1342d5e4ac9ec72",
746            "e33c0f7d81d843c572275f287498e8d408654fdf0d1e065b84e2e6f157aab09b",
747        );
748        let key = key.bip32_derive(ChildNumber::hardened_from_u32(2))?;
749        key.assert(
750            "5d70af781f3a37b829f0d060924d5e960bdc02e85423494afc0b1a41bbe196d4",
751            "551d333177df541ad876a60ea71f00447931c0a9da16f227c11ea080d7391b8d",
752            "47150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0",
753        );
754        Ok(())
755    }
756
757    #[test]
758    fn bip32_retry_derive_secp256r1() -> Result<()> {
759        // test vectors from SLIP0010
760        let seed = "000102030405060708090a0b0c0d0e0f";
761        let key = DerivedKey::bip32_master_key(Algorithm::EcdsaSecp256r1, seed)?;
762        key.assert(
763            "beeb672fe4621673f722f38529c07392fecaa61015c80c34f29ce8b41b3cb6ea",
764            "612091aaa12e22dd2abef664f8a01a82cae99ad7441b7ef8110424915c268bc2",
765            "0266874dc6ade47b3ecd096745ca09bcd29638dd52c2c12117b11ed3e458cfa9e8",
766        );
767        let key = key.bip32_derive(ChildNumber::hardened_from_u32(28578))?;
768        key.assert(
769            "e94c8ebe30c2250a14713212f6449b20f3329105ea15b652ca5bdfc68f6c65c2",
770            "06f0db126f023755d0b8d86d4591718a5210dd8d024e3e14b6159d63f53aa669",
771            "02519b5554a4872e8c9c1c847115363051ec43e93400e030ba3c36b52a3e70a5b7",
772        );
773        let key = key.bip32_derive(ChildNumber::non_hardened_from_u32(33941))?;
774        key.assert(
775            "9e87fe95031f14736774cd82f25fd885065cb7c358c1edf813c72af535e83071",
776            "092154eed4af83e078ff9b84322015aefe5769e31270f62c3f66c33888335f3a",
777            "0235bfee614c0d5b2cae260000bb1d0d84b270099ad790022c1ae0b2e782efe120",
778        );
779        Ok(())
780    }
781
782    #[test]
783    fn bip32_retry_seed_secp256r1() -> Result<()> {
784        // test vectors from SLIP0010
785        let seed = "a7305bc8df8d0951f0cb224c0e95d7707cbdf2c6ce7e8d481fec69c7ff5e9446";
786        let key = DerivedKey::bip32_master_key(Algorithm::EcdsaSecp256r1, seed)?;
787        key.assert(
788            "7762f9729fed06121fd13f326884c82f59aa95c57ac492ce8c9654e60efd130c",
789            "3b8c18469a4634517d6d0b65448f8e6c62091b45540a1743c5846be55d47d88f",
790            "0383619fadcde31063d8c5cb00dbfe1713f3e6fa169d8541a798752a1c1ca0cb20",
791        );
792        Ok(())
793    }
794
795    #[test]
796    fn bip32_derive_secp256k1_3() -> Result<()> {
797        // test vector 3 from BIP32
798        let seed = "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be";
799        let key = DerivedKey::bip32_master_key(Algorithm::EcdsaSecp256k1, seed)?;
800        key.assert_bip32(
801            "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
802            "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13",
803        );
804        let key = key.bip32_derive(ChildNumber::hardened_from_u32(0))?;
805        key.assert_bip32(
806            "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
807            "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y",
808        );
809        Ok(())
810    }
811
812    #[test]
813    fn bip32_derive_secp256k1_4() -> Result<()> {
814        // test vector 4 from BIP32
815        let seed = "3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678";
816        let key = DerivedKey::bip32_master_key(Algorithm::EcdsaSecp256k1, seed)?;
817        key.assert_bip32(
818            "xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv",
819            "xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa",
820        );
821        let key = key.bip32_derive(ChildNumber::hardened_from_u32(0))?;
822        key.assert_bip32(
823            "xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G",
824            "xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m",
825        );
826        let key = key.bip32_derive(ChildNumber::hardened_from_u32(1))?;
827        key.assert_bip32(
828            "xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1",
829            "xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt",
830        );
831        Ok(())
832    }
833}