@@ -32,19 +32,30 @@ pub fn get_word(idx: u16) -> Result<zeroize::Zeroizing<String>, ()> {
32
32
/// The passphrase must be not NULL and null-terminated.
33
33
///
34
34
/// `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.
36
37
#[ unsafe( no_mangle) ]
37
38
pub unsafe extern "C" fn rust_derive_bip39_seed (
38
39
seed : util:: bytes:: Bytes ,
39
40
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 ,
41
43
) {
42
44
let mnemonic =
43
45
bip39:: Mnemonic :: from_entropy_in ( bip39:: Language :: English , seed. as_ref ( ) ) . unwrap ( ) ;
44
46
let passphrase = unsafe { core:: ffi:: CStr :: from_ptr ( passphrase) } ;
45
- let bip39_seed =
47
+ let bip39_seed: zeroize :: Zeroizing < [ u8 ; 64 ] > =
46
48
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) ;
48
59
}
49
60
50
61
#[ unsafe( no_mangle) ]
@@ -73,6 +84,7 @@ mod tests {
73
84
seed : & ' static str ,
74
85
passphrase : & ' static core:: ffi:: CStr ,
75
86
expected_bip39_seed : & ' static str ,
87
+ expected_root_fingerprint : & ' static str ,
76
88
}
77
89
78
90
let tests = & [
@@ -81,47 +93,62 @@ mod tests {
81
93
seed : "fb5cf00d5ea61059fa066e25a6be9544" ,
82
94
passphrase : c"" ,
83
95
expected_bip39_seed : "f4577e463be595868060e5a763328153155b4167cd284998c8c6096d044742372020f5b052d0c41c1c5e6a6a7da2cb8a367aaaa074fab7773e8d5b2f684257ed" ,
96
+ expected_root_fingerprint : "0b2fa4e5" ,
84
97
} ,
85
98
Test {
86
99
seed : "fb5cf00d5ea61059fa066e25a6be9544" ,
87
100
passphrase : c"password" ,
88
101
expected_bip39_seed : "5922fb7630bc7cb871af102f733b6bdb8f05945147cd4646a89056fde0bdad5c3a4ff5be3f9e7af535f570e7053b5b22472555b331bc89cb797c306f7eb6a5a1" ,
102
+ expected_root_fingerprint : "c4062d44" ,
89
103
} ,
90
104
// 24 byte seed
91
105
Test {
92
106
seed : "23705a91b177b49822f28b3f1a60072d113fcaff4f250191" ,
93
107
passphrase : c"" ,
94
108
expected_bip39_seed : "4a2a016a6d90eb3a79b7931ca0a172df5c5bfee3e5b47f0fd84bc0791ea3bbc9476c3d5de71cdb12c37e93c2aa3d5c303257f1992aed400fc5bbfc7da787bfa7" ,
109
+ expected_root_fingerprint : "62fd19e0" ,
95
110
} ,
96
111
Test {
97
112
seed : "23705a91b177b49822f28b3f1a60072d113fcaff4f250191" ,
98
113
passphrase : c"password" ,
99
114
expected_bip39_seed : "bc317ee0f88870254be32274d63ec2b0e962bf09f3ca04287912bfc843f2fab7c556f8657cadc924f99a217b0daa91898303a8414102031a125c50023e45a80b" ,
115
+ expected_root_fingerprint : "c745266d" ,
100
116
} ,
101
117
// 32 byte seed
102
118
Test {
103
119
seed : "bd83a008b3b78c8cc56c678d1b7bfc651cc5be8242f44b5c0db96a34ee297833" ,
104
120
passphrase : c"" ,
105
121
expected_bip39_seed : "63f844e2c61ecfb20f9100de381a7a9ec875b085f5ac7735a2ba4d615a0f4147b87be402f65651969130683deeef752760c09e291604fe4b89d61ffee2630be8" ,
122
+ expected_root_fingerprint : "93ba3a7b" ,
106
123
} ,
107
124
Test {
108
125
seed : "bd83a008b3b78c8cc56c678d1b7bfc651cc5be8242f44b5c0db96a34ee297833" ,
109
126
passphrase : c"password" ,
110
127
expected_bip39_seed : "42e90dacd61f3373542d212f0fb9c291dcea84a6d85034272372dde7188638a98527280d65e41599f30d3434d8ee3d4747dbb84801ff1a851d2306c7d1648374" ,
128
+ expected_root_fingerprint : "b95c9318" ,
111
129
} ,
112
130
] ;
113
131
114
132
for test in tests {
115
133
let seed = hex:: decode ( test. seed ) . unwrap ( ) ;
116
134
let mut bip39_seed = [ 0u8 ; 64 ] ;
135
+ let mut root_fingerprint = [ 0u8 ; 4 ] ;
117
136
unsafe {
118
137
rust_derive_bip39_seed (
119
138
util:: bytes:: rust_util_bytes ( seed. as_ptr ( ) , seed. len ( ) ) ,
120
139
test. passphrase . as_ptr ( ) ,
121
140
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
+ ) ,
122
145
) ;
123
146
}
124
147
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
+ ) ;
125
152
}
126
153
}
127
154
0 commit comments