@@ -235,22 +235,19 @@ static bool has_invalid_path_characters(const char* str) {
235235 return false;
236236}
237237
238- int bip32_derive (bip32_key * target , const char * source , const char * path ) {
238+ int bip32_derive_from_str (bip32_key * target , const char * source , const char * path ) {
239239 if (!target || !source || !path || strncmp (path , "m" , 1 ) != 0 ) {
240240 return 0 ;
241241 }
242242 if (strlen (source ) < 1 ) {
243243 return 0 ;
244244 }
245- if (has_invalid_path_characters (path )) {
246- return 0 ;
247- }
248245 bip32_key basekey ;
249246 size_t source_len = strlen (source );
250-
251- if (strncmp (source , "xprv" , 4 ) == 0 ||
247+
248+ if (strncmp (source , "xprv" , 4 ) == 0 ||
252249 strncmp (source , "tprv" , 4 ) == 0 ||
253- strncmp (source , "xpub" , 4 ) == 0 ||
250+ strncmp (source , "xpub" , 4 ) == 0 ||
254251 strncmp (source , "tpub" , 4 ) == 0 ) {
255252 if (!bip32_deserialize (& basekey , source , strlen (source ))) {
256253 return 0 ;
@@ -269,36 +266,57 @@ int bip32_derive(bip32_key *target, const char* source, const char* path) {
269266 } else {
270267 return 0 ;
271268 }
272-
269+
270+ if (bip32_derive (& basekey , path )) {
271+ memcpy (target , & basekey , sizeof (bip32_key ));
272+ return 1 ;
273+ }
274+ return 0 ;
275+ }
276+
277+ int bip32_derive_from_seed (bip32_key * target , const unsigned char * seed , size_t seed_len , const char * path ) {
278+ if (!bip32_from_seed (target , seed , seed_len )) {
279+ return 0 ;
280+ }
281+ if (bip32_derive (target , path )) {
282+ return 1 ;
283+ }
284+ return 0 ;
285+ }
286+
287+ // Do an in-place derivation on `key`.
288+ int bip32_derive (bip32_key * key , const char * path ) {
289+ if (!path || strncmp (path , "m" , 1 ) != 0 || has_invalid_path_characters (path )) {
290+ return 0 ;
291+ }
292+
273293 char * p = (char * )strchr (path , '/' );
274294 if (!p ) {
275- memcpy (target , & basekey , sizeof (bip32_key ));
276295 return 1 ;
277296 }
278-
297+
279298 while (p && * p ) {
280299 char * end ;
281300 uint32_t path_index = strtoul (p + 1 , & end , 10 );
282-
301+
283302 if (errno == ERANGE || path_index > INT_MAX || end == p + 1 ) {
284303 // Overflow detected.
285304 return 0 ;
286305 }
287-
306+
288307 if (* end == '\'' || * end == 'h' || * end == 'H' || * end == 'p' || * end == 'P' ) {
289308 path_index |= HARDENED_INDEX ;
290309 end ++ ;
291310 }
292311
293312 bip32_key tmp ;
294- memcpy (& tmp , & basekey , sizeof (bip32_key ));
295- if (bip32_index_derive (& basekey , & tmp , path_index ) != 1 ) {
313+ memcpy (& tmp , key , sizeof (bip32_key ));
314+ if (bip32_index_derive (key , & tmp , path_index ) != 1 ) {
296315 return 0 ;
297316 }
298317 p = strchr (end , '/' );
299318 }
300-
301- memcpy (target , & basekey , sizeof (bip32_key ));
319+
302320 return 1 ;
303321}
304322
@@ -308,37 +326,37 @@ int bip32_derive(bip32_key *target, const char* source, const char* path) {
308326int bip32_serialize (const bip32_key * key , char * str , size_t str_len ) {
309327 unsigned char data [SER_PLUS_CHECKSUM_SIZE ];
310328 uint32_t version ;
311-
329+
312330 // Set version bytes based on network and key type
313331 if (key -> is_private ) {
314332 version = key -> is_testnet ? VERSION_TPRIV : VERSION_XPRIV ;
315333 } else {
316334 version = key -> is_testnet ? VERSION_TPUB : VERSION_XPUB ;
317335 }
318336 version = to_big_endian (version );
319-
337+
320338 memcpy (data , & version , sizeof (version ));
321-
339+
322340 data [4 ] = key -> depth ;
323-
341+
324342 // Write parent fingerprint
325343 uint32_t parfinger = key -> parent_fingerprint ;
326344 memcpy (data + 5 , & parfinger , sizeof (parfinger ));
327345
328346 // Write child number in big-endian
329347 uint32_t childnum = to_big_endian (key -> child_number );
330348 memcpy (data + 9 , & childnum , sizeof (childnum ));
331-
349+
332350 // Copy chain code
333351 memcpy (data + 13 , key -> chain_code , 32 );
334-
352+
335353 if (key -> is_private ) {
336354 data [45 ] = 0 ;
337355 memcpy (data + 46 , key -> key .privkey , 32 );
338356 } else {
339357 memcpy (data + 45 , key -> key .pubkey , 33 );
340358 }
341-
359+
342360 // Add checksum and base58 encode
343361 uint8_t hash [32 ];
344362 bip32_sha256_double (hash , data , 78 );
@@ -374,7 +392,7 @@ int bip32_deserialize(bip32_key *key, const char *str, const size_t str_len) {
374392 key -> is_private = 0 ;
375393 break ;
376394 case VERSION_XPRIV :
377- key -> is_testnet = 0 ;
395+ key -> is_testnet = 0 ;
378396 key -> is_private = 1 ;
379397 break ;
380398 case VERSION_TPRIV :
@@ -454,10 +472,10 @@ void bip32_sha256_double(uint8_t *hash, const uint8_t *data, size_t len) {
454472}
455473
456474void bip32_hmac_sha512 (
457- unsigned char * hmac_out ,
458- const unsigned char * key ,
459- size_t key_len ,
460- const unsigned char * msg ,
475+ unsigned char * hmac_out ,
476+ const unsigned char * key ,
477+ size_t key_len ,
478+ const unsigned char * msg ,
461479 size_t msg_len
462480) {
463481 assert (sodium_init () >= 0 );
0 commit comments