1use byteorder::{BigEndian, WriteBytesExt};
2use network::Network;
3use ring::hmac;
4use rust_base58::base58::{FromBase58, ToBase58};
5use secp256k1::{PublicKey, Secp256k1, SecretKey};
6use std::fmt;
7use std::io;
8use std::io::{Cursor, Read, Write};
9use std::slice;
10use util::{hash160, sha256d, Error, Result, Serializable};
11
12const SECP256K1_CURVE_ORDER: [u8; 32] = [
14 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
15 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41,
16];
17
18pub const HARDENED_KEY: u32 = 2147483648;
20
21pub const MAINNET_PUBLIC_EXTENDED_KEY: u32 = 0x0488B21E;
23pub const MAINNET_PRIVATE_EXTENDED_KEY: u32 = 0x0488ADE4;
25pub const TESTNET_PUBLIC_EXTENDED_KEY: u32 = 0x043587C;
27pub const TESTNET_PRIVATE_EXTENDED_KEY: u32 = 0x04358394;
29
30#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
32pub enum ExtendedKeyType {
33 Public,
34 Private,
35}
36
37#[derive(Clone, Copy)]
39pub struct ExtendedKey(pub [u8; 78]);
40
41impl ExtendedKey {
42 pub fn new_public_key(
44 network: Network,
45 depth: u8,
46 parent_fingerprint: &[u8],
47 index: u32,
48 chain_code: &[u8],
49 public_key: &[u8],
50 ) -> Result<ExtendedKey> {
51 if parent_fingerprint.len() != 4 {
52 return Err(Error::BadArgument("Fingerprint must be len 4".to_string()));
53 }
54 if chain_code.len() != 32 {
55 return Err(Error::BadArgument("Chain code must be len 32".to_string()));
56 }
57 if public_key.len() != 33 {
58 return Err(Error::BadArgument("Public key must be len 33".to_string()));
59 }
60 let mut extended_key = ExtendedKey([0; 78]);
61 {
62 let mut c = Cursor::new(&mut extended_key.0 as &mut [u8]);
63 match network {
64 Network::Mainnet => c
65 .write_u32::<BigEndian>(MAINNET_PUBLIC_EXTENDED_KEY)
66 .unwrap(),
67 Network::Testnet => c
68 .write_u32::<BigEndian>(TESTNET_PUBLIC_EXTENDED_KEY)
69 .unwrap(),
70 }
71 c.write_u8(depth).unwrap();
72 c.write(parent_fingerprint).unwrap();
73 c.write_u32::<BigEndian>(index).unwrap();
74 c.write(chain_code).unwrap();
75 c.write(public_key).unwrap();
76 }
77 Ok(extended_key)
78 }
79
80 pub fn new_private_key(
82 network: Network,
83 depth: u8,
84 parent_fingerprint: &[u8],
85 index: u32,
86 chain_code: &[u8],
87 private_key: &[u8],
88 ) -> Result<ExtendedKey> {
89 if parent_fingerprint.len() != 4 {
90 return Err(Error::BadArgument("Fingerprint must be len 4".to_string()));
91 }
92 if chain_code.len() != 32 {
93 return Err(Error::BadArgument("Chain code must be len 32".to_string()));
94 }
95 if private_key.len() != 32 {
96 return Err(Error::BadArgument("Private key must be len 32".to_string()));
97 }
98 let mut extended_key = ExtendedKey([0; 78]);
99 {
100 let mut c = Cursor::new(&mut extended_key.0 as &mut [u8]);
101 match network {
102 Network::Mainnet => c
103 .write_u32::<BigEndian>(MAINNET_PRIVATE_EXTENDED_KEY)
104 .unwrap(),
105 Network::Testnet => c
106 .write_u32::<BigEndian>(TESTNET_PRIVATE_EXTENDED_KEY)
107 .unwrap(),
108 }
109 c.write_u8(depth).unwrap();
110 c.write(parent_fingerprint).unwrap();
111 c.write_u32::<BigEndian>(index).unwrap();
112 c.write(chain_code).unwrap();
113 c.write_u8(0).unwrap();
114 c.write(private_key).unwrap();
115 }
116 Ok(extended_key)
117 }
118
119 pub fn version(&self) -> u32 {
121 ((self.0[0] as u32) << 24)
122 | ((self.0[1] as u32) << 16)
123 | ((self.0[2] as u32) << 8)
124 | ((self.0[3] as u32) << 0)
125 }
126
127 pub fn network(&self) -> Result<Network> {
129 let ver = self.version();
130 if ver == MAINNET_PUBLIC_EXTENDED_KEY || ver == MAINNET_PRIVATE_EXTENDED_KEY {
131 return Ok(Network::Mainnet);
132 } else if ver == TESTNET_PUBLIC_EXTENDED_KEY || ver == TESTNET_PRIVATE_EXTENDED_KEY {
133 return Ok(Network::Testnet);
134 } else {
135 let msg = format!("Unknown extended key version {:?}", ver);
136 return Err(Error::BadData(msg));
137 }
138 }
139
140 pub fn key_type(&self) -> Result<ExtendedKeyType> {
142 let ver = self.version();
143 if ver == MAINNET_PUBLIC_EXTENDED_KEY || ver == TESTNET_PUBLIC_EXTENDED_KEY {
144 return Ok(ExtendedKeyType::Public);
145 } else if ver == MAINNET_PRIVATE_EXTENDED_KEY || ver == TESTNET_PRIVATE_EXTENDED_KEY {
146 return Ok(ExtendedKeyType::Private);
147 } else {
148 let msg = format!("Unknown extended key version {:?}", ver);
149 return Err(Error::BadData(msg));
150 }
151 }
152
153 pub fn depth(&self) -> u8 {
155 self.0[4]
156 }
157
158 pub fn parent_fingerprint(&self) -> [u8; 4] {
160 [self.0[5], self.0[6], self.0[7], self.0[8]]
161 }
162
163 pub fn index(&self) -> u32 {
165 ((self.0[9] as u32) << 24)
166 | ((self.0[10] as u32) << 16)
167 | ((self.0[11] as u32) << 8)
168 | ((self.0[12] as u32) << 0)
169 }
170
171 pub fn chain_code(&self) -> [u8; 32] {
173 let mut chain_code = [0; 32];
174 chain_code.clone_from_slice(&self.0[13..45]);
175 chain_code
176 }
177
178 pub fn public_key(&self) -> Result<[u8; 33]> {
180 match self.key_type()? {
181 ExtendedKeyType::Public => {
182 let mut public_key = [0; 33];
183 public_key.clone_from_slice(&self.0[45..]);
184 Ok(public_key)
185 }
186 ExtendedKeyType::Private => {
187 let secp = Secp256k1::signing_only();
188 let secp_secret_key = SecretKey::from_slice(&self.0[46..])?;
189 let secp_public_key = PublicKey::from_secret_key(&secp, &secp_secret_key);
190 Ok(secp_public_key.serialize())
191 }
192 }
193 }
194
195 pub fn private_key(&self) -> Result<[u8; 32]> {
197 if self.key_type()? == ExtendedKeyType::Private {
198 let mut private_key = [0; 32];
199 private_key.clone_from_slice(&self.0[46..]);
200 Ok(private_key)
201 } else {
202 let msg = "Cannot get private key of public extended key";
203 Err(Error::BadData(msg.to_string()))
204 }
205 }
206
207 pub fn fingerprint(&self) -> Result<[u8; 4]> {
209 let mut fingerprint = [0; 4];
210 let public_key_hash = hash160(&self.public_key()?);
211 fingerprint.clone_from_slice(&public_key_hash.0[..4]);
212 Ok(fingerprint)
213 }
214
215 pub fn extended_public_key(&self) -> Result<ExtendedKey> {
217 match self.key_type()? {
218 ExtendedKeyType::Public => Ok(self.clone()),
219 ExtendedKeyType::Private => {
220 let private_key = &self.0[46..];
221 let secp = Secp256k1::signing_only();
222 let secp_secret_key = SecretKey::from_slice(&private_key)?;
223 let secp_public_key = PublicKey::from_secret_key(&secp, &secp_secret_key);
224 let public_key = secp_public_key.serialize();
225
226 ExtendedKey::new_public_key(
227 self.network()?,
228 self.depth(),
229 &self.0[5..9],
230 self.index(),
231 &self.0[13..45],
232 &public_key,
233 )
234 }
235 }
236 }
237
238 pub fn derive_private_key(&self, index: u32) -> Result<ExtendedKey> {
240 if self.key_type()? == ExtendedKeyType::Public {
241 let msg = "Cannot derive private key from public key";
242 return Err(Error::BadData(msg.to_string()));
243 }
244 let network = self.network()?;
245 if self.depth() == 255 {
246 let msg = "Cannot derive extended key. Depth already at max.";
247 return Err(Error::BadData(msg.to_string()));
248 }
249
250 let secp = Secp256k1::signing_only();
251 let private_key = &self.0[46..];
252 let secp_par_secret_key = SecretKey::from_slice(&private_key)?;
253 let chain_code = &self.0[13..45];
254 let key = hmac::Key::new(hmac::HMAC_SHA512, chain_code);
255
256 let hmac = if index >= HARDENED_KEY {
257 let mut v = Vec::<u8>::with_capacity(37);
258 v.push(0);
259 v.extend_from_slice(&private_key);
260 v.write_u32::<BigEndian>(index)?;
261 hmac::sign(&key, &v)
262 } else {
263 let mut v = Vec::<u8>::with_capacity(37);
264 let secp_public_key = PublicKey::from_secret_key(&secp, &secp_par_secret_key);
265 let public_key = secp_public_key.serialize();
266 v.extend_from_slice(&public_key);
267 v.write_u32::<BigEndian>(index)?;
268 hmac::sign(&key, &v)
269 };
270
271 if hmac.as_ref().len() != 64 {
272 return Err(Error::IllegalState("HMAC invalid length".to_string()));
273 }
274
275 if !is_private_key_valid(&hmac.as_ref()[..32]) {
276 let msg = "Invalid key. Try next index.".to_string();
277 return Err(Error::IllegalState(msg));
278 }
279
280 let mut secp_child_secret_key = SecretKey::from_slice(&hmac.as_ref()[..32])?;
281 secp_child_secret_key.add_assign(&private_key)?;
282
283 let child_chain_code = &hmac.as_ref()[32..];
284 let fingerprint = self.fingerprint()?;
285 let child_private_key =
286 unsafe { slice::from_raw_parts(secp_child_secret_key.as_ptr(), 32) };
287
288 ExtendedKey::new_private_key(
289 network,
290 self.depth() + 1,
291 &fingerprint,
292 index,
293 child_chain_code,
294 child_private_key,
295 )
296 }
297
298 pub fn derive_public_key(&self, index: u32) -> Result<ExtendedKey> {
300 if index >= HARDENED_KEY {
301 return Err(Error::BadArgument("i cannot be hardened".to_string()));
302 }
303 let network = self.network()?;
304 if self.depth() == 255 {
305 let msg = "Cannot derive extended key. Depth already at max.";
306 return Err(Error::BadData(msg.to_string()));
307 }
308
309 let chain_code = &self.0[13..45];
310 let key = hmac::Key::new(hmac::HMAC_SHA512, chain_code);
311 let mut v = Vec::<u8>::with_capacity(65);
312 let public_key = self.public_key()?;
313 v.extend_from_slice(&public_key);
314 v.write_u32::<BigEndian>(index)?;
315 let hmac = hmac::sign(&key, &v);
316
317 if hmac.as_ref().len() != 64 {
318 return Err(Error::IllegalState("HMAC invalid length".to_string()));
319 }
320
321 if !is_private_key_valid(&hmac.as_ref()[..32]) {
322 let msg = "Invalid key. Try next index.".to_string();
323 return Err(Error::IllegalState(msg));
324 }
325
326 let secp = Secp256k1::signing_only();
327 let child_offset = SecretKey::from_slice(&hmac.as_ref()[..32])?;
328 let child_offset = PublicKey::from_secret_key(&secp, &child_offset);
329 let secp_par_public_key = PublicKey::from_slice(&public_key)?;
330 let secp_child_public_key = secp_par_public_key.combine(&child_offset)?;
331 let child_public_key = secp_child_public_key.serialize();
332
333 let child_chain_code = &hmac.as_ref()[32..];
334 let fingerprint = self.fingerprint()?;
335
336 ExtendedKey::new_public_key(
337 network,
338 self.depth() + 1,
339 &fingerprint,
340 index,
341 child_chain_code,
342 &child_public_key,
343 )
344 }
345
346 pub fn encode(&self) -> String {
348 let checksum = sha256d(&self.0);
349 let mut v = Vec::with_capacity(82);
350 v.extend_from_slice(&self.0);
351 v.extend_from_slice(&checksum.0[..4]);
352 v.to_base58()
353 }
354
355 pub fn decode(s: &str) -> Result<ExtendedKey> {
357 let v = s.from_base58()?;
358 let checksum = sha256d(&v[..78]);
359 if checksum.0[..4] != v[78..] {
360 return Err(Error::BadArgument("Invalid checksum".to_string()));
361 }
362 let mut extended_key = ExtendedKey([0; 78]);
363 extended_key.0.clone_from_slice(&v[..78]);
364 Ok(extended_key)
365 }
366}
367
368impl Serializable<ExtendedKey> for ExtendedKey {
369 fn read(reader: &mut dyn Read) -> Result<ExtendedKey> {
370 let mut k = ExtendedKey([0; 78]);
371 reader.read(&mut k.0)?;
372 Ok(k)
373 }
374
375 fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
376 writer.write(&self.0)?;
377 Ok(())
378 }
379}
380
381impl fmt::Debug for ExtendedKey {
382 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
383 write!(f, "{}", self.encode())
384 }
385}
386
387impl PartialEq for ExtendedKey {
388 fn eq(&self, other: &ExtendedKey) -> bool {
389 self.0.to_vec() == other.0.to_vec()
390 }
391}
392
393impl Eq for ExtendedKey {}
394
395pub fn derive_extended_key(master: &ExtendedKey, path: &str) -> Result<ExtendedKey> {
397 let parts: Vec<&str> = path.split('/').collect();
398 let mut key_type = ExtendedKeyType::Public;
399
400 if parts[0] == "m" {
401 if master.key_type()? == ExtendedKeyType::Public {
402 let msg = "Cannot derive private key from public master";
403 return Err(Error::BadArgument(msg.to_string()));
404 }
405 key_type = ExtendedKeyType::Private;
406 } else if parts[0] != "M" {
407 let msg = "Path must start with m or M";
408 return Err(Error::BadArgument(msg.to_string()));
409 }
410
411 let mut key = master.clone();
412
413 for part in parts[1..].iter() {
414 if part.len() == 0 {
415 let msg = "Empty part";
416 return Err(Error::BadArgument(msg.to_string()));
417 }
418
419 let index = if part.ends_with("'") || part.ends_with("h") || part.ends_with("H") {
420 let index: u32 = part
421 .trim_end_matches("'")
422 .trim_end_matches("h")
423 .trim_end_matches("H")
424 .parse()?;
425 if index >= HARDENED_KEY {
426 let msg = "Key index is already hardened";
427 return Err(Error::BadArgument(msg.to_string()));
428 }
429 index + HARDENED_KEY
430 } else {
431 part.parse()?
432 };
433
434 key = match key_type {
435 ExtendedKeyType::Public => key.derive_public_key(index)?,
436 ExtendedKeyType::Private => key.derive_private_key(index)?,
437 };
438 }
439
440 Ok(key)
441}
442
443pub fn is_private_key_valid(key: &[u8]) -> bool {
445 let mut is_below_order = false;
446 if key.len() != 32 {
447 return false;
448 }
449 for i in 0..32 {
450 if key[i] < SECP256K1_CURVE_ORDER[i] {
451 is_below_order = true;
452 break;
453 }
454 }
455 if !is_below_order {
456 return false;
457 }
458 for i in 0..32 {
459 if key[i] != 0 {
460 return true;
461 }
462 }
463 return false;
464}
465
466#[cfg(test)]
467mod tests {
468 use super::*;
469 use hex;
470
471 #[test]
472 fn private_key_range() {
473 let mut max = SECP256K1_CURVE_ORDER.clone();
475 max[31] = max[31] - 1;
476 assert!(is_private_key_valid(&max));
477 assert!(is_private_key_valid(&[0x01; 32]));
478
479 assert!(!is_private_key_valid(&[0x00; 32]));
481 assert!(!is_private_key_valid(&[0xff; 32]));
482 assert!(!is_private_key_valid(&SECP256K1_CURVE_ORDER));
483 }
484
485 #[test]
486 fn path() {
487 let m = master_private_key("000102030405060708090a0b0c0d0e0f");
489 assert!(derive_extended_key(&m, "m").unwrap().encode() == "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi");
490 assert!(derive_extended_key(&m, "m").unwrap().extended_public_key().unwrap().encode() == "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8");
491 assert!(derive_extended_key(&m, "m/0H").unwrap().encode() == "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7");
492 assert!(derive_extended_key(&m, "m/0H").unwrap().extended_public_key().unwrap().encode() == "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw");
493 assert!(derive_extended_key(&m, "m/0h/1").unwrap().encode() == "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs");
494 assert!(
495 derive_extended_key(&m, "m/0h/1")
496 .unwrap()
497 .extended_public_key()
498 .unwrap()
499 .encode()
500 == "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
501 );
502 assert!(derive_extended_key(&m, "m/0h/1/2'").unwrap().encode() == "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM");
503 assert!(
504 derive_extended_key(&m, "m/0h/1/2'")
505 .unwrap()
506 .extended_public_key()
507 .unwrap()
508 .encode()
509 == "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"
510 );
511 assert!(derive_extended_key(&m, "m/0H/1/2H/2").unwrap().encode() == "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334");
512 assert!(
513 derive_extended_key(&m, "m/0H/1/2H/2")
514 .unwrap()
515 .extended_public_key()
516 .unwrap()
517 .encode()
518 == "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"
519 );
520 assert!(
521 derive_extended_key(&m, "m/0H/1/2H/2/1000000000")
522 .unwrap()
523 .encode()
524 == "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"
525 );
526 assert!(
527 derive_extended_key(&m, "m/0H/1/2H/2/1000000000")
528 .unwrap()
529 .extended_public_key()
530 .unwrap()
531 .encode()
532 == "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
533 );
534
535 let m = master_private_key("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542");
537 assert!(derive_extended_key(&m, "m").unwrap().encode() == "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U");
538 assert!(derive_extended_key(&m, "m").unwrap().extended_public_key().unwrap().encode() == "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB");
539 assert!(derive_extended_key(&m, "m/0").unwrap().encode() == "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt");
540 assert!(derive_extended_key(&m, "m/0").unwrap().extended_public_key().unwrap().encode() == "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH");
541 assert!(derive_extended_key(&m, "m/0/2147483647H").unwrap().encode() == "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9");
542 assert!(derive_extended_key(&m, "m/0/2147483647H").unwrap().extended_public_key().unwrap().encode() == "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a");
543 assert!(derive_extended_key(&m, "m/0/2147483647H/1").unwrap().encode() == "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef");
544 assert!(derive_extended_key(&m, "m/0/2147483647H/1").unwrap().extended_public_key().unwrap().encode() == "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon");
545 assert!(derive_extended_key(&m, "m/0/2147483647H/1/2147483646H").unwrap().encode() == "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc");
546 assert!(derive_extended_key(&m, "m/0/2147483647H/1/2147483646H").unwrap().extended_public_key().unwrap().encode() == "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL");
547 assert!(derive_extended_key(&m, "m/0/2147483647H/1/2147483646H/2").unwrap().encode() == "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j");
548 assert!(derive_extended_key(&m, "m/0/2147483647H/1/2147483646H/2").unwrap().extended_public_key().unwrap().encode() == "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt");
549
550 let m = master_private_key("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be");
552 assert!(derive_extended_key(&m, "m").unwrap().encode() == "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6");
553 assert!(derive_extended_key(&m, "m").unwrap().extended_public_key().unwrap().encode() == "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13");
554 assert!(derive_extended_key(&m, "m/0H").unwrap().encode() == "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L");
555 assert!(derive_extended_key(&m, "m/0H").unwrap().extended_public_key().unwrap().encode() == "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y");
556 }
557
558 #[test]
559 fn new_public_key() {
560 let key = ExtendedKey::new_public_key(
561 Network::Testnet,
562 111,
563 &[0, 1, 2, 3],
564 44,
565 &[5; 32],
566 &[6; 33],
567 )
568 .unwrap();
569 assert!(key.network().unwrap() == Network::Testnet);
570 assert!(key.key_type().unwrap() == ExtendedKeyType::Public);
571 assert!(key.depth() == 111);
572 assert!(key.parent_fingerprint() == [0_u8, 1_u8, 2_u8, 3_u8]);
573 assert!(key.index() == 44);
574 assert!(key.chain_code() == [5_u8; 32]);
575 assert!(
576 key.public_key().unwrap()[1..] == [6_u8; 32] && key.public_key().unwrap()[0] == 6_u8
577 );
578
579 assert!(ExtendedKey::new_public_key(
581 Network::Testnet,
582 111,
583 &[0, 1, 2],
584 44,
585 &[5; 32],
586 &[6; 33],
587 )
588 .is_err());
589 assert!(ExtendedKey::new_public_key(
590 Network::Testnet,
591 111,
592 &[0, 1, 2, 3],
593 44,
594 &[5; 31],
595 &[6; 33],
596 )
597 .is_err());
598 assert!(ExtendedKey::new_public_key(
599 Network::Testnet,
600 111,
601 &[0, 1, 2, 3],
602 44,
603 &[5; 32],
604 &[6; 32],
605 )
606 .is_err());
607 }
608
609 #[test]
610 fn new_private_key() {
611 let key = ExtendedKey::new_private_key(
612 Network::Mainnet,
613 255,
614 &[4, 5, 6, 7],
615 HARDENED_KEY + 100,
616 &[7; 32],
617 &[8; 32],
618 )
619 .unwrap();
620 assert!(key.network().unwrap() == Network::Mainnet);
621 assert!(key.key_type().unwrap() == ExtendedKeyType::Private);
622 assert!(key.depth() == 255);
623 assert!(key.parent_fingerprint() == [4_u8, 5_u8, 6_u8, 7_u8]);
624 assert!(key.index() == HARDENED_KEY + 100);
625 assert!(key.chain_code() == [7_u8; 32]);
626 assert!(key.private_key().unwrap() == [8_u8; 32]);
627
628 assert!(ExtendedKey::new_private_key(
630 Network::Mainnet,
631 255,
632 &[4, 5, 6],
633 HARDENED_KEY + 100,
634 &[7; 32],
635 &[8; 32],
636 )
637 .is_err());
638 assert!(ExtendedKey::new_private_key(
639 Network::Mainnet,
640 255,
641 &[4, 5, 6, 7],
642 HARDENED_KEY + 100,
643 &[7],
644 &[8; 32],
645 )
646 .is_err());
647 assert!(ExtendedKey::new_private_key(
648 Network::Mainnet,
649 255,
650 &[4, 5, 6, 7],
651 HARDENED_KEY + 100,
652 &[7; 32],
653 &[8; 33],
654 )
655 .is_err());
656 }
657
658 #[test]
659 fn invalid() {
660 let k = ExtendedKey([5; 78]);
661 assert!(k.network().is_err());
662 assert!(k.key_type().is_err());
663 }
664
665 #[test]
666 fn encode_decode() {
667 let k = master_private_key("0123456789abcdef");
668 assert!(k == ExtendedKey::decode(&k.encode()).unwrap());
669 let k = derive_extended_key(&k, "M/1/2/3/4/5").unwrap();
670 assert!(k == ExtendedKey::decode(&k.encode()).unwrap());
671 }
672
673 fn master_private_key(seed: &str) -> ExtendedKey {
674 let seed = hex::decode(seed).unwrap();
675 let key = "Bitcoin seed".to_string();
676 let key = hmac::Key::new(hmac::HMAC_SHA512, &key.as_bytes());
677 let hmac = hmac::sign(&key, &seed);
678 ExtendedKey::new_private_key(
679 Network::Mainnet,
680 0,
681 &[0; 4],
682 0,
683 &hmac.as_ref()[32..],
684 &hmac.as_ref()[0..32],
685 )
686 .unwrap()
687 }
688}