Skip to content
This repository was archived by the owner on May 8, 2021. It is now read-only.

Commit 7a59589

Browse files
committed
add derive child key for Private Keys
1 parent fc8b848 commit 7a59589

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

src/crypto.rs

+32-4
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,7 @@ impl PublicKey {
313313
}
314314
}
315315

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.
318317
impl FromStr for PublicKey {
319318
type Err = Error;
320319

@@ -468,7 +467,7 @@ impl SecretKey {
468467
///
469468
/// Mnemonics generated by the Android and iOS wallets will work
470469
///
471-
/// Returned key will support deriving child keys with `.derive_child()`
470+
/// Returned key will support deriving child keys with `.derive_child_key(index)`
472471
pub fn from_mnemonic_with_passphrase(mnemonic: &str, passphrase: &str) -> Result<Self, Error> {
473472
let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English)?;
474473

@@ -495,6 +494,22 @@ impl SecretKey {
495494
Ok(secret_key)
496495
}
497496

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+
498513
/// Format a `SecretKey` as a vec of bytes in ASN.1 format.
499514
pub fn to_encoded_bytes(&self) -> Vec<u8> {
500515
der_encode(&PrivateKeyInfo {
@@ -532,7 +547,7 @@ impl SecretKey {
532547

533548
input[0] = 0u8;
534549
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());
536551

537552
input[33] = input[33] | 128u8;
538553

@@ -767,6 +782,7 @@ mod tests {
767782
Ok(())
768783
}
769784

785+
770786
#[test]
771787
fn test_reconstruct() -> Result<(), Error> {
772788
let (secret1, mnemonic) = SecretKey::generate_mnemonic();
@@ -776,4 +792,16 @@ mod tests {
776792

777793
Ok(())
778794
}
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+
}
779807
}

0 commit comments

Comments
 (0)