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, SECP256K1};
209 use cfx_crypto::crypto::keccak::Keccak256;
210 use cfx_types::{BigEndianHash, H256, H512, U256, U512};
211 use hmac::{Hmac, Mac};
212 use secp256k1::key::{PublicKey, SecretKey};
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 =
277 SecretKey::from_slice(&SECP256K1, private_key.as_bytes())
278 .expect("Caller should provide valid private key");
279 let sec_public = PublicKey::from_secret_key(&SECP256K1, &sec_private)
280 .expect("Caller should provide valid private key");
281 let public_serialized = sec_public.serialize_vec(&SECP256K1, true);
282
283 data[0..33].copy_from_slice(&public_serialized);
286 index.store(&mut data[33..]);
287
288 hmac_pair(&data, private_key, chain_code)
289 }
290
291 fn private_hard<T>(
295 private_key: H256, chain_code: H256, index: T,
296 ) -> (H256, H256)
297 where T: Label {
298 let mut data: Vec<u8> = vec![0u8; 33 + T::len()];
299 let private: U256 = private_key.into_uint();
300
301 private.to_big_endian(&mut data[1..33]);
304 index.store(&mut data[33..(33 + T::len())]);
305
306 hmac_pair(&data, private_key, chain_code)
307 }
308
309 fn private_add(k1: U256, k2: U256) -> U256 {
310 let sum = U512::from(k1) + U512::from(k2);
311 modulo(sum, curve_order())
312 }
313
314 fn modulo(u1: U512, u2: U256) -> U256 {
316 let m = u1 % U512::from(u2);
317 m.try_into()
318 .expect("U512 modulo U256 should fit into U256; qed")
319 }
320
321 pub fn public<T>(
322 public_key: H512, chain_code: H256, derivation: Derivation<T>,
323 ) -> Result<(H512, H256), Error>
324 where T: Label {
325 let index = match derivation {
326 Derivation::Soft(index) => index,
327 Derivation::Hard(_) => {
328 return Err(Error::InvalidHardenedUse);
329 }
330 };
331
332 let mut public_sec_raw = [0u8; 65];
333 public_sec_raw[0] = 4;
334 public_sec_raw[1..65].copy_from_slice(public_key.as_bytes());
335 let public_sec = PublicKey::from_slice(&SECP256K1, &public_sec_raw)
336 .map_err(|_| Error::InvalidPoint)?;
337 let public_serialized = public_sec.serialize_vec(&SECP256K1, true);
338
339 let mut data = vec![0u8; 33 + T::len()];
340 data[0..33].copy_from_slice(&public_serialized);
343 index.store(&mut data[33..(33 + T::len())]);
344
345 let mut skey = HmacSha512::new_from_slice(chain_code.as_bytes())
347 .expect("HmacSha512 failed");
348 skey.update(data.as_slice());
349 let i_512 = skey.finalize().into_bytes().to_vec();
350
351 let new_private = H256::from_slice(&i_512[0..32]);
352 let new_chain_code = H256::from_slice(&i_512[32..64]);
353
354 if curve_order() <= new_private.into_uint() {
357 return Err(Error::MissingIndex);
358 }
359 let new_private_sec = SecretKey::from_slice(&SECP256K1, new_private.as_bytes())
360 .expect("Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed");
361 let mut new_public =
362 PublicKey::from_secret_key(&SECP256K1, &new_private_sec)
363 .expect("Valid private key produces valid public key");
364
365 new_public
367 .add_assign(&SECP256K1, &public_sec)
368 .expect("Addition of two valid points produce valid point");
369
370 let serialized = new_public.serialize_vec(&SECP256K1, false);
371
372 Ok((H512::from_slice(&serialized[1..65]), new_chain_code))
373 }
374
375 fn sha3(slc: &[u8]) -> H256 { slc.keccak256().into() }
376
377 pub fn chain_code(secret: H256) -> H256 {
378 let mut running_sha3 = sha3(secret.as_bytes());
380 for _ in 0..99999 {
381 running_sha3 = sha3(running_sha3.as_bytes());
382 }
383 running_sha3
384 }
385
386 pub fn point(secret: H256) -> Result<H512, Error> {
387 let sec = SecretKey::from_slice(&SECP256K1, secret.as_bytes())
388 .map_err(|_| Error::InvalidPoint)?;
389 let public_sec = PublicKey::from_secret_key(&SECP256K1, &sec)
390 .map_err(|_| Error::InvalidPoint)?;
391 let serialized = public_sec.serialize_vec(&SECP256K1, false);
392 Ok(H512::from_slice(&serialized[1..65]))
393 }
394
395 pub fn seed_pair(seed: &[u8]) -> (H256, H256) {
396 let mut skey = HmacSha512::new_from_slice(b"Bitcoin seed")
397 .expect("HmacSha512 failed");
398 skey.update(seed);
399 let i_512 = skey.finalize().into_bytes().to_vec();
400
401 let master_key = H256::from_slice(&i_512[0..32]);
402 let chain_code = H256::from_slice(&i_512[32..64]);
403
404 (master_key, chain_code)
405 }
406}
407
408#[cfg(test)]
409mod tests {
410 use super::{
411 derivation, Derivation, ExtendedKeyPair, ExtendedPublic, ExtendedSecret,
412 };
413 use crate::secret::Secret;
414 use cfx_types::{H128, H256, H512};
415 use std::str::FromStr;
416
417 fn master_chain_basic() -> (H256, H256) {
418 let seed = H128::from_str("000102030405060708090a0b0c0d0e0f")
419 .expect("Seed should be valid H128")
420 .as_bytes()
421 .to_vec();
422
423 derivation::seed_pair(&*seed)
424 }
425
426 fn test_extended<F>(f: F, test_private: H256)
427 where F: Fn(ExtendedSecret) -> ExtendedSecret {
428 let (private_seed, chain_code) = master_chain_basic();
429 let extended_secret =
430 ExtendedSecret::with_code(Secret::from(private_seed.0), chain_code);
431 let derived = f(extended_secret);
432 assert_eq!(**derived.as_raw(), test_private);
433 }
434
435 #[test]
436 fn smoky() {
437 let secret = Secret::from_str(
438 "a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65",
439 )
440 .unwrap();
441 let extended_secret =
442 ExtendedSecret::with_code(secret.clone(), H256::zero());
443
444 assert_eq!(&**extended_secret.as_raw(), &*secret);
446 assert_eq!(
447 **extended_secret.derive(2_147_483_648.into()).as_raw(),
448 H256::from_str("0927453daed47839608e414a3738dfad10aed17c459bbd9ab53f89b026c834b6").unwrap(),
449 );
450 assert_eq!(
451 **extended_secret.derive(2_147_483_649.into()).as_raw(),
452 H256::from_str("44238b6a29c6dcbe9b401364141ba11e2198c289a5fed243a1c11af35c19dc0f").unwrap(),
453 );
454
455 assert_eq!(**extended_secret.derive(0.into()).as_raw(), H256::from_str("bf6a74e3f7b36fc4c96a1e12f31abc817f9f5904f5a8fc27713163d1f0b713f6").unwrap());
457 assert_eq!(**extended_secret.derive(1.into()).as_raw(), H256::from_str("bd4fca9eb1f9c201e9448c1eecd66e302d68d4d313ce895b8c134f512205c1bc").unwrap());
458 assert_eq!(**extended_secret.derive(2.into()).as_raw(), H256::from_str("86932b542d6cab4d9c65490c7ef502d89ecc0e2a5f4852157649e3251e2a3268").unwrap());
459
460 let extended_public = ExtendedPublic::from_secret(&extended_secret)
461 .expect("Extended public should be created");
462 let derived_public = extended_public
463 .derive(0.into())
464 .expect("First derivation of public should succeed");
465 assert_eq!(
466 *derived_public.public(),
467 H512::from_str("f7b3244c96688f92372bfd4def26dc4151529747bab9f188a4ad34e141d47bd66522ff048bc6f19a0a4429b04318b1a8796c000265b4fa200dae5f6dda92dd94").unwrap(),
468 );
469
470 let keypair = ExtendedKeyPair::with_secret(
471 Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(),
472 H256::from_low_u64_be(64),
473 );
474 assert_eq!(
475 **keypair.derive(2_147_483_648u32.into()).expect("Derivation of keypair should succeed").secret().as_raw(),
476 H256::from_str("edef54414c03196557cf73774bc97a645c9a1df2164ed34f0c2a78d1375a930c").unwrap(),
477 );
478 }
479
480 #[test]
481 fn h256_soft_match() {
482 let secret = Secret::from_str(
483 "a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65",
484 )
485 .unwrap();
486 let derivation_secret = H256::from_str(
487 "51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015",
488 )
489 .unwrap();
490
491 let extended_secret = ExtendedSecret::with_code(secret, H256::zero());
492 let extended_public = ExtendedPublic::from_secret(&extended_secret)
493 .expect("Extended public should be created");
494
495 let derived_secret0 =
496 extended_secret.derive(Derivation::Soft(derivation_secret));
497 let derived_public0 = extended_public
498 .derive(Derivation::Soft(derivation_secret))
499 .expect("First derivation of public should succeed");
500
501 let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0)
502 .expect("Extended public should be created");
503
504 assert_eq!(public_from_secret0.public(), derived_public0.public());
505 }
506
507 #[test]
508 fn h256_hard() {
509 let secret = Secret::from_str(
510 "a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65",
511 )
512 .unwrap();
513 let derivation_secret = H256::from_str(
514 "51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015",
515 )
516 .unwrap();
517 let extended_secret =
518 ExtendedSecret::with_code(secret, H256::from_low_u64_be(1));
519
520 assert_eq!(
521 **extended_secret.derive(Derivation::Hard(derivation_secret)).as_raw(),
522 H256::from_str("2bc2d696fb744d77ff813b4a1ef0ad64e1e5188b622c54ba917acc5ebc7c5486").unwrap(),
523 );
524 }
525
526 #[test]
527 fn match_() {
528 let secret = Secret::from_str(
529 "a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65",
530 )
531 .unwrap();
532 let extended_secret =
533 ExtendedSecret::with_code(secret, H256::from_low_u64_be(1));
534 let extended_public = ExtendedPublic::from_secret(&extended_secret)
535 .expect("Extended public should be created");
536
537 let derived_secret0 = extended_secret.derive(0.into());
538 let derived_public0 = extended_public
539 .derive(0.into())
540 .expect("First derivation of public should succeed");
541
542 let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0)
543 .expect("Extended public should be created");
544
545 assert_eq!(public_from_secret0.public(), derived_public0.public());
546 }
547
548 #[test]
549 fn test_seeds() {
550 let seed = H128::from_str("000102030405060708090a0b0c0d0e0f")
551 .expect("Seed should be valid H128")
552 .as_bytes()
553 .to_vec();
554
555 let test_private = H256::from_str(
558 "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35",
559 )
560 .expect("Private should be decoded ok");
561
562 let (private_seed, _) = derivation::seed_pair(&*seed);
563
564 assert_eq!(private_seed, test_private);
565 }
566
567 #[test]
568 fn test_vector_1() {
569 test_extended(
572 |secret| secret.derive(2_147_483_648.into()),
573 H256::from_str("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea")
574 .expect("Private should be decoded ok")
575 );
576 }
577
578 #[test]
579 fn test_vector_2() {
580 test_extended(
583 |secret| secret.derive(2_147_483_648.into()).derive(1.into()),
584 H256::from_str("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368")
585 .expect("Private should be decoded ok")
586 );
587 }
588}