Implement Bip32 for seed-phrase/passphrase signing (#16942)

* Add Keypair helpers for bip32 derivation

* Plumb bip32 for SignerSourceKind::Ask

* Support full-path querystring

* Use as_ref

* Add public wrappers for from_uri cases

* Support master root derivations (and fix too-deep print

* Add ask:// HD documentation

* Update ASK elsewhere in docs
This commit is contained in:
Tyera Eulberg
2021-05-03 19:58:56 -06:00
committed by GitHub
parent 6318705607
commit 694c674aa6
11 changed files with 471 additions and 65 deletions

View File

@@ -1,8 +1,9 @@
//! The `signature` module provides functionality for public, and private keys.
#![cfg(feature = "full")]
use crate::{pubkey::Pubkey, transaction::TransactionError};
use crate::{derivation_path::DerivationPath, pubkey::Pubkey, transaction::TransactionError};
use ed25519_dalek::Signer as DalekSigner;
use ed25519_dalek_bip32::Error as Bip32Error;
use generic_array::{typenum::U64, GenericArray};
use hmac::Hmac;
use itertools::Itertools;
@@ -396,10 +397,37 @@ pub fn keypair_from_seed(seed: &[u8]) -> Result<Keypair, Box<dyn error::Error>>
Ok(Keypair(dalek_keypair))
}
pub fn keypair_from_seed_phrase_and_passphrase(
/// Generates a Keypair using Bip32 Hierarchical Derivation if derivation-path is provided;
/// otherwise builds standard Keypair using the seed as SecretKey
pub fn keypair_from_seed_and_derivation_path(
seed: &[u8],
derivation_path: Option<DerivationPath>,
) -> Result<Keypair, Box<dyn error::Error>> {
if let Some(derivation_path) = derivation_path {
bip32_derived_keypair(seed, derivation_path).map_err(|err| err.to_string().into())
} else {
keypair_from_seed(seed)
}
}
/// Generates a Keypair using Bip32 Hierarchical Derivation
fn bip32_derived_keypair(
seed: &[u8],
derivation_path: DerivationPath,
) -> Result<Keypair, Bip32Error> {
let extended = ed25519_dalek_bip32::ExtendedSecretKey::from_seed(seed)
.and_then(|extended| extended.derive(&derivation_path))?;
let extended_public_key = extended.public_key();
Ok(Keypair(ed25519_dalek::Keypair {
secret: extended.secret_key,
public: extended_public_key,
}))
}
pub fn generate_seed_from_seed_phrase_and_passphrase(
seed_phrase: &str,
passphrase: &str,
) -> Result<Keypair, Box<dyn error::Error>> {
) -> Vec<u8> {
const PBKDF2_ROUNDS: u32 = 2048;
const PBKDF2_BYTES: usize = 64;
@@ -412,7 +440,17 @@ pub fn keypair_from_seed_phrase_and_passphrase(
PBKDF2_ROUNDS,
&mut seed,
);
keypair_from_seed(&seed[..])
seed
}
pub fn keypair_from_seed_phrase_and_passphrase(
seed_phrase: &str,
passphrase: &str,
) -> Result<Keypair, Box<dyn error::Error>> {
keypair_from_seed(&generate_seed_from_seed_phrase_and_passphrase(
seed_phrase,
passphrase,
))
}
#[cfg(test)]