1pub use self::derivation::Error as DerivationError;
20use crate::{secret::Secret, Public};
21use cfx_types::H256;
22
23pub trait Label {
25 fn len() -> usize;
27
28 fn store(&self, target: &mut [u8]);
31}
32
33impl Label for u32 {
34 fn len() -> usize { 4 }
35
36 fn store(&self, target: &mut [u8]) {
37 let bytes = self.to_be_bytes();
38 target[0..4].copy_from_slice(&bytes);
39 }
40}
41
42pub enum Derivation<T: Label> {
44 Soft(T),
46 Hard(T),
48}
49
50impl From<u32> for Derivation<u32> {
51 fn from(index: u32) -> Self {
52 if index < (2 << 30) {
53 Derivation::Soft(index)
54 } else {
55 Derivation::Hard(index)
56 }
57 }
58}
59
60impl Label for H256 {
61 fn len() -> usize { Self::len_bytes() }
62
63 fn store(&self, target: &mut [u8]) {
64 (&mut target[0..32]).copy_from_slice(self.as_bytes());
65 }
66}
67
68pub struct ExtendedSecret {
70 secret: Secret,
71 chain_code: H256,
72}
73
74impl ExtendedSecret {
75 pub fn with_code(secret: Secret, chain_code: H256) -> ExtendedSecret {
77 ExtendedSecret { secret, chain_code }
78 }
79
80 pub fn new_random(secret: Secret) -> ExtendedSecret {
82 ExtendedSecret::with_code(secret, H256::random())
83 }
84
85 pub fn new(secret: Secret) -> ExtendedSecret {
89 let chain_code = derivation::chain_code(*secret);
90 ExtendedSecret::with_code(secret, chain_code)
91 }
92
93 pub fn derive<T>(&self, index: Derivation<T>) -> ExtendedSecret
95 where T: Label {
96 let (derived_key, next_chain_code) =
97 derivation::private(*self.secret, self.chain_code, index);
98
99 let derived_secret = Secret::from(derived_key.0);
100
101 ExtendedSecret::with_code(derived_secret, next_chain_code)
102 }
103
104 pub fn as_raw(&self) -> &Secret { &self.secret }
106}
107
108pub struct ExtendedPublic {
110 public: Public,
111 chain_code: H256,
112}
113
114impl ExtendedPublic {
115 pub fn new(public: Public, chain_code: H256) -> Self {
117 ExtendedPublic { public, chain_code }
118 }
119
120 pub fn from_secret(
122 secret: &ExtendedSecret,
123 ) -> Result<Self, DerivationError> {
124 Ok(ExtendedPublic::new(
125 derivation::point(**secret.as_raw())?,
126 secret.chain_code.clone(),
127 ))
128 }
129
130 pub fn derive<T>(
133 &self, index: Derivation<T>,
134 ) -> Result<Self, DerivationError>
135 where T: Label {
136 let (derived_key, next_chain_code) =
137 derivation::public(self.public, self.chain_code, index)?;
138 Ok(ExtendedPublic::new(derived_key, next_chain_code))
139 }
140
141 pub fn public(&self) -> &Public { &self.public }
142}
143
144pub struct ExtendedKeyPair {
145 secret: ExtendedSecret,
146 public: ExtendedPublic,
147}
148
149impl ExtendedKeyPair {
150 pub fn new(secret: Secret) -> Self {
151 let extended_secret = ExtendedSecret::new(secret);
152 let extended_public = ExtendedPublic::from_secret(&extended_secret)
153 .expect("Valid `Secret` always produces valid public; qed");
154 ExtendedKeyPair {
155 secret: extended_secret,
156 public: extended_public,
157 }
158 }
159
160 pub fn with_code(secret: Secret, public: Public, chain_code: H256) -> Self {
161 ExtendedKeyPair {
162 secret: ExtendedSecret::with_code(secret, chain_code.clone()),
163 public: ExtendedPublic::new(public, chain_code),
164 }
165 }
166
167 pub fn with_secret(secret: Secret, chain_code: H256) -> Self {
168 let extended_secret = ExtendedSecret::with_code(secret, chain_code);
169 let extended_public = ExtendedPublic::from_secret(&extended_secret)
170 .expect("Valid `Secret` always produces valid public; qed");
171 ExtendedKeyPair {
172 secret: extended_secret,
173 public: extended_public,
174 }
175 }
176
177 pub fn with_seed(seed: &[u8]) -> Result<ExtendedKeyPair, DerivationError> {
178 let (master_key, chain_code) = derivation::seed_pair(seed);
179 Ok(ExtendedKeyPair::with_secret(
180 Secret::from_unsafe_slice(master_key.as_bytes())
181 .map_err(|_| DerivationError::InvalidSeed)?,
182 chain_code,
183 ))
184 }
185
186 pub fn secret(&self) -> &ExtendedSecret { &self.secret }
187
188 pub fn public(&self) -> &ExtendedPublic { &self.public }
189
190 pub fn derive<T>(
191 &self, index: Derivation<T>,
192 ) -> Result<Self, DerivationError>
193 where T: Label {
194 let derived = self.secret.derive(index);
195
196 Ok(ExtendedKeyPair {
197 public: ExtendedPublic::from_secret(&derived)?,
198 secret: derived,
199 })
200 }
201}
202
203mod derivation {
207 use super::{Derivation, Label};
208 use crate::math::{curve_order, pubkey_to_public, public_to_pubkey};
209 use cfx_crypto::crypto::keccak::Keccak256;
210 use cfx_types::{BigEndianHash, H256, H512, U256, U512};
211 use hmac::{Hmac, Mac};
212 use secp256k1::{PublicKey, SecretKey, SECP256K1};
213 use sha2::Sha512;
214 use std::convert::TryInto;
215
216 type HmacSha512 = Hmac<Sha512>;
217
218 #[derive(Debug)]
219 pub enum Error {
220 InvalidHardenedUse,
221 InvalidPoint,
222 MissingIndex,
223 InvalidSeed,
224 }
225
226 pub fn private<T>(
234 private_key: H256, chain_code: H256, index: Derivation<T>,
235 ) -> (H256, H256)
236 where T: Label {
237 match index {
238 Derivation::Soft(index) => {
239 private_soft(private_key, chain_code, index)
240 }
241 Derivation::Hard(index) => {
242 private_hard(private_key, chain_code, index)
243 }
244 }
245 }
246
247 fn hmac_pair(
248 data: &[u8], private_key: H256, chain_code: H256,
249 ) -> (H256, H256) {
250 let private: U256 = private_key.into_uint();
251
252 let mut skey = HmacSha512::new_from_slice(chain_code.as_bytes())
254 .expect("HmacSha512 failed");
255 skey.update(data);
256 let i_512 = skey.finalize().into_bytes().to_vec();
257
258 let hmac_key: U256 = H256::from_slice(&i_512[0..32]).into_uint();
260 let next_chain_code = H256::from_slice(&i_512[32..64]);
262
263 let child_key =
264 BigEndianHash::from_uint(&private_add(hmac_key, private));
265 (child_key, next_chain_code)
266 }
267
268 fn private_soft<T>(
271 private_key: H256, chain_code: H256, index: T,
272 ) -> (H256, H256)
273 where T: Label {
274 let mut data = vec![0u8; 33 + T::len()];
275
276 let sec_private = SecretKey::from_slice(private_key.as_bytes())
277 .expect("Caller should provide valid private key");
278 let sec_public = PublicKey::from_secret_key(SECP256K1, &sec_private);
279 let public_serialized = sec_public.serialize();
280
281 data[0..33].copy_from_slice(&public_serialized);
284 index.store(&mut data[33..]);
285
286 hmac_pair(&data, private_key, chain_code)
287 }
288
289 fn private_hard<T>(
293 private_key: H256, chain_code: H256, index: T,
294 ) -> (H256, H256)
295 where T: Label {
296 let mut data: Vec<u8> = vec![0u8; 33 + T::len()];
297 let private: U256 = private_key.into_uint();
298
299 private.to_big_endian(&mut data[1..33]);
302 index.store(&mut data[33..(33 + T::len())]);
303
304 hmac_pair(&data, private_key, chain_code)
305 }
306
307 fn private_add(k1: U256, k2: U256) -> U256 {
308 let sum = U512::from(k1) + U512::from(k2);
309 modulo(sum, curve_order())
310 }
311
312 fn modulo(u1: U512, u2: U256) -> U256 {
314 let m = u1 % U512::from(u2);
315 m.try_into()
316 .expect("U512 modulo U256 should fit into U256; qed")
317 }
318
319 pub fn public<T>(
320 public_key: H512, chain_code: H256, derivation: Derivation<T>,
321 ) -> Result<(H512, H256), Error>
322 where T: Label {
323 let index = match derivation {
324 Derivation::Soft(index) => index,
325 Derivation::Hard(_) => {
326 return Err(Error::InvalidHardenedUse);
327 }
328 };
329
330 let public_sec =
331 public_to_pubkey(&public_key).map_err(|_| Error::InvalidPoint)?;
332 let public_serialized = public_sec.serialize();
333
334 let mut data = vec![0u8; 33 + T::len()];
335 data[0..33].copy_from_slice(&public_serialized);
338 index.store(&mut data[33..(33 + T::len())]);
339
340 let mut skey = HmacSha512::new_from_slice(chain_code.as_bytes())
342 .expect("HmacSha512 failed");
343 skey.update(data.as_slice());
344 let i_512 = skey.finalize().into_bytes().to_vec();
345
346 let new_private = H256::from_slice(&i_512[0..32]);
347 let new_chain_code = H256::from_slice(&i_512[32..64]);
348
349 if curve_order() <= new_private.into_uint() {
352 return Err(Error::MissingIndex);
353 }
354 let new_private_sec = SecretKey::from_slice(new_private.as_bytes())
355 .expect("Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed");
356 let new_public =
357 PublicKey::from_secret_key(SECP256K1, &new_private_sec);
358
359 let combined = new_public
361 .combine(&public_sec)
362 .expect("Addition of two valid points produce valid point");
363
364 Ok((pubkey_to_public(&combined), new_chain_code))
365 }
366
367 fn sha3(slc: &[u8]) -> H256 { slc.keccak256().into() }
368
369 pub fn chain_code(secret: H256) -> H256 {
370 let mut running_sha3 = sha3(secret.as_bytes());
372 for _ in 0..99999 {
373 running_sha3 = sha3(running_sha3.as_bytes());
374 }
375 running_sha3
376 }
377
378 pub fn point(secret: H256) -> Result<H512, Error> {
379 let sec = SecretKey::from_slice(secret.as_bytes())
380 .map_err(|_| Error::InvalidPoint)?;
381 Ok(pubkey_to_public(&PublicKey::from_secret_key(
382 SECP256K1, &sec,
383 )))
384 }
385
386 pub fn seed_pair(seed: &[u8]) -> (H256, H256) {
387 let mut skey = HmacSha512::new_from_slice(b"Bitcoin seed")
388 .expect("HmacSha512 failed");
389 skey.update(seed);
390 let i_512 = skey.finalize().into_bytes().to_vec();
391
392 let master_key = H256::from_slice(&i_512[0..32]);
393 let chain_code = H256::from_slice(&i_512[32..64]);
394
395 (master_key, chain_code)
396 }
397}
398
399#[cfg(test)]
400mod tests {
401 use super::{
402 derivation, Derivation, ExtendedKeyPair, ExtendedPublic, ExtendedSecret,
403 };
404 use crate::secret::Secret;
405 use cfx_types::{H128, H256, H512};
406 use std::str::FromStr;
407
408 fn master_chain_basic() -> (H256, H256) {
409 let seed = H128::from_str("000102030405060708090a0b0c0d0e0f")
410 .expect("Seed should be valid H128")
411 .as_bytes()
412 .to_vec();
413
414 derivation::seed_pair(&*seed)
415 }
416
417 fn test_extended<F>(f: F, test_private: H256)
418 where F: Fn(ExtendedSecret) -> ExtendedSecret {
419 let (private_seed, chain_code) = master_chain_basic();
420 let extended_secret =
421 ExtendedSecret::with_code(Secret::from(private_seed.0), chain_code);
422 let derived = f(extended_secret);
423 assert_eq!(**derived.as_raw(), test_private);
424 }
425
426 #[test]
427 fn smoky() {
428 let secret = Secret::from_str(
429 "a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65",
430 )
431 .unwrap();
432 let extended_secret =
433 ExtendedSecret::with_code(secret.clone(), H256::zero());
434
435 assert_eq!(&**extended_secret.as_raw(), &*secret);
437 assert_eq!(
438 **extended_secret.derive(2_147_483_648.into()).as_raw(),
439 H256::from_str("0927453daed47839608e414a3738dfad10aed17c459bbd9ab53f89b026c834b6").unwrap(),
440 );
441 assert_eq!(
442 **extended_secret.derive(2_147_483_649.into()).as_raw(),
443 H256::from_str("44238b6a29c6dcbe9b401364141ba11e2198c289a5fed243a1c11af35c19dc0f").unwrap(),
444 );
445
446 assert_eq!(**extended_secret.derive(0.into()).as_raw(), H256::from_str("bf6a74e3f7b36fc4c96a1e12f31abc817f9f5904f5a8fc27713163d1f0b713f6").unwrap());
448 assert_eq!(**extended_secret.derive(1.into()).as_raw(), H256::from_str("bd4fca9eb1f9c201e9448c1eecd66e302d68d4d313ce895b8c134f512205c1bc").unwrap());
449 assert_eq!(**extended_secret.derive(2.into()).as_raw(), H256::from_str("86932b542d6cab4d9c65490c7ef502d89ecc0e2a5f4852157649e3251e2a3268").unwrap());
450
451 let extended_public = ExtendedPublic::from_secret(&extended_secret)
452 .expect("Extended public should be created");
453 let derived_public = extended_public
454 .derive(0.into())
455 .expect("First derivation of public should succeed");
456 assert_eq!(
457 *derived_public.public(),
458 H512::from_str("f7b3244c96688f92372bfd4def26dc4151529747bab9f188a4ad34e141d47bd66522ff048bc6f19a0a4429b04318b1a8796c000265b4fa200dae5f6dda92dd94").unwrap(),
459 );
460
461 let keypair = ExtendedKeyPair::with_secret(
462 Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(),
463 H256::from_low_u64_be(64),
464 );
465 assert_eq!(
466 **keypair.derive(2_147_483_648u32.into()).expect("Derivation of keypair should succeed").secret().as_raw(),
467 H256::from_str("edef54414c03196557cf73774bc97a645c9a1df2164ed34f0c2a78d1375a930c").unwrap(),
468 );
469 }
470
471 #[test]
472 fn h256_soft_match() {
473 let secret = Secret::from_str(
474 "a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65",
475 )
476 .unwrap();
477 let derivation_secret = H256::from_str(
478 "51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015",
479 )
480 .unwrap();
481
482 let extended_secret = ExtendedSecret::with_code(secret, H256::zero());
483 let extended_public = ExtendedPublic::from_secret(&extended_secret)
484 .expect("Extended public should be created");
485
486 let derived_secret0 =
487 extended_secret.derive(Derivation::Soft(derivation_secret));
488 let derived_public0 = extended_public
489 .derive(Derivation::Soft(derivation_secret))
490 .expect("First derivation of public should succeed");
491
492 let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0)
493 .expect("Extended public should be created");
494
495 assert_eq!(public_from_secret0.public(), derived_public0.public());
496 }
497
498 #[test]
499 fn h256_hard() {
500 let secret = Secret::from_str(
501 "a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65",
502 )
503 .unwrap();
504 let derivation_secret = H256::from_str(
505 "51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015",
506 )
507 .unwrap();
508 let extended_secret =
509 ExtendedSecret::with_code(secret, H256::from_low_u64_be(1));
510
511 assert_eq!(
512 **extended_secret.derive(Derivation::Hard(derivation_secret)).as_raw(),
513 H256::from_str("2bc2d696fb744d77ff813b4a1ef0ad64e1e5188b622c54ba917acc5ebc7c5486").unwrap(),
514 );
515 }
516
517 #[test]
518 fn match_() {
519 let secret = Secret::from_str(
520 "a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65",
521 )
522 .unwrap();
523 let extended_secret =
524 ExtendedSecret::with_code(secret, H256::from_low_u64_be(1));
525 let extended_public = ExtendedPublic::from_secret(&extended_secret)
526 .expect("Extended public should be created");
527
528 let derived_secret0 = extended_secret.derive(0.into());
529 let derived_public0 = extended_public
530 .derive(0.into())
531 .expect("First derivation of public should succeed");
532
533 let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0)
534 .expect("Extended public should be created");
535
536 assert_eq!(public_from_secret0.public(), derived_public0.public());
537 }
538
539 #[test]
540 fn test_seeds() {
541 let seed = H128::from_str("000102030405060708090a0b0c0d0e0f")
542 .expect("Seed should be valid H128")
543 .as_bytes()
544 .to_vec();
545
546 let test_private = H256::from_str(
549 "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35",
550 )
551 .expect("Private should be decoded ok");
552
553 let (private_seed, _) = derivation::seed_pair(&*seed);
554
555 assert_eq!(private_seed, test_private);
556 }
557
558 #[test]
559 fn test_vector_1() {
560 test_extended(
563 |secret| secret.derive(2_147_483_648.into()),
564 H256::from_str("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea")
565 .expect("Private should be decoded ok")
566 );
567 }
568
569 #[test]
570 fn test_vector_2() {
571 test_extended(
574 |secret| secret.derive(2_147_483_648.into()).derive(1.into()),
575 H256::from_str("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368")
576 .expect("Private should be decoded ok")
577 );
578 }
579}