@@ -313,8 +313,7 @@ impl PublicKey {
313
313
}
314
314
}
315
315
316
- /// Construct a `PublicKey` from a hex representation of a raw or ASN.1 encoded
317
- /// key.
316
+ /// Construct a `PublicKey` from a hex representation of a raw or ASN.1 encoded key.
318
317
impl FromStr for PublicKey {
319
318
type Err = Error ;
320
319
@@ -468,7 +467,7 @@ impl SecretKey {
468
467
///
469
468
/// Mnemonics generated by the Android and iOS wallets will work
470
469
///
471
- /// Returned key will support deriving child keys with `.derive_child( )`
470
+ /// Returned key will support deriving child keys with `.derive_child_key(index )`
472
471
pub fn from_mnemonic_with_passphrase ( mnemonic : & str , passphrase : & str ) -> Result < Self , Error > {
473
472
let mnemonic = Mnemonic :: from_phrase ( mnemonic, Language :: English ) ?;
474
473
@@ -495,6 +494,22 @@ impl SecretKey {
495
494
Ok ( secret_key)
496
495
}
497
496
497
+ /// Derive a new private key at the given wallet index.
498
+ ///
499
+ /// Currently fails if the key was not generated with `generate_mnemonic` or `generated_mnemonic_with_passphrase`
500
+ /// or reconstructed with `from_mnemonic` or `from_mnemonic_with_passphrase`
501
+ pub fn derive_child_key ( & self , index : u32 ) -> Result < Self , Error > {
502
+ let chain_code = self . chain_code
503
+ . map_or ( Err ( err_msg ( "this Ed25519 private key does not support key derivation" ) ) , |cc| { Ok ( cc) } ) ?;
504
+
505
+ let ( key_bytes, chain_code) = Self :: derive_child_key_bytes ( self . as_bytes ( ) , & chain_code, & index) ?;
506
+
507
+ Ok ( SecretKey {
508
+ value : ed25519_dalek:: SecretKey :: from_bytes ( & key_bytes) ?,
509
+ chain_code : Some ( chain_code)
510
+ } )
511
+ }
512
+
498
513
/// Format a `SecretKey` as a vec of bytes in ASN.1 format.
499
514
pub fn to_encoded_bytes ( & self ) -> Vec < u8 > {
500
515
der_encode ( & PrivateKeyInfo {
@@ -532,7 +547,7 @@ impl SecretKey {
532
547
533
548
input[ 0 ] = 0u8 ;
534
549
input[ 1 ..33 ] . copy_from_slice ( parent_key) ;
535
- input[ 34 ..37 ] . copy_from_slice ( & index. to_be_bytes ( ) ) ;
550
+ input[ 33 ..37 ] . copy_from_slice ( & index. to_be_bytes ( ) ) ;
536
551
537
552
input[ 33 ] = input[ 33 ] | 128u8 ;
538
553
@@ -767,6 +782,7 @@ mod tests {
767
782
Ok ( ( ) )
768
783
}
769
784
785
+
770
786
#[ test]
771
787
fn test_reconstruct ( ) -> Result < ( ) , Error > {
772
788
let ( secret1, mnemonic) = SecretKey :: generate_mnemonic ( ) ;
@@ -776,4 +792,16 @@ mod tests {
776
792
777
793
Ok ( ( ) )
778
794
}
795
+
796
+ #[ test]
797
+ fn test_reconstruct_with_passphrase ( ) -> Result < ( ) , Error > {
798
+ let passphrase = "HelloHedera!" ;
799
+
800
+ let ( secret1, mnemonic) = SecretKey :: generate_mnemonic_with_passphrase ( passphrase) ;
801
+ let secret2 = SecretKey :: from_mnemonic_with_passphrase ( & mnemonic, passphrase) ?;
802
+
803
+ assert_eq ! ( secret1. as_bytes( ) , secret2. as_bytes( ) ) ;
804
+
805
+ Ok ( ( ) )
806
+ }
779
807
}
0 commit comments