1use std::collections::HashMap;
2use std::fmt::Write;
3use std::num::{NonZeroU32, ParseIntError};
4use std::str::FromStr;
5mod bip39;
6
7use binary_utils::*;
8use bip39::WORDS;
9use bitcoin::hashes::{ripemd160, Hash};
10use bitcoin::schnorr::UntweakedPublicKey;
11use bitcoin::util::base58::check_encode_slice;
12use bitcoin::util::base58::from_check;
13use bitcoin::util::taproot::TapTweakHash;
14use bitcoin_bech32::{u5, WitnessProgram};
15use bitcoin_utils::*;
16use hmac_sha512::HMAC;
17use num_bigint::BigUint;
18use rand::{thread_rng, RngCore};
19use ring::{digest, pbkdf2};
20use secp256k1::{Scalar, Secp256k1, SecretKey};
21use sha2::{Digest, Sha256};
22
23use hex_utilities::{
24 convert_decimal_to_32_byte_hex, convert_decimal_to_8_byte_hex, convert_hex_to_decimal,
25 decode_hex, encode_hex, get_hex_string_from_byte_array,
26};
27
28const HARDENED_DERIVATION_CHARACTER: &str = "'";
30
31#[derive(Debug, Clone)]
32pub struct SerializedExtendedKeys {
33 pub xpub: String,
34 pub xpriv: String,
35}
36
37#[derive(Debug, Clone)]
38pub struct NonMasterKeys {
39 pub private_key_hex: String,
40 pub public_key_hex: String,
41 pub chain_code_hex: String,
42 pub is_hardened: bool,
43}
44impl NonMasterKeys {
45 pub fn get_wif(&self, network: Network, should_compress: bool) -> String {
46 get_wif_from_private_key(&self.private_key_hex, network, should_compress)
47 }
48 pub fn get_address(&self, network: Network, address_type: AddressType) -> String {
49 get_address_from_pub_key(&self.public_key_hex, network, address_type)
50 }
51 pub fn serialize(
52 &self,
53 parent_public_key: String,
54 depth: u8,
55 child_index: u32,
56 network: Network,
57 bip: Bip,
58 ) -> SerializedExtendedKeys {
59 serialize_non_master_key(&self, parent_public_key, depth, child_index, network, bip)
60 }
61}
62#[derive(Debug, Clone)]
63pub struct MasterKeys {
64 pub private_key_hex: String,
65 pub public_key_hex: String,
66 pub chain_code_hex: String,
67}
68impl MasterKeys {
69 pub fn get_wif(&self, network: Network, should_compress: bool) -> String {
70 get_wif_from_private_key(&self.private_key_hex, network, should_compress)
71 }
72 pub fn get_address(&self, network: Network, address_type: AddressType) -> String {
73 get_address_from_pub_key(&self.public_key_hex, network, address_type)
74 }
75 pub fn serialize(&self, network: Network, bip: Bip) -> SerializedExtendedKeys {
76 serialize_master_key(self, network, bip)
77 }
78}
79
80#[derive(Debug, Clone)]
81pub enum Keys {
82 Master(MasterKeys),
83 NonMaster(NonMasterKeys),
84}
85
86impl Keys {
87 pub fn get_wif(&self, network: Network, should_compress: bool) -> String {
88 match &self {
89 Keys::Master(master_keys) => master_keys.get_wif(network, should_compress),
90 Keys::NonMaster(non_master_keys) => non_master_keys.get_wif(network, should_compress),
91 }
92 }
93 pub fn get_address(&self, network: Network, address_type: AddressType) -> String {
94 match &self {
95 Keys::Master(master_keys) => master_keys.get_address(network, address_type),
96 Keys::NonMaster(non_master_keys) => non_master_keys.get_address(network, address_type),
97 }
98 }
99}
100#[derive(Debug)]
101enum DerivationChild {
102 NonHardened(u32),
103 Hardened(u32),
104}
105
106#[derive(Debug, Clone)]
107pub struct DecodedExtendedSerializedPrivateKey {
108 pub version_hex: String,
109 pub depth: u8,
110 pub parent_fingerprint: String,
111 pub child_index: u32,
112 pub network: Network,
113 pub depth_fingerprint_child_index_hex: String,
114 pub chain_code_hex: String,
115 pub private_key_hex: String,
116 pub wif_compressed: String,
117 pub wif_uncompressed: String,
118 pub public_key_hex_uncompressed: String,
119 pub public_key_hex_compressed: String,
120}
121#[derive(Debug, Clone)]
122pub struct DecodedExtendedSerializedPublicKey {
123 pub version_hex: String,
124 pub depth: u8,
125 pub parent_fingerprint: String,
126 pub child_index: u32,
127 pub network: Network,
128 pub depth_fingerprint_child_index_hex: String,
129 pub chain_code_hex: String,
130 pub public_key_hex_uncompressed: String,
131}
132
133#[derive(Debug, Clone)]
134pub enum DecodedExtendedKeySerialized {
135 PrivateKey(DecodedExtendedSerializedPrivateKey),
136 PublicKey(DecodedExtendedSerializedPublicKey),
137}
138
139fn sha256_entropy_hex_byte_array(hex_byte_array: &Vec<u8>) -> Vec<u8> {
147 let mut hasher = Sha256::new();
148 hasher.update(&hex_byte_array);
150 let sha256_result = hasher.finalize();
152 sha256_result.to_vec()
153}
154fn serialize_master_key(
155 master_keys: &MasterKeys,
156 network: Network,
157 bip: Bip,
158) -> SerializedExtendedKeys {
159 let master_xprv = serialize_key(SerializeKeyArgs {
160 keys_to_serialize: Keys::Master(master_keys.clone()).clone(),
161 parent_public_key: None,
162 is_public: false,
163 network: network,
164 depth: Some(0),
165 child_index: 0,
166 bip,
167 });
169 let master_xpub = serialize_key(SerializeKeyArgs {
170 keys_to_serialize: Keys::Master(master_keys.clone()).clone(),
171 parent_public_key: None,
172 is_public: true,
173 network: network,
174 depth: Some(0),
175 child_index: 0,
176 bip,
177 });
179 SerializedExtendedKeys {
180 xpub: master_xpub,
181 xpriv: master_xprv,
182 }
183}
184fn serialize_non_master_key(
185 non_master_keys: &NonMasterKeys,
186 parent_public_key: String,
187 depth: u8,
188 child_index: u32,
189 network: Network,
190 bip: Bip,
191) -> SerializedExtendedKeys {
192 let bip32_extended_public_key = serialize_key(SerializeKeyArgs {
193 keys_to_serialize: Keys::NonMaster(non_master_keys.clone()).clone(),
194 parent_public_key: Some(parent_public_key.clone()),
195 is_public: true,
196 network,
197 depth: Some(depth),
198 child_index: child_index as u32,
199 bip,
200 });
201 let bip32_extended_private_key = serialize_key(SerializeKeyArgs {
202 keys_to_serialize: Keys::NonMaster(non_master_keys.clone()).clone(),
203 parent_public_key: Some(parent_public_key.clone()),
204 is_public: false,
205 network,
206 depth: Some(depth),
207 child_index: child_index as u32,
208 bip,
209 });
210 SerializedExtendedKeys {
211 xpub: bip32_extended_public_key,
212 xpriv: bip32_extended_private_key,
213 }
214}
215struct SerializeKeyArgs {
216 pub keys_to_serialize: Keys,
217 pub parent_public_key: Option<String>,
218 pub is_public: bool,
219 pub network: Network,
220 pub depth: Option<u8>,
221 pub child_index: u32,
222 pub bip: Bip,
223}
224
225#[derive(Copy, Clone)]
226pub enum Bip {
227 Bip32,
228 Bip44,
229 Bip49,
230 Bip84,
231 Bip86,
232}
233
234pub fn create_fingerprint(public_key_hex: &String) -> String {
235 let sha256_result_hex = sha256_hex(public_key_hex);
236 let sha256_result_array = decode_hex(&sha256_result_hex).unwrap();
237 let ripemd160_result = ripemd160::Hash::hash(&sha256_result_array);
238 let first_four_bytes = &ripemd160_result[..4];
239 let first_four_hex = encode_hex(&first_four_bytes);
240 first_four_hex
241}
242
243fn serialize_key(args: SerializeKeyArgs) -> String {
244 let SerializeKeyArgs {
245 keys_to_serialize,
246 parent_public_key,
247 is_public,
248 network,
249 depth,
250 child_index,
251 bip,
252 } = args;
253
254 fn checksum(hex: &String) -> String {
255 let hash = double_sha256_hex(&hex);
256 let hash_byte_array = decode_hex(&hash).unwrap();
257 let first_four_bytes = &hash_byte_array[0..=3];
258 encode_hex(first_four_bytes)
259 }
260
261 fn base58_encode(hex_byte_array: Vec<u8>) -> String {
262 let encoded = bitcoin::util::base58::encode_slice(&hex_byte_array);
263 encoded
264 }
265 let public_key_hex = match &keys_to_serialize {
266 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
267 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
268 };
269 let private_key_hex = match &keys_to_serialize {
270 Keys::NonMaster(non_master_keys) => non_master_keys.private_key_hex.clone(),
271 Keys::Master(master_keys) => master_keys.private_key_hex.clone(),
272 };
273 let chain_code_hex = match &keys_to_serialize {
274 Keys::NonMaster(non_master_keys) => non_master_keys.chain_code_hex.clone(),
275 Keys::Master(master_keys) => master_keys.chain_code_hex.clone(),
276 };
277 let is_hardened = match &keys_to_serialize {
278 Keys::NonMaster(non_master_keys) => non_master_keys.is_hardened.clone(),
279 Keys::Master(_master_keys) => false,
280 };
281
282 let version = match bip {
285 Bip::Bip32 | Bip::Bip44 => {
286 if is_public {
287 match network {
288 Network::Mainnet => "0488b21e",
289 Network::Testnet => "043587cf",
290 }
291 } else {
292 match network {
293 Network::Mainnet => "0488ade4",
294 Network::Testnet => "04358394",
295 }
296 }
297 }
298 Bip::Bip49 => {
299 if is_public {
301 match network {
302 Network::Mainnet => "049d7cb2",
303 Network::Testnet => "044a5262",
304 }
305 } else {
306 match network {
307 Network::Mainnet => "049d7878",
308 Network::Testnet => "044a4e28",
309 }
310 }
311 }
312 Bip::Bip84 | Bip::Bip86 => {
313 if is_public {
315 match network {
316 Network::Mainnet => "04b24746",
317 Network::Testnet => "045f1cf6",
318 }
319 } else {
320 match network {
321 Network::Mainnet => "04b2430c",
322 Network::Testnet => "045f18bc",
323 }
324 }
325 }
326 };
327 let key = if is_public {
328 format!("{}", public_key_hex)
329 } else {
330 format!("{}{}", "00", private_key_hex)
331 };
332
333 let depth = convert_decimal_to_8_byte_hex(depth.unwrap_or(0));
334 let parent_fingerprint = match &parent_public_key {
335 Some(parent_public_key) => create_fingerprint(&parent_public_key.to_string()),
336 None => "00000000".to_string(),
337 };
338 let child_index_with_hardened_factored_in = if is_hardened {
342 child_index + 2147483648 } else {
344 child_index
345 };
346 let child_number = convert_decimal_to_32_byte_hex(child_index_with_hardened_factored_in);
347 let chain_code = chain_code_hex;
348 let serialized = format!(
350 "{}{}{}{}{}{}",
351 version, depth, parent_fingerprint, child_number, chain_code, key
352 );
353
354 let serialized_bytes = decode_hex(&serialized).unwrap();
355 let checksum = checksum(&serialized);
356 let checksum_bytes = decode_hex(&checksum).unwrap();
357 let serialized_with_checksum = format!("{}{}", serialized, checksum);
358 let serialized_with_checksum_bytes = concat_u8(&serialized_bytes, &checksum_bytes);
359 let base58_encoded_serialized_with_checksum = base58_encode(serialized_with_checksum_bytes);
360 base58_encoded_serialized_with_checksum
361 }
364
365fn get_child_extended_public_key(
366 parent_chain_code: &[u8],
367 parent_public_key: &String,
368 child_index: i32,
369) -> (String, String) {
370 let parent_chain_code = parent_chain_code;
371 let key = parent_chain_code;
372 let index: i32 = child_index;
373 let index_as_bytes = index.to_be_bytes();
374 let parent_public_key_hex = parent_public_key.clone();
375 let parent_public_key_as_bytes = decode_hex(&parent_public_key).unwrap();
376 let parent_public_key_with_index_as_bytes =
377 concat_u8(&parent_public_key_as_bytes, &index_as_bytes);
378
379 let h = HMAC::mac(parent_public_key_with_index_as_bytes, key);
380 let left = &h[0..=31];
381 let right = &h[32..];
382 let secp = Secp256k1::new();
391 let sk = secp256k1::SecretKey::from_str(&encode_hex(left)).unwrap();
392 let pk = secp256k1::PublicKey::from_str(&parent_public_key_hex)
393 .expect("statistically impossible to hit");
394 let tweaked = pk.add_exp_tweak(&secp, &sk.into()).unwrap();
395
396 let child_public_key: String = tweaked.to_string();
397 let child_chain_code: String = encode_hex(right);
398
399 return (child_public_key, child_chain_code);
400}
401fn get_hardened_child_extended_private_key(
402 master_chain_code: &[u8],
403 master_private_key: &[u8],
404 child_index: u32,
405) -> Keys {
406 let key = master_chain_code;
407 let index: u32 = child_index + 2147483648; let index_as_bytes = index.to_be_bytes();
409 let master_private_key_as_bytes = master_private_key;
410 let prefix_bytes = decode_hex("00").unwrap();
411 let master_private_key_with_index_as_bytes =
412 concat_u8(master_private_key_as_bytes, &index_as_bytes);
413 let master_private_key_with_index_and_prefix_as_bytes =
414 concat_u8(&prefix_bytes, &master_private_key_with_index_as_bytes);
415
416 let h = HMAC::mac(master_private_key_with_index_and_prefix_as_bytes, key);
417 let left = &h[0..=31];
418 let right = &h[32..];
419 let sk = secp256k1::SecretKey::from_slice(left).expect("statistically impossible to hit");
421 let master_private_secret_key = SecretKey::from_str(&encode_hex(master_private_key)).unwrap();
422
423 let tweaked = sk
424 .add_tweak(&master_private_secret_key.into())
425 .expect("statistically impossible to hit");
426 let hardened_child_private_key: String = tweaked.display_secret().to_string();
427 let child_public_key = get_compressed_public_key_from_private_key(&hardened_child_private_key);
428
429 let child_private_key = hardened_child_private_key;
430 let child_chain_code = encode_hex(right);
431 let child_public_key = child_public_key;
432 let keys = Keys::NonMaster(NonMasterKeys {
433 private_key_hex: child_private_key,
434 public_key_hex: child_public_key,
435 chain_code_hex: child_chain_code,
436 is_hardened: true,
437 });
438 keys
439}
440fn get_child_extended_private_key(
441 master_chain_code: &[u8],
442 master_public_key: &String,
443 master_private_key: &[u8],
444 child_index: i32,
445) -> Keys {
446 let key = master_chain_code;
448 let index: i32 = child_index;
450 let index_as_bytes = index.to_be_bytes();
451 let master_public_key_as_bytes = master_public_key.as_bytes();
452 let master_public_key_as_bytes = decode_hex(&master_public_key).unwrap();
453 let master_public_key_with_index_as_bytes =
454 concat_u8(&master_public_key_as_bytes, &index_as_bytes);
455 let h = HMAC::mac(master_public_key_with_index_as_bytes, key);
456 let left = &h[0..=31];
457 let right = &h[32..];
458 let sk = secp256k1::SecretKey::from_slice(left).expect("statistically impossible to hit");
460 let master_private_secret_key = SecretKey::from_str(&encode_hex(master_private_key)).unwrap();
462
463 let tweaked = sk
464 .add_tweak(&master_private_secret_key.into())
465 .expect("statistically impossible to hit");
466 let child_private_key: String = tweaked.display_secret().to_string();
467 let child_public_key = get_compressed_public_key_from_private_key(&child_private_key);
468
469 let child_private_key = child_private_key;
470 let child_chain_code = encode_hex(right);
471 let child_public_key = child_public_key;
472 let keys = Keys::NonMaster(NonMasterKeys {
473 private_key_hex: child_private_key,
474 public_key_hex: child_public_key,
475 chain_code_hex: child_chain_code,
476 is_hardened: false,
477 });
478 keys
479}
480
481fn parse_derivation_path_child(derivation_path_child: &String) -> DerivationChild {
482 let child_split_into_hardened_key: Vec<&str> = derivation_path_child
483 .split(HARDENED_DERIVATION_CHARACTER)
484 .collect();
485 let is_hardened = child_split_into_hardened_key.len() == 2;
486 let child_index = child_split_into_hardened_key
487 .get(0)
488 .unwrap()
489 .parse()
490 .unwrap();
491 if is_hardened {
492 DerivationChild::Hardened(child_index)
493 } else {
494 DerivationChild::NonHardened(child_index)
495 }
496}
497fn get_child_index_from_derivation_path(derivation_path: &String) -> DerivationChild {
498 let derivation_path_split_by_dash: Vec<&str> = derivation_path.split('/').collect();
499 let first = derivation_path_split_by_dash.first().unwrap();
500 if first.to_string() != "m" {
501 panic!("derivation must start with m")
502 } else {
503 let last_item = derivation_path_split_by_dash.last().unwrap().to_string();
504 parse_derivation_path_child(&last_item)
505 }
506}
507
508fn split_derivation_path(derivation_path: String) -> Vec<String> {
509 let derivation_path_split_by_dash: Vec<&str> = derivation_path.split('/').collect();
510 let first = derivation_path_split_by_dash.first().unwrap();
511 if first.to_string() != "m" {
512 panic!("derivation must start with m")
513 } else {
514 let derivation_path_indexes: Vec<String> = derivation_path_split_by_dash[1..]
516 .iter()
517 .map(|s| s.to_string())
518 .collect();
519 derivation_path_indexes
520 }
521}
522
523fn get_child_key_from_derivation_path(derivation_path: String, master_keys: Keys) -> Keys {
524 let derivation_path_indexes = split_derivation_path(derivation_path);
525 let mut current_parent_keys = master_keys;
526 for derivation_path_item in derivation_path_indexes {
528 let derivation_child = parse_derivation_path_child(&derivation_path_item);
529
530 let child_keys = match derivation_child {
531 DerivationChild::NonHardened(child_index) => {
532 let should_harden = false;
533 get_child_key(¤t_parent_keys, child_index as i32, should_harden)
534 }
535 DerivationChild::Hardened(child_index) => {
536 let should_harden = true;
537 get_child_key(¤t_parent_keys, child_index as i32, should_harden)
538 }
539 };
540 current_parent_keys = child_keys;
542 }
543
544 current_parent_keys
545}
546fn get_children_keys_from_derivation_path(
547 derivation_path: &String,
548 master_keys: Keys,
549 children_count: i32,
550 should_be_hardened: bool,
551) -> HashMap<String, Keys> {
552 let child_key = get_child_key_from_derivation_path(derivation_path.to_string(), master_keys);
553 let child_keys = get_child_keys(&child_key, children_count, should_be_hardened);
554 child_keys
555}
556fn get_child_key(parent_keys: &Keys, child_index: i32, should_harden: bool) -> Keys {
557 let parent_chain_code_hex = match &parent_keys {
558 Keys::NonMaster(non_master_keys) => non_master_keys.chain_code_hex.clone(),
559 Keys::Master(master_keys) => master_keys.chain_code_hex.clone(),
560 };
561 let parent_private_key_hex = match parent_keys {
562 Keys::NonMaster(non_master_keys) => non_master_keys.private_key_hex.clone(),
563 Keys::Master(master_keys) => master_keys.private_key_hex.clone(),
564 };
565 let parent_public_key_hex = match parent_keys {
566 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
567 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
568 };
569 let parent_chain_code_bytes = decode_hex(&parent_chain_code_hex).unwrap();
570 let parent_private_key_bytes = decode_hex(&parent_private_key_hex).unwrap();
571 if should_harden {
572 get_hardened_child_extended_private_key(
573 &parent_chain_code_bytes,
574 &parent_private_key_bytes,
575 child_index as u32,
576 )
577 } else {
578 get_child_extended_private_key(
579 &parent_chain_code_bytes,
580 &parent_public_key_hex.clone(),
581 &parent_private_key_bytes,
582 child_index as i32,
583 )
584 }
585}
586fn get_child_keys(
587 parent_keys: &Keys,
588 children_count: i32,
589 should_be_hardened: bool,
590) -> HashMap<String, Keys> {
591 let mut children = HashMap::new();
592 for child_index in 0..=children_count {
593 if should_be_hardened {
594 let child_keys_hardened = get_child_key(parent_keys, child_index as i32, true);
595 let hash_key = format!("{}'", child_index);
596 children.insert(hash_key, child_keys_hardened);
597 } else {
598 let child_keys = get_child_key(parent_keys, child_index as i32, false);
599 let hash_key = format!("{}", child_index);
600 children.insert(hash_key, child_keys);
601 }
602 }
603 children
604}
605
606fn get_depth_from_derivation_path(derivation_path: &String) -> u8 {
607 let derivation_path_split_by_dash: Vec<&str> = derivation_path.split('/').collect();
608 let first = derivation_path_split_by_dash.first().unwrap();
609 if first.to_string() != "m" {
610 panic!("derivation must start with m")
611 } else {
612 let derivation_path_without_m = derivation_path_split_by_dash.get(1..).unwrap();
613 let depth = derivation_path_without_m.len() as u8;
614 depth
615 }
616}
617fn get_parent_derivation_path(derivation_path: &String) -> String {
618 let derivation_path_split_by_dash: Vec<&str> = derivation_path.split('/').collect();
619 let first = derivation_path_split_by_dash.first().unwrap();
620 if first.to_string() != "m" {
621 panic!("derivation must start with m")
622 } else {
623 derivation_path_split_by_dash
624 .get(0..=derivation_path_split_by_dash.len() - 2)
625 .unwrap()
626 .join("/")
627 }
628}
629
630pub fn get_128_bits_of_entropy() -> [u8; 32] {
633 let mut data = [0u8; 32];
634 rand::thread_rng().fill_bytes(&mut data);
635 data
636}
637
638pub fn get_256_bits_of_entropy() -> [u8; 64] {
640 let mut data = [0u8; 64];
641 rand::thread_rng().fill_bytes(&mut data);
642 data
643}
644pub fn get_mnemonic_words(entropy: Vec<u8>) -> Vec<String> {
645 let entropy_hex_string = get_hex_string_from_byte_array(&entropy);
648
649 let entropy_hex_byte_array = decode_hex(&entropy_hex_string).unwrap();
651
652 let sha256_result = sha256_entropy_hex_byte_array(&entropy_hex_byte_array);
654 let entropy_hex_binary_string = get_binary_string_for_byte_array(&entropy_hex_byte_array);
656 let bits_to_append_count = (&entropy_hex_binary_string.len()) / 32;
657 let sha256_result_binary_string = get_binary_string_for_byte_array(&sha256_result);
658 let checksum_binary_string = &sha256_result_binary_string[0..bits_to_append_count];
659
660 let entropy_plus_checksum_binary =
662 format!("{}{}", entropy_hex_binary_string, checksum_binary_string);
663
664 let word_binary = split_binary_string_into_framents_of_11_bits(&entropy_plus_checksum_binary);
665
666 let words: Vec<String> = word_binary
667 .iter()
668 .map(|word_binary_string| {
669 let word_num = convert_binary_to_int(word_binary_string);
670 WORDS.get(word_num as usize).unwrap().to_string()
671 })
672 .collect();
673 words
674}
675fn get_mnemonic_sentence(mnemonic_words: &Vec<String>) -> String {
676 mnemonic_words.join(" ")
677}
678
679fn get_bip38_512_bit_private_key(words: Vec<String>, passphrase: Option<String>) -> String {
680 let mnemonic_sentence = words.join(" ");
681
682 const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
684 let n_iter = NonZeroU32::new(2048).unwrap();
685 let rng = thread_rng();
686 let passphrase = match passphrase {
690 Some(passphrase) => passphrase,
691 None => "".to_string(),
692 };
693 let salt = format!("{}{}", "mnemonic", passphrase);
694 let mut salt_as_bytes = salt.as_bytes().to_owned();
695 let password = mnemonic_sentence.clone();
698 let mut password_as_bytes = password.as_bytes().to_owned();
699 let mut pbkdf2_hash = [0u8; CREDENTIAL_LEN];
700
701 pbkdf2::derive(
702 pbkdf2::PBKDF2_HMAC_SHA512,
703 n_iter,
704 &salt_as_bytes,
705 password.as_bytes(),
706 &mut pbkdf2_hash,
707 );
708
709 let bip39_seed = encode_hex(&pbkdf2_hash);
710
711 let wrong_password = "Definitely not the correct password";
713 let should_fail = pbkdf2::verify(
714 pbkdf2::PBKDF2_HMAC_SHA512,
715 n_iter,
716 &salt.as_bytes(),
717 wrong_password.as_bytes(),
718 &pbkdf2_hash,
719 );
720 match should_fail {
721 Err(err) => {}
722 _ => panic!("SOULD HAVE ERRORERED"),
723 }
724
725 bip39_seed
726}
727fn get_master_keys_from_seed(bip39_seed: &String) -> MasterKeys {
728 let pbkdf2_hash = decode_hex(&bip39_seed).unwrap();
729 let key = "Bitcoin seed";
730 let h = HMAC::mac(pbkdf2_hash.to_vec(), key.as_bytes());
731 let left = &h[0..=31];
732 let master_private_key = left;
733 let master_private_key_hex = encode_hex(master_private_key);
734 let right = &h[32..];
735 let master_chain_code = right;
736
737 let master_public_key = get_compressed_public_key_from_private_key(&master_private_key_hex);
741 let keys = MasterKeys {
742 public_key_hex: master_public_key,
743 private_key_hex: master_private_key_hex,
744 chain_code_hex: encode_hex(master_chain_code),
745 };
746 keys
747}
748fn get_bip32_root_key_from_seed(bip39_seed: &String, network: Network, bip: Bip) -> String {
749 let master_keys = get_master_keys_from_seed(&bip39_seed.to_string());
750 let serialized_extended_master_keys = master_keys.serialize(network, bip);
751
752 let master_xprv = serialized_extended_master_keys.xpriv;
753 master_xprv
754}
755fn get_bip32_root_key_from_master_keys(
756 master_keys: &MasterKeys,
757 network: Network,
758 bip: Bip,
759) -> String {
760 let serialized_extended_master_keys = master_keys.serialize(network, bip);
761
762 let master_xprv = serialized_extended_master_keys.xpriv;
763 master_xprv
764}
765fn get_bip32_extended_keys_from_derivation_path(
766 derivation_path: &String,
767 master_keys: &Keys,
768 network: Network,
769 bip: Bip,
770) -> SerializedExtendedKeys {
771 let parent_deviation_path = get_parent_derivation_path(derivation_path);
772 let derivation_child = get_child_index_from_derivation_path(derivation_path);
773 let derivation_child_index = match derivation_child {
774 DerivationChild::NonHardened(child_index) => child_index,
775 DerivationChild::Hardened(child_index) => child_index,
776 };
777 let found_child =
778 get_child_key_from_derivation_path(derivation_path.to_string(), master_keys.clone());
779 let parent_keys =
780 get_child_key_from_derivation_path(parent_deviation_path, master_keys.clone());
781 let depth = get_depth_from_derivation_path(&derivation_path.to_string());
782
783 let parent_public_key_hex = match parent_keys {
784 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex,
785 Keys::Master(master_keys) => master_keys.public_key_hex,
786 };
787
788 let bip32_extended_keys = match found_child {
789 Keys::NonMaster(non_master_keys) => non_master_keys.serialize(
790 parent_public_key_hex,
791 depth,
792 derivation_child_index,
793 network,
794 bip,
795 ),
796 Keys::Master(master_keys) => master_keys.serialize(network, bip),
797 };
798
799 bip32_extended_keys
800}
801
802fn get_derived_addresses_for_derivation_path(
803 derivation_path: &String,
804 master_keys: &MasterKeys,
805 child_count: i32,
806 should_use_hardened_addresses: bool,
807) -> HashMap<String, Keys> {
808 let found_children = get_children_keys_from_derivation_path(
809 &derivation_path,
810 Keys::Master(master_keys.clone()),
811 child_count,
812 should_use_hardened_addresses,
813 );
814 let mut found_children_with_full_derivation_path_as_key: HashMap<String, Keys> = HashMap::new();
815 for (key, value) in found_children {
816 let full_derivation_path_with_child = format!("{}/{}", derivation_path, key);
817 found_children_with_full_derivation_path_as_key
818 .insert(full_derivation_path_with_child, value);
819 }
820 found_children_with_full_derivation_path_as_key
821}
822
823fn decode_serialized_extended_key(extended_key_serialized: &str) -> DecodedExtendedKeySerialized {
824 let decoded_result = from_check(extended_key_serialized).unwrap();
826 let index_of_last_byte_of_version = 3;
827 let version_bytes = decoded_result
828 .get(0..=index_of_last_byte_of_version)
829 .unwrap();
830 let version_hex = encode_hex(version_bytes);
831 let (network, is_public) = match version_hex.as_str() {
832 "0488b21e" => (Network::Mainnet, true),
834 "043587cf" => (Network::Testnet, true),
835 "0488ade4" => (Network::Mainnet, false),
836 "04358394" => (Network::Testnet, false),
837 "049d7cb2" => (Network::Mainnet, true),
839 "044a5262" => (Network::Testnet, true),
840 "049d7878" => (Network::Mainnet, false),
841 "044a4e28" => (Network::Testnet, false),
842 "04b24746" => (Network::Mainnet, true),
844 "045f1cf6" => (Network::Testnet, true),
845 "04b2430c" => (Network::Mainnet, false),
846 "045f18bc" => (Network::Testnet, false),
847 _ => panic!("Version not recognized: {}", version_hex),
848 };
849
850 let index_where_private_key_starts = decoded_result.len() - (64 / 2);
855 let index_where_chain_code_starts = index_where_private_key_starts - (64 / 2) - 1;
856 let key_bytes = decoded_result
857 .get(index_where_private_key_starts..)
858 .unwrap();
859 let chain_code_bytes = decoded_result
862 .get(
863 index_where_chain_code_starts
864 ..(index_where_private_key_starts - (if is_public { 0 } else { 1 })),
865 )
866 .unwrap();
867 let key_hex = encode_hex(&key_bytes);
868 let chain_code_hex = encode_hex(&chain_code_bytes);
869
870 let depth_fingerprint_child_index_bytes = decoded_result
871 .get((index_of_last_byte_of_version + 1)..index_where_chain_code_starts)
872 .unwrap();
873 let depth_fingerprint_child_index_hex = encode_hex(&depth_fingerprint_child_index_bytes);
874 let depth_byte = depth_fingerprint_child_index_bytes.get(0).unwrap().clone();
875 let depth_hex = encode_hex(&[depth_byte]);
876 let depth_decimal = convert_hex_to_decimal(&depth_hex).unwrap() as u8;
877 let depth = depth_fingerprint_child_index_bytes.get(0..=1).unwrap();
878 let depth_hex = encode_hex(&depth);
879
880 let parent_fingerprint_bytes = depth_fingerprint_child_index_bytes.get(1..=4).unwrap();
881 let parent_fingerprint_hex = encode_hex(parent_fingerprint_bytes);
882
883 let child_index_bytes = depth_fingerprint_child_index_bytes.get(5..).unwrap();
884 let child_index_hex = encode_hex(&child_index_bytes);
885 let child_index_decimal = convert_hex_to_decimal(&child_index_hex).unwrap() as u32;
886 if is_public {
887 DecodedExtendedKeySerialized::PublicKey(DecodedExtendedSerializedPublicKey {
888 version_hex,
889 network,
890 depth_fingerprint_child_index_hex,
891 depth: depth_decimal,
892 parent_fingerprint: parent_fingerprint_hex,
893 child_index: child_index_decimal,
894 chain_code_hex,
895 public_key_hex_uncompressed: key_hex,
896 })
897 } else {
898 DecodedExtendedKeySerialized::PrivateKey(DecodedExtendedSerializedPrivateKey {
899 version_hex,
900 network,
901 depth_fingerprint_child_index_hex,
902 depth: depth_decimal,
903 parent_fingerprint: parent_fingerprint_hex,
904 child_index: child_index_decimal,
905 chain_code_hex,
906 private_key_hex: key_hex.clone(),
907 wif_compressed: get_wif_from_private_key(&key_hex, network, true),
908 wif_uncompressed: get_wif_from_private_key(&key_hex, network, false),
909 public_key_hex_uncompressed: get_public_key_from_private_key(&key_hex, false),
910 public_key_hex_compressed: get_public_key_from_private_key(&key_hex, true),
911 })
912 }
913}
914fn get_master_keys_from_serialized_extended_private_master_key(
915 serialized_extended_private_key: &String,
916) -> MasterKeys {
917 let decoded_serialized_extended_key =
918 decode_serialized_extended_key(serialized_extended_private_key);
919 let decoded_xpriv_keys = match decoded_serialized_extended_key.clone() {
920 DecodedExtendedKeySerialized::PrivateKey(decoded_extended_serialized_private_key) => {
921 decoded_extended_serialized_private_key
922 }
923 DecodedExtendedKeySerialized::PublicKey(_) => panic!("shouldn happen"),
924 };
925 if decoded_xpriv_keys.depth == 0 && decoded_xpriv_keys.child_index == 0 {
926 let master_keys = MasterKeys {
927 private_key_hex: decoded_xpriv_keys.private_key_hex,
928 public_key_hex: decoded_xpriv_keys.public_key_hex_uncompressed,
929 chain_code_hex: decoded_xpriv_keys.chain_code_hex,
930 };
931 master_keys
932 } else {
933 panic!("must pass a master extended key here, not a child");
934 }
935}
936fn get_master_keys_from_bip32_root_key(bip32_root_key: &String) -> MasterKeys {
938 get_master_keys_from_serialized_extended_private_master_key(bip32_root_key)
939}
940fn get_bip32_derived_addresses(
941 bip32_derivation_path: &String,
942 master_keys: &MasterKeys,
943 children_count: i32,
944 should_harden: bool,
945) -> HashMap<String, Keys> {
946 let found_children = get_derived_addresses_for_derivation_path(
953 &bip32_derivation_path,
954 master_keys,
955 children_count,
956 should_harden,
957 );
958 found_children
959}
960
961#[derive(Debug, Clone)]
962pub struct DerivedAdresses {
963 pub external: HashMap<String, Keys>,
964 pub internal: HashMap<String, Keys>,
965}
966
967fn get_derived_addresses_from_5_levels(
968 purpose: u8,
969 cointype: i32,
970 account: i32,
971 should_include_change_addresses: bool,
973 master_keys: &MasterKeys,
974 children_count: i32,
975 should_harden: bool,
976) -> DerivedAdresses {
977 let bip44_derivation_path_for_external_chain =
978 format!("m/{}'/{}'/{}'/0", purpose, cointype, account.to_string()).to_string(); let bip44_derivation_path_for_internal_chain =
982 format!("m/{}'/{}'/{}'/1", purpose, cointype, account.to_string()).to_string(); let found_children_for_external_chain = get_derived_addresses_for_derivation_path(
991 &bip44_derivation_path_for_external_chain,
992 &master_keys,
993 children_count,
994 should_harden,
995 );
996
997 let found_children_for_internal_chain = get_derived_addresses_for_derivation_path(
998 &bip44_derivation_path_for_internal_chain,
999 &master_keys,
1000 children_count,
1001 should_harden,
1002 );
1003
1004 DerivedAdresses {
1005 internal: found_children_for_internal_chain,
1006 external: found_children_for_external_chain,
1007 }
1008}
1009
1010fn get_bip44_derived_addresses(
1013 coin_type: i32,
1014 account: i32,
1015 should_include_change_addresses: bool,
1016 master_keys: &MasterKeys,
1017 children_count: i32,
1018 should_harden: bool,
1019) -> DerivedAdresses {
1020 let purpose = 44;
1024 get_derived_addresses_from_5_levels(
1025 purpose,
1026 coin_type,
1027 account,
1028 should_include_change_addresses,
1029 master_keys,
1030 children_count,
1031 should_harden,
1032 )
1033}
1034fn get_bip49_derived_addresses(
1037 coin_type: i32,
1038 account: i32,
1039 should_include_change_addresses: bool,
1040 master_keys: &MasterKeys,
1041 children_count: i32,
1042 should_harden: bool,
1043) -> DerivedAdresses {
1044 let purpose = 49;
1048 get_derived_addresses_from_5_levels(
1049 purpose,
1050 coin_type,
1051 account,
1052 should_include_change_addresses,
1053 master_keys,
1054 children_count,
1055 should_harden,
1056 )
1057}
1058fn get_bip84_derived_addresses(
1061 coin_type: i32,
1062 account: i32,
1063 should_include_change_addresses: bool,
1064 master_keys: &MasterKeys,
1065 children_count: i32,
1066 should_harden: bool,
1067) -> DerivedAdresses {
1068 let purpose = 84;
1072 get_derived_addresses_from_5_levels(
1073 purpose,
1074 coin_type,
1075 account,
1076 should_include_change_addresses,
1077 master_keys,
1078 children_count,
1079 should_harden,
1080 )
1081}
1082fn get_bip86_derived_addresses(
1085 coin_type: i32,
1086 account: i32,
1087 should_include_change_addresses: bool,
1088 master_keys: &MasterKeys,
1089 children_count: i32,
1090 should_harden: bool,
1091) -> DerivedAdresses {
1092 let purpose = 86;
1096 get_derived_addresses_from_5_levels(
1097 purpose,
1098 coin_type,
1099 account,
1100 should_include_change_addresses,
1101 master_keys,
1102 children_count,
1103 should_harden,
1104 )
1105}
1106
1107#[derive(Debug)]
1108struct Bip44DerivationPathInfo {
1109 account_extended_private_key: String,
1110 account_extended_public_key: String,
1111}
1112fn get_bip44_derivation_path_info(
1113 cointype: i32,
1114 account: i32,
1115 master_keys: &MasterKeys,
1116 network: Network,
1117) -> Bip44DerivationPathInfo {
1118 let purpose = 44;
1119 let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, cointype, account);
1120 let bip32_extended_keys_for_account = get_bip32_extended_keys_from_derivation_path(
1121 &account_derivation_path.to_string(),
1122 &Keys::Master(master_keys.clone()),
1123 network,
1124 Bip::Bip44,
1125 );
1126
1127 Bip44DerivationPathInfo {
1128 account_extended_private_key: bip32_extended_keys_for_account.xpriv,
1129 account_extended_public_key: bip32_extended_keys_for_account.xpub,
1130 }
1131}
1132#[derive(Debug)]
1133struct Bip49DerivationPathInfo {
1134 account_extended_private_key: String,
1135 account_extended_public_key: String,
1136}
1137fn get_bip49_derivation_path_info(
1138 coin_type: i32,
1139 account: i32,
1140 master_keys: &MasterKeys,
1141 network: Network,
1142) -> Bip49DerivationPathInfo {
1143 let purpose = 49;
1144 let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1145 let bip32_extended_keys_for_account = get_bip32_extended_keys_from_derivation_path(
1146 &account_derivation_path.to_string(),
1147 &Keys::Master(master_keys.clone()),
1148 network,
1149 Bip::Bip49,
1150 );
1151
1152 Bip49DerivationPathInfo {
1153 account_extended_private_key: bip32_extended_keys_for_account.xpriv,
1154 account_extended_public_key: bip32_extended_keys_for_account.xpub,
1155 }
1156}
1157#[derive(Debug)]
1158struct Bip84DerivationPathInfo {
1159 account_extended_private_key: String,
1160 account_extended_public_key: String,
1161}
1162fn get_bip84_derivation_path_info(
1163 coin_type: i32,
1164 account: i32,
1165 master_keys: &MasterKeys,
1166 network: Network,
1167) -> Bip84DerivationPathInfo {
1168 let purpose = 84;
1169 let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1170 let bip32_extended_keys_for_account = get_bip32_extended_keys_from_derivation_path(
1171 &account_derivation_path.to_string(),
1172 &Keys::Master(master_keys.clone()),
1173 network,
1174 Bip::Bip84,
1175 );
1176
1177 Bip84DerivationPathInfo {
1178 account_extended_private_key: bip32_extended_keys_for_account.xpriv,
1179 account_extended_public_key: bip32_extended_keys_for_account.xpub,
1180 }
1181}
1182#[derive(Debug)]
1183struct Bip86DerivationPathInfo {
1184 account_extended_private_key: String,
1185 account_extended_public_key: String,
1186}
1187fn get_bip86_derivation_path_info(
1188 coin_type: i32,
1189 account: i32,
1190 master_keys: &MasterKeys,
1191 network: Network,
1192) -> Bip86DerivationPathInfo {
1193 let purpose = 86;
1194 let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1195 let bip32_extended_keys_for_account = get_bip32_extended_keys_from_derivation_path(
1196 &account_derivation_path.to_string(),
1197 &Keys::Master(master_keys.clone()),
1198 network,
1199 Bip::Bip84,
1200 );
1201
1202 Bip86DerivationPathInfo {
1203 account_extended_private_key: bip32_extended_keys_for_account.xpriv,
1204 account_extended_public_key: bip32_extended_keys_for_account.xpub,
1205 }
1206}
1207
1208#[derive(Debug)]
1209pub struct HDWalletBip32 {
1210 pub network: Network,
1211 pub bip39_seed: String,
1212 pub master_keys: MasterKeys,
1213 pub bip32_root_key: String,
1214 pub bip32_root_pub_key: String,
1215 pub bip32_derivation_path: String,
1216 pub bip32_extended_private_key: String,
1217 pub bip32_extended_public_key: String,
1218 pub master_fingerprint: String,
1219 pub derived_addresses: HashMap<String, Keys>,
1220}
1221impl HDWalletBip32 {
1222 pub fn pretty_print_derived_addressed(
1223 &self,
1224 network: Network,
1225 address_type: AddressType,
1226 ) -> () {
1227 for (key, value) in self.derived_addresses.clone() {
1228 let should_compress = true;
1229 let public_key_hex = match &value {
1230 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1231 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1232 };
1233 let address = value.get_address(network, address_type);
1234 println!(
1235 "{} {} {} {} {} {}",
1236 key,
1237 address,
1238 get_public_key_hash_from_address(&address),
1239 get_public_key_hash_from_public_key(&public_key_hex),
1240 public_key_hex,
1241 value.get_wif(network, should_compress)
1242 )
1243 }
1244 }
1245}
1246
1247pub fn generate_bip32_hd_wallet_from_mnemonic_words(
1248 mnemonic_words: Vec<String>,
1249 password: Option<String>,
1250 derivation_path: String,
1251 children_count: i32,
1252 should_harden: bool,
1253 network: Network,
1254) -> HDWalletBip32 {
1255 let bip = Bip::Bip32;
1256 let passphrase = match password {
1257 Some(password) => password,
1258 None => "".to_string(),
1259 };
1260 let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1261 let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1262 let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1265 let master_keys_generated_from_bip32_root_key =
1267 get_master_keys_from_bip32_root_key(&bip32_root_key);
1268 let master_keys = master_keys_generated_from_seed;
1269 let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1272 let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1273 let serialized_extended_master_keys = master_keys.serialize(network, bip);
1275
1276 let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1277
1278 let bip32_extended_keys = get_bip32_extended_keys_from_derivation_path(
1279 &derivation_path,
1280 &Keys::Master(master_keys.clone()),
1281 network,
1282 bip,
1283 );
1284 let xpriv = &bip32_extended_keys.xpriv;
1285 let xpub = &bip32_extended_keys.xpub;
1286
1287 let found_children = get_bip32_derived_addresses(
1288 &derivation_path,
1289 &master_keys,
1290 children_count,
1291 should_harden,
1292 );
1293
1294 HDWalletBip32 {
1295 network,
1296 master_keys,
1297 bip39_seed,
1298 bip32_root_key,
1299 bip32_root_pub_key,
1300 master_fingerprint,
1301 bip32_derivation_path: derivation_path,
1302 bip32_extended_private_key: xpriv.to_string(),
1303 bip32_extended_public_key: xpub.to_string(),
1304 derived_addresses: found_children,
1305 }
1306}
1307#[derive(Debug)]
1308pub struct HDWalletBip44 {
1309 pub network: Network,
1310 pub bip39_seed: String,
1311 pub master_keys: MasterKeys,
1312 pub bip32_root_key: String,
1313 pub bip32_root_pub_key: String,
1314 pub master_fingerprint: String,
1315 pub purpose: i32,
1316 pub coin_type: i32,
1317 pub account: i32,
1318 pub account_derivation_path: String,
1320 pub account_extended_private_key: String,
1321 pub account_extended_public_key: String,
1322 pub derivation_path_external: String,
1323 pub bip32_extended_private_key_for_external: String,
1324 pub bip32_extended_public_key_for_external: String,
1325 pub derivation_path_internal: String,
1326 pub bip32_extended_private_key_for_internal: String,
1327 pub bip32_extended_public_key_for_internal: String,
1328 pub derived_addresses: DerivedAdresses,
1329}
1330impl HDWalletBip44 {
1331 pub fn pretty_print_derived_addressed(&self, network: Network) -> () {
1332 let address_type = AddressType::P2PKH;
1333 for (key, value) in self.derived_addresses.external.clone() {
1334 let should_compress = true;
1335 let public_key_hex = match &value {
1336 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1337 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1338 };
1339 let address = value.get_address(network, address_type);
1340 println!(
1341 "{} {} {} {} {} {}",
1342 key,
1343 address,
1344 get_public_key_hash_from_address(&address),
1345 get_public_key_hash_from_public_key(&public_key_hex),
1346 public_key_hex,
1347 value.get_wif(network, should_compress)
1348 )
1349 }
1350 for (key, value) in self.derived_addresses.internal.clone() {
1351 let should_compress = true;
1352 let public_key_hex = match &value {
1353 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1354 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1355 };
1356 let address = value.get_address(network, address_type);
1357 println!(
1358 "{} {} {} {} {} {}",
1359 key,
1360 address,
1361 get_public_key_hash_from_address(&address),
1362 get_public_key_hash_from_public_key(&public_key_hex),
1363 public_key_hex,
1364 value.get_wif(network, should_compress)
1365 )
1366 }
1367 }
1368}
1369pub fn generate_bip44_hd_wallet_from_mnemonic_words(
1370 mnemonic_words: Vec<String>,
1371 password: Option<String>,
1372 coin_type: i32,
1373 account: i32,
1374 children_count: i32,
1375 should_harden: bool,
1376 network: Network,
1377) -> HDWalletBip44 {
1378 let bip = Bip::Bip44;
1379 let purpose = 44;
1380
1381 let passphrase = match password {
1382 Some(password) => password,
1383 None => "".to_string(),
1384 };
1385 let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1386 let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1387 let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1390 let master_keys_generated_from_bip32_root_key =
1392 get_master_keys_from_bip32_root_key(&bip32_root_key);
1393 let master_keys = master_keys_generated_from_seed;
1394 let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1397 let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1399 let serialized_extended_master_keys = master_keys.serialize(network, bip);
1400
1401 let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1402 let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1403 let derivation_path_external = format!("{}/0", account_derivation_path);
1404 let bip32_extended_keys_for_external = get_bip32_extended_keys_from_derivation_path(
1405 &derivation_path_external,
1406 &Keys::Master(master_keys.clone()),
1407 network,
1408 bip,
1409 );
1410 let bip32_extended_private_key_for_external = bip32_extended_keys_for_external.xpriv;
1411 let bip32_extended_public_key_for_external = bip32_extended_keys_for_external.xpub;
1412 let derivation_path_internal = format!("{}/1", account_derivation_path);
1414 let bip32_extended_keys_for_internal = get_bip32_extended_keys_from_derivation_path(
1415 &derivation_path_internal,
1416 &Keys::Master(master_keys.clone()),
1417 network,
1418 bip,
1419 );
1420 let bip32_extended_private_key_for_internal = bip32_extended_keys_for_internal.xpriv;
1421 let bip32_extended_public_key_for_internal = bip32_extended_keys_for_internal.xpub;
1422
1423 let should_include_change_addresses = true;
1424 let found_children = get_bip44_derived_addresses(
1425 coin_type,
1426 account,
1427 should_include_change_addresses,
1428 &master_keys,
1429 children_count,
1430 should_harden,
1431 );
1432 let bip44_derivation_path_info =
1433 get_bip44_derivation_path_info(coin_type, account, &master_keys.clone(), network);
1434 HDWalletBip44 {
1437 network,
1438 bip39_seed,
1439 master_keys,
1440 bip32_root_key,
1441 bip32_root_pub_key,
1442 master_fingerprint,
1443 purpose,
1444 coin_type,
1445 account,
1446 account_derivation_path,
1448 account_extended_private_key: bip44_derivation_path_info.account_extended_private_key,
1449 account_extended_public_key: bip44_derivation_path_info.account_extended_public_key,
1450 derivation_path_external,
1451 bip32_extended_private_key_for_external,
1452 bip32_extended_public_key_for_external,
1453 derivation_path_internal,
1454 bip32_extended_private_key_for_internal,
1455 bip32_extended_public_key_for_internal,
1456 derived_addresses: found_children,
1457 }
1458}
1459#[derive(Debug)]
1460pub struct HDWalletBip49 {
1461 pub network: Network,
1462 pub master_keys: MasterKeys,
1463 pub bip39_seed: String,
1464 pub bip32_root_key: String,
1465 pub bip32_root_pub_key: String,
1466 pub master_fingerprint: String,
1467 pub purpose: i32,
1468 pub coin_type: i32,
1469 pub account: i32,
1470 pub account_derivation_path: String,
1472 pub account_extended_private_key: String,
1473 pub account_extended_public_key: String,
1474 pub derivation_path_external: String,
1475 pub bip32_extended_private_key_for_external: String,
1476 pub bip32_extended_public_key_for_external: String,
1477 pub derivation_path_internal: String,
1478 pub bip32_extended_private_key_for_internal: String,
1479 pub bip32_extended_public_key_for_internal: String,
1480 pub derived_addresses: DerivedAdresses,
1481}
1482impl HDWalletBip49 {
1483 pub fn pretty_print_derived_addressed(&self, network: Network) -> () {
1484 let address_type = AddressType::P2SH;
1485 for (key, value) in self.derived_addresses.external.clone() {
1486 let should_compress = true;
1487 let public_key_hex = match &value {
1488 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1489 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1490 };
1491 let address = value.get_address(network, address_type);
1492 println!(
1493 "{} {} {} {} {}",
1494 key,
1495 address,
1496 get_public_key_hash_from_public_key(&public_key_hex),
1498 public_key_hex,
1499 value.get_wif(network, should_compress)
1500 )
1501 }
1502 for (key, value) in self.derived_addresses.internal.clone() {
1503 let should_compress = true;
1504 let public_key_hex = match &value {
1505 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1506 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1507 };
1508 let address = value.get_address(network, address_type);
1509 println!(
1510 "{} {} {} {} {}",
1511 key,
1512 address,
1513 get_public_key_hash_from_public_key(&public_key_hex),
1515 public_key_hex,
1516 value.get_wif(network, should_compress)
1517 )
1518 }
1519 }
1520}
1521pub fn generate_bip49_hd_wallet_from_mnemonic_words(
1522 mnemonic_words: Vec<String>,
1523 password: Option<String>,
1524 coin_type: i32,
1525 account: i32,
1526 children_count: i32,
1527 should_harden: bool,
1528 network: Network,
1529) -> HDWalletBip49 {
1530 let bip = Bip::Bip49;
1531 let purpose = 49;
1532
1533 let passphrase = match password {
1534 Some(password) => password,
1535 None => "".to_string(),
1536 };
1537 let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1538 let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1539 let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1542 let master_keys_generated_from_bip32_root_key =
1544 get_master_keys_from_bip32_root_key(&bip32_root_key);
1545 let master_keys = master_keys_generated_from_seed;
1546 let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1549 let serialized_extended_master_keys = master_keys.serialize(network, bip);
1551
1552 let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1553 let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1554
1555 let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1556 let derivation_path_external = format!("{}/0", account_derivation_path);
1557 let bip32_extended_keys_for_external = get_bip32_extended_keys_from_derivation_path(
1558 &derivation_path_external,
1559 &Keys::Master(master_keys.clone()),
1560 network,
1561 bip,
1562 );
1563 let bip32_extended_private_key_for_external = bip32_extended_keys_for_external.xpriv;
1564 let bip32_extended_public_key_for_external = bip32_extended_keys_for_external.xpub;
1565 let derivation_path_internal = format!("{}/1", account_derivation_path);
1567 let bip32_extended_keys_for_internal = get_bip32_extended_keys_from_derivation_path(
1568 &derivation_path_internal,
1569 &Keys::Master(master_keys.clone()),
1570 network,
1571 bip,
1572 );
1573 let bip32_extended_private_key_for_internal = bip32_extended_keys_for_internal.xpriv;
1574 let bip32_extended_public_key_for_internal = bip32_extended_keys_for_internal.xpub;
1575
1576 let should_include_change_addresses = true;
1577 let found_children = get_bip49_derived_addresses(
1578 coin_type,
1579 account,
1580 should_include_change_addresses,
1581 &master_keys,
1582 children_count,
1583 should_harden,
1584 );
1585 let bip49_derivation_path_info =
1586 get_bip49_derivation_path_info(coin_type, account, &master_keys.clone(), network);
1587
1588 HDWalletBip49 {
1589 network,
1590 bip39_seed,
1591 master_keys,
1592 bip32_root_key,
1593 bip32_root_pub_key,
1594 master_fingerprint,
1595 purpose,
1596 coin_type,
1597 account,
1598 account_derivation_path,
1600 account_extended_private_key: bip49_derivation_path_info.account_extended_private_key,
1601 account_extended_public_key: bip49_derivation_path_info.account_extended_public_key,
1602 derivation_path_external,
1603 bip32_extended_private_key_for_external,
1604 bip32_extended_public_key_for_external,
1605 derivation_path_internal,
1606 bip32_extended_private_key_for_internal,
1607 bip32_extended_public_key_for_internal,
1608 derived_addresses: found_children,
1609 }
1610}
1611#[derive(Debug)]
1612pub struct HDWalletBip84 {
1613 pub network: Network,
1614 pub bip39_seed: String,
1615 pub master_keys: MasterKeys,
1616 pub bip32_root_key: String,
1617 pub bip32_root_pub_key: String,
1618 pub master_fingerprint: String,
1619 pub purpose: i32,
1620 pub coin_type: i32,
1621 pub account: i32,
1622 pub account_derivation_path: String,
1624 pub account_extended_private_key: String,
1625 pub account_extended_public_key: String,
1626 pub derivation_path_external: String,
1627 pub bip32_extended_private_key_for_external: String,
1628 pub bip32_extended_public_key_for_external: String,
1629 pub derivation_path_internal: String,
1630 pub bip32_extended_private_key_for_internal: String,
1631 pub bip32_extended_public_key_for_internal: String,
1632 pub derived_addresses: DerivedAdresses,
1633}
1634impl HDWalletBip84 {
1635 pub fn pretty_print_derived_addressed(&self, network: Network) -> () {
1636 let address_type = AddressType::P2WPKH;
1637 for (key, value) in self.derived_addresses.external.clone() {
1638 let should_compress = true;
1639 let public_key_hex = match &value {
1640 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1641 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1642 };
1643 let address = value.get_address(network, address_type);
1644 println!(
1645 "{} {} {} {} {} {}",
1646 key,
1647 address,
1648 get_public_key_hash_from_address(&address),
1649 get_public_key_hash_from_public_key(&public_key_hex),
1650 public_key_hex,
1651 value.get_wif(network, should_compress)
1652 )
1653 }
1654 for (key, value) in self.derived_addresses.internal.clone() {
1655 let should_compress = true;
1656 let public_key_hex = match &value {
1657 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1658 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1659 };
1660 let address = value.get_address(network, address_type);
1661 println!(
1662 "{} {} {} {} {} {}",
1663 key,
1664 address,
1665 get_public_key_hash_from_address(&address),
1666 get_public_key_hash_from_public_key(&public_key_hex),
1667 public_key_hex,
1668 value.get_wif(network, should_compress)
1669 )
1670 }
1671 }
1672}
1673pub fn generate_bip84_hd_wallet_from_mnemonic_words(
1674 mnemonic_words: Vec<String>,
1675 password: Option<String>,
1676 coin_type: i32,
1677 account: i32,
1678 children_count: i32,
1679 should_harden: bool,
1680 network: Network,
1681) -> HDWalletBip84 {
1682 let bip = Bip::Bip84;
1683 let purpose = 84;
1684
1685 let passphrase = match password {
1686 Some(password) => password,
1687 None => "".to_string(),
1688 };
1689 let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1690 let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1691 let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1694 let master_keys_generated_from_bip32_root_key =
1696 get_master_keys_from_bip32_root_key(&bip32_root_key);
1697 let master_keys = master_keys_generated_from_seed;
1698 let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1701 let serialized_extended_master_keys = master_keys.serialize(network, bip);
1703 let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1704
1705 let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1706 let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1707 let derivation_path_external = format!("{}/0", account_derivation_path);
1708 let bip32_extended_keys_for_external = get_bip32_extended_keys_from_derivation_path(
1709 &derivation_path_external,
1710 &Keys::Master(master_keys.clone()),
1711 network,
1712 bip,
1713 );
1714 let bip32_extended_private_key_for_external = bip32_extended_keys_for_external.xpriv;
1715 let bip32_extended_public_key_for_external = bip32_extended_keys_for_external.xpub;
1716 let derivation_path_internal = format!("{}/1", account_derivation_path);
1718 let bip32_extended_keys_for_internal = get_bip32_extended_keys_from_derivation_path(
1719 &derivation_path_internal,
1720 &Keys::Master(master_keys.clone()),
1721 network,
1722 bip,
1723 );
1724 let bip32_extended_private_key_for_internal = bip32_extended_keys_for_internal.xpriv;
1725 let bip32_extended_public_key_for_internal = bip32_extended_keys_for_internal.xpub;
1726
1727 let should_include_change_addresses = true;
1728 let found_children = get_bip84_derived_addresses(
1729 coin_type,
1730 account,
1731 should_include_change_addresses,
1732 &master_keys,
1733 children_count,
1734 should_harden,
1735 );
1736 let bip84_derivation_path_info =
1737 get_bip84_derivation_path_info(coin_type, account, &master_keys.clone(), network);
1738
1739 HDWalletBip84 {
1740 network,
1741 bip39_seed,
1742 master_keys,
1743 bip32_root_key,
1744 bip32_root_pub_key,
1745 master_fingerprint,
1746 purpose,
1747 coin_type,
1748 account,
1749 account_derivation_path,
1751 account_extended_private_key: bip84_derivation_path_info.account_extended_private_key,
1752 account_extended_public_key: bip84_derivation_path_info.account_extended_public_key,
1753 derivation_path_external,
1754 bip32_extended_private_key_for_external,
1755 bip32_extended_public_key_for_external,
1756 derivation_path_internal,
1757 bip32_extended_private_key_for_internal,
1758 bip32_extended_public_key_for_internal,
1759 derived_addresses: found_children,
1760 }
1761}
1762#[derive(Debug)]
1763pub struct HDWalletBip86 {
1764 pub network: Network,
1765 pub bip39_seed: String,
1766 pub master_keys: MasterKeys,
1767 pub bip32_root_key: String,
1768 pub bip32_root_pub_key: String,
1769 pub master_fingerprint: String,
1770 pub purpose: i32,
1771 pub coin_type: i32,
1772 pub account: i32,
1773 pub account_derivation_path: String,
1775 pub account_extended_private_key: String,
1776 pub account_extended_public_key: String,
1777 pub derivation_path_external: String,
1778 pub bip32_extended_private_key_for_external: String,
1779 pub bip32_extended_public_key_for_external: String,
1780 pub derivation_path_internal: String,
1781 pub bip32_extended_private_key_for_internal: String,
1782 pub bip32_extended_public_key_for_internal: String,
1783 pub derived_addresses: DerivedAdresses,
1784}
1785impl HDWalletBip86 {
1786 pub fn pretty_print_derived_addressed(&self, network: Network) -> () {
1787 let address_type = AddressType::P2TR;
1788 for (key, value) in self.derived_addresses.internal.clone() {
1789 let should_compress = true;
1790 let public_key_hex = match &value {
1791 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1792 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1793 };
1794 let address = value.get_address(network, address_type);
1795 println!(
1796 "{} {} {} {} {}",
1797 key,
1798 address,
1799 get_public_key_hash_from_public_key(&public_key_hex),
1801 public_key_hex,
1802 value.get_wif(network, should_compress)
1803 )
1804 }
1805 for (key, value) in self.derived_addresses.external.clone() {
1806 let should_compress = true;
1807 let public_key_hex = match &value {
1808 Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1809 Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1810 };
1811 let address = value.get_address(network, address_type);
1812 println!(
1813 "{} {} {} {} {}",
1814 key,
1815 address,
1816 get_public_key_hash_from_public_key(&public_key_hex),
1818 public_key_hex,
1819 value.get_wif(network, should_compress)
1820 )
1821 }
1822 }
1823}
1824pub fn generate_bip86_hd_wallet_from_mnemonic_words(
1825 mnemonic_words: Vec<String>,
1826 password: Option<String>,
1827 coin_type: i32,
1828 account: i32,
1829 children_count: i32,
1830 should_harden: bool,
1831 network: Network,
1832) -> HDWalletBip86 {
1833 let bip = Bip::Bip86;
1834 let purpose = 86;
1835
1836 let passphrase = match password {
1837 Some(password) => password,
1838 None => "".to_string(),
1839 };
1840 let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1841 let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1842 let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1845 let master_keys_generated_from_bip32_root_key =
1847 get_master_keys_from_bip32_root_key(&bip32_root_key);
1848 let master_keys = master_keys_generated_from_seed;
1849 let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1852 let serialized_extended_master_keys = master_keys.serialize(network, bip);
1854 let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1855
1856 let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1857 let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1858 let derivation_path_external = format!("{}/0", account_derivation_path);
1859 let bip32_extended_keys_for_external = get_bip32_extended_keys_from_derivation_path(
1860 &derivation_path_external,
1861 &Keys::Master(master_keys.clone()),
1862 network,
1863 bip,
1864 );
1865 let bip32_extended_private_key_for_external = bip32_extended_keys_for_external.xpriv;
1866 let bip32_extended_public_key_for_external = bip32_extended_keys_for_external.xpub;
1867 let derivation_path_internal = format!("{}/1", account_derivation_path);
1869 let bip32_extended_keys_for_internal = get_bip32_extended_keys_from_derivation_path(
1870 &derivation_path_internal,
1871 &Keys::Master(master_keys.clone()),
1872 network,
1873 bip,
1874 );
1875 let bip32_extended_private_key_for_internal = bip32_extended_keys_for_internal.xpriv;
1876 let bip32_extended_public_key_for_internal = bip32_extended_keys_for_internal.xpub;
1877
1878 let should_include_change_addresses = true;
1879 let found_children = get_bip86_derived_addresses(
1880 coin_type,
1881 account,
1882 should_include_change_addresses,
1883 &master_keys,
1884 children_count,
1885 should_harden,
1886 );
1887 let bip86_derivation_path_info =
1888 get_bip86_derivation_path_info(coin_type, account, &master_keys.clone(), network);
1889
1890 HDWalletBip86 {
1891 network,
1892 bip39_seed,
1893 master_keys,
1894 bip32_root_key,
1895 bip32_root_pub_key,
1896 master_fingerprint,
1897 purpose,
1898 coin_type,
1899 account,
1900 account_derivation_path,
1902 account_extended_private_key: bip86_derivation_path_info.account_extended_private_key,
1903 account_extended_public_key: bip86_derivation_path_info.account_extended_public_key,
1904 derivation_path_external,
1905 bip32_extended_private_key_for_external,
1906 bip32_extended_public_key_for_external,
1907 derivation_path_internal,
1908 bip32_extended_private_key_for_internal,
1909 bip32_extended_public_key_for_internal,
1910 derived_addresses: found_children,
1911 }
1912}
1913pub fn generate_bip141_hd_wallet_from_mnemonic_words() {
1914 todo!("Need to implement: https://iancoleman.io/bip39/");
1915}