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

Commit

Permalink
add derive child key for Private Keys
Browse files Browse the repository at this point in the history
  • Loading branch information
QuestofIranon committed Sep 20, 2019
1 parent fc8b848 commit 7a59589
Showing 1 changed file with 32 additions and 4 deletions.
36 changes: 32 additions & 4 deletions src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,7 @@ impl PublicKey {
}
}

/// Construct a `PublicKey` from a hex representation of a raw or ASN.1 encoded
/// key.
/// Construct a `PublicKey` from a hex representation of a raw or ASN.1 encoded key.
impl FromStr for PublicKey {
type Err = Error;

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

Expand All @@ -495,6 +494,22 @@ impl SecretKey {
Ok(secret_key)
}

/// Derive a new private key at the given wallet index.
///
/// Currently fails if the key was not generated with `generate_mnemonic` or `generated_mnemonic_with_passphrase`
/// or reconstructed with `from_mnemonic` or `from_mnemonic_with_passphrase`
pub fn derive_child_key(&self, index: u32) -> Result<Self, Error> {
let chain_code = self.chain_code
.map_or(Err(err_msg("this Ed25519 private key does not support key derivation")), |cc| {Ok(cc)})?;

let (key_bytes, chain_code) = Self::derive_child_key_bytes(self.as_bytes(), &chain_code, &index)?;

Ok(SecretKey{
value: ed25519_dalek::SecretKey::from_bytes(&key_bytes)?,
chain_code: Some(chain_code)
})
}

/// Format a `SecretKey` as a vec of bytes in ASN.1 format.
pub fn to_encoded_bytes(&self) -> Vec<u8> {
der_encode(&PrivateKeyInfo {
Expand Down Expand Up @@ -532,7 +547,7 @@ impl SecretKey {

input[0] = 0u8;
input[1..33].copy_from_slice(parent_key);
input[34..37].copy_from_slice(&index.to_be_bytes());
input[33..37].copy_from_slice(&index.to_be_bytes());

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

Expand Down Expand Up @@ -767,6 +782,7 @@ mod tests {
Ok(())
}


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

Ok(())
}

#[test]
fn test_reconstruct_with_passphrase() -> Result<(), Error> {
let passphrase = "HelloHedera!";

let (secret1, mnemonic) = SecretKey::generate_mnemonic_with_passphrase(passphrase);
let secret2 = SecretKey::from_mnemonic_with_passphrase(&mnemonic, passphrase)?;

assert_eq!(secret1.as_bytes(), secret2.as_bytes());

Ok(())
}
}

0 comments on commit 7a59589

Please sign in to comment.