1use 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 fn supports_bip32(self) -> bool {
13 !matches!(self, Algorithm::Sr25519)
14 }
15
16 fn supports_non_hardened_derivation(self) -> bool {
19 !matches!(self, Algorithm::Ed25519)
20 }
21
22 fn uses_bip32_retry(self) -> bool {
24 matches!(
25 self,
26 Algorithm::EcdsaSecp256k1 | Algorithm::EcdsaRecoverableSecp256k1
27 )
28 }
29
30 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#[derive(Clone)]
108pub struct DerivedSecretKey {
109 secret_key: SecretKey,
110 chain_code: [u8; 32],
111}
112
113impl DerivedSecretKey {
114 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 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 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 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 pub fn secret_key(&self) -> &SecretKey {
180 &self.secret_key
181 }
182
183 pub fn chain_code(&self) -> &[u8; 32] {
185 &self.chain_code
186 }
187
188 pub fn public_key(&self) -> DerivedPublicKey {
190 DerivedPublicKey::new(self.secret_key.public_key(), self.chain_code)
191 }
192
193 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 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#[derive(Clone, Copy, Debug, Eq, PartialEq)]
278pub struct DerivedPublicKey {
279 public_key: PublicKey,
280 chain_code: [u8; 32],
281}
282
283impl DerivedPublicKey {
284 pub fn new(public_key: PublicKey, chain_code: [u8; 32]) -> Self {
286 Self {
287 public_key,
288 chain_code,
289 }
290 }
291
292 pub fn public_key(&self) -> &PublicKey {
294 &self.public_key
295 }
296
297 pub fn chain_code(&self) -> &[u8; 32] {
299 &self.chain_code
300 }
301
302 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 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 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 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 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 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 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 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 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 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 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 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 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 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}