@@ -32,19 +32,30 @@ pub fn get_word(idx: u16) -> Result<zeroize::Zeroizing<String>, ()> {
3232/// The passphrase must be not NULL and null-terminated.
3333///
3434/// `seed` must be 16, 24 or 32 bytes long.
35- /// `out` must be exactly 64 bytes long.
35+ /// `bip39_seed_out` must be exactly 64 bytes long.
36+ /// `root_fingerprint_out` must be exactly 4 bytes long.
3637#[ unsafe( no_mangle) ]
3738pub unsafe extern "C" fn rust_derive_bip39_seed (
3839 seed : util:: bytes:: Bytes ,
3940 passphrase : * const core:: ffi:: c_char ,
40- mut out : util:: bytes:: BytesMut ,
41+ mut bip39_seed_out : util:: bytes:: BytesMut ,
42+ mut root_fingerprint_out : util:: bytes:: BytesMut ,
4143) {
4244 let mnemonic =
4345 bip39:: Mnemonic :: from_entropy_in ( bip39:: Language :: English , seed. as_ref ( ) ) . unwrap ( ) ;
4446 let passphrase = unsafe { core:: ffi:: CStr :: from_ptr ( passphrase) } ;
45- let bip39_seed =
47+ let bip39_seed: zeroize :: Zeroizing < [ u8 ; 64 ] > =
4648 zeroize:: Zeroizing :: new ( mnemonic. to_seed_normalized ( passphrase. to_str ( ) . unwrap ( ) ) ) ;
47- out. as_mut ( ) . clone_from_slice ( & bip39_seed[ ..] ) ;
49+ bip39_seed_out. as_mut ( ) . clone_from_slice ( & bip39_seed[ ..] ) ;
50+
51+ let root_fingerprint: [ u8 ; 4 ] =
52+ bitcoin:: bip32:: Xpriv :: new_master ( bitcoin:: NetworkKind :: Main , bip39_seed. as_ref ( ) )
53+ . unwrap ( )
54+ . fingerprint ( crate :: secp256k1:: SECP256K1 )
55+ . to_bytes ( ) ;
56+ root_fingerprint_out
57+ . as_mut ( )
58+ . clone_from_slice ( & root_fingerprint) ;
4859}
4960
5061#[ unsafe( no_mangle) ]
@@ -73,6 +84,7 @@ mod tests {
7384 seed : & ' static str ,
7485 passphrase : & ' static core:: ffi:: CStr ,
7586 expected_bip39_seed : & ' static str ,
87+ expected_root_fingerprint : & ' static str ,
7688 }
7789
7890 let tests = & [
@@ -81,47 +93,62 @@ mod tests {
8193 seed : "fb5cf00d5ea61059fa066e25a6be9544" ,
8294 passphrase : c"" ,
8395 expected_bip39_seed : "f4577e463be595868060e5a763328153155b4167cd284998c8c6096d044742372020f5b052d0c41c1c5e6a6a7da2cb8a367aaaa074fab7773e8d5b2f684257ed" ,
96+ expected_root_fingerprint : "0b2fa4e5" ,
8497 } ,
8598 Test {
8699 seed : "fb5cf00d5ea61059fa066e25a6be9544" ,
87100 passphrase : c"password" ,
88101 expected_bip39_seed : "5922fb7630bc7cb871af102f733b6bdb8f05945147cd4646a89056fde0bdad5c3a4ff5be3f9e7af535f570e7053b5b22472555b331bc89cb797c306f7eb6a5a1" ,
102+ expected_root_fingerprint : "c4062d44" ,
89103 } ,
90104 // 24 byte seed
91105 Test {
92106 seed : "23705a91b177b49822f28b3f1a60072d113fcaff4f250191" ,
93107 passphrase : c"" ,
94108 expected_bip39_seed : "4a2a016a6d90eb3a79b7931ca0a172df5c5bfee3e5b47f0fd84bc0791ea3bbc9476c3d5de71cdb12c37e93c2aa3d5c303257f1992aed400fc5bbfc7da787bfa7" ,
109+ expected_root_fingerprint : "62fd19e0" ,
95110 } ,
96111 Test {
97112 seed : "23705a91b177b49822f28b3f1a60072d113fcaff4f250191" ,
98113 passphrase : c"password" ,
99114 expected_bip39_seed : "bc317ee0f88870254be32274d63ec2b0e962bf09f3ca04287912bfc843f2fab7c556f8657cadc924f99a217b0daa91898303a8414102031a125c50023e45a80b" ,
115+ expected_root_fingerprint : "c745266d" ,
100116 } ,
101117 // 32 byte seed
102118 Test {
103119 seed : "bd83a008b3b78c8cc56c678d1b7bfc651cc5be8242f44b5c0db96a34ee297833" ,
104120 passphrase : c"" ,
105121 expected_bip39_seed : "63f844e2c61ecfb20f9100de381a7a9ec875b085f5ac7735a2ba4d615a0f4147b87be402f65651969130683deeef752760c09e291604fe4b89d61ffee2630be8" ,
122+ expected_root_fingerprint : "93ba3a7b" ,
106123 } ,
107124 Test {
108125 seed : "bd83a008b3b78c8cc56c678d1b7bfc651cc5be8242f44b5c0db96a34ee297833" ,
109126 passphrase : c"password" ,
110127 expected_bip39_seed : "42e90dacd61f3373542d212f0fb9c291dcea84a6d85034272372dde7188638a98527280d65e41599f30d3434d8ee3d4747dbb84801ff1a851d2306c7d1648374" ,
128+ expected_root_fingerprint : "b95c9318" ,
111129 } ,
112130 ] ;
113131
114132 for test in tests {
115133 let seed = hex:: decode ( test. seed ) . unwrap ( ) ;
116134 let mut bip39_seed = [ 0u8 ; 64 ] ;
135+ let mut root_fingerprint = [ 0u8 ; 4 ] ;
117136 unsafe {
118137 rust_derive_bip39_seed (
119138 util:: bytes:: rust_util_bytes ( seed. as_ptr ( ) , seed. len ( ) ) ,
120139 test. passphrase . as_ptr ( ) ,
121140 util:: bytes:: rust_util_bytes_mut ( bip39_seed. as_mut_ptr ( ) , bip39_seed. len ( ) ) ,
141+ util:: bytes:: rust_util_bytes_mut (
142+ root_fingerprint. as_mut_ptr ( ) ,
143+ root_fingerprint. len ( ) ,
144+ ) ,
122145 ) ;
123146 }
124147 assert_eq ! ( hex:: encode( bip39_seed) . as_str( ) , test. expected_bip39_seed) ;
148+ assert_eq ! (
149+ hex:: encode( root_fingerprint) . as_str( ) ,
150+ test. expected_root_fingerprint
151+ ) ;
125152 }
126153 }
127154
0 commit comments