keyfork-derive-util: fixup request API, publicity of ExtendedPrivateKey
This commit is contained in:
parent
8510e382d2
commit
72666011a4
|
@ -29,6 +29,10 @@ pub enum Error {
|
|||
/// The algorithm used mandates hardened derivation only.
|
||||
#[error("The algorithm used mandates hardened derivation only")]
|
||||
HardenedDerivationRequired,
|
||||
|
||||
/// The given slice was of an inappropriate size to create a Private Key.
|
||||
#[error("The given slice was of an inappropriate size to create a Private Key")]
|
||||
InvalidSliceError(#[from] std::array::TryFromSliceError),
|
||||
}
|
||||
|
||||
type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
@ -41,9 +45,9 @@ type HmacSha512 = Hmac<Sha512>;
|
|||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct ExtendedPrivateKey<K: PrivateKey + Clone> {
|
||||
/// The internal private key data.
|
||||
pub private_key: K,
|
||||
private_key: K,
|
||||
depth: u8,
|
||||
pub(crate) chain_code: ChainCode,
|
||||
chain_code: ChainCode,
|
||||
}
|
||||
|
||||
impl<K: PrivateKey + Clone> std::fmt::Debug for ExtendedPrivateKey<K> {
|
||||
|
@ -88,18 +92,42 @@ where
|
|||
.into_bytes();
|
||||
let (private_key, chain_code) = hash.split_at(KEY_SIZE / 8);
|
||||
|
||||
Self::new_from_parts(
|
||||
private_key,
|
||||
0,
|
||||
// Checked: chain_code is always the same length, hash is static size
|
||||
chain_code.try_into().expect("Invalid chain code length"),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_from_parts(seed: &[u8], depth: u8, chain_code: [u8; 32]) -> Result<Self> {
|
||||
Ok(Self {
|
||||
private_key: K::from_bytes(private_key.try_into().expect("Invalid key length")),
|
||||
depth: 0,
|
||||
chain_code: chain_code.try_into().expect("Invalid chain code length"),
|
||||
private_key: K::from_bytes(seed.try_into()?),
|
||||
depth,
|
||||
chain_code,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a reference to the [`PrivateKey`].
|
||||
pub fn private_key(&self) -> &K {
|
||||
&self.private_key
|
||||
}
|
||||
|
||||
/// Return a public key for the current [`PrivateKey`].
|
||||
pub fn public_key(&self) -> K::PublicKey {
|
||||
self.private_key.public_key()
|
||||
}
|
||||
|
||||
/// Returns the current depth.
|
||||
pub fn depth(&self) -> u8 {
|
||||
self.depth
|
||||
}
|
||||
|
||||
/// Returns a copy of the current chain code.
|
||||
pub fn chain_code(&self) -> [u8; 32] {
|
||||
self.chain_code
|
||||
}
|
||||
|
||||
/// Derive a child using the given [`DerivationPath`].
|
||||
///
|
||||
/// # Errors
|
||||
|
|
|
@ -34,6 +34,14 @@ impl DerivationPath {
|
|||
pub fn iter(&self) -> impl Iterator<Item = &DerivationIndex> {
|
||||
self.path.iter()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.path.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.path.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for DerivationPath {
|
||||
|
|
|
@ -28,19 +28,19 @@ impl DerivationAlgorithm {
|
|||
Self::Ed25519 => {
|
||||
let key = ExtendedPrivateKey::<ed25519_dalek::SigningKey>::new(seed)?;
|
||||
let derived_key = key.derive_path(path)?;
|
||||
Ok(DerivationResponse {
|
||||
algorithm: self.clone(),
|
||||
data: PrivateKey::to_bytes(&derived_key.private_key).to_vec(),
|
||||
})
|
||||
Ok(DerivationResponse::with_algo_and_xprv(
|
||||
self.clone(),
|
||||
&derived_key,
|
||||
))
|
||||
}
|
||||
#[cfg(feature = "secp256k1")]
|
||||
Self::Secp256k1 => {
|
||||
let key = ExtendedPrivateKey::<k256::SecretKey>::new(seed)?;
|
||||
let derived_key = key.derive_path(path)?;
|
||||
Ok(DerivationResponse {
|
||||
algorithm: self.clone(),
|
||||
data: PrivateKey::to_bytes(&derived_key.private_key).to_vec(),
|
||||
})
|
||||
Ok(DerivationResponse::with_algo_and_xprv(
|
||||
self.clone(),
|
||||
&derived_key,
|
||||
))
|
||||
}
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => Err(DerivationError::Algorithm),
|
||||
|
@ -59,6 +59,10 @@ impl DerivationRequest {
|
|||
Self { algorithm, path }
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &DerivationPath {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn derive_with_mnemonic(&self, mnemonic: &Mnemonic) -> Result<DerivationResponse> {
|
||||
self.derive_with_master_seed(mnemonic.seed())
|
||||
}
|
||||
|
@ -72,4 +76,20 @@ impl DerivationRequest {
|
|||
pub struct DerivationResponse {
|
||||
pub algorithm: DerivationAlgorithm,
|
||||
pub data: Vec<u8>,
|
||||
pub chain_code: [u8; 32],
|
||||
pub depth: u8,
|
||||
}
|
||||
|
||||
impl DerivationResponse {
|
||||
pub fn with_algo_and_xprv<T: PrivateKey + Clone>(
|
||||
algorithm: DerivationAlgorithm,
|
||||
xprv: &ExtendedPrivateKey<T>,
|
||||
) -> Self {
|
||||
Self {
|
||||
algorithm,
|
||||
data: PrivateKey::to_bytes(xprv.private_key()).to_vec(),
|
||||
chain_code: xprv.chain_code(),
|
||||
depth: xprv.depth(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,8 +62,8 @@ fn secp256k1() {
|
|||
for (seed, chain, chain_code, private_key, public_key) in tests {
|
||||
let xkey = ExtendedPrivateKey::<SecretKey>::new(seed).unwrap();
|
||||
let derived_key = xkey.derive_path(&chain).unwrap();
|
||||
assert_eq!(derived_key.chain_code, chain_code);
|
||||
assert_eq!(derived_key.private_key.to_bytes().as_slice(), private_key);
|
||||
assert_eq!(derived_key.chain_code(), chain_code);
|
||||
assert_eq!(derived_key.private_key().to_bytes().as_slice(), private_key);
|
||||
assert_eq!(derived_key.public_key().to_bytes(), public_key);
|
||||
let request = DerivationRequest::new(DerivationAlgorithm::Secp256k1, chain);
|
||||
let response = request.derive_with_master_seed(seed.to_vec()).unwrap();
|
||||
|
@ -103,8 +103,8 @@ fn ed25519() {
|
|||
for (seed, chain, chain_code, private_key, public_key) in tests {
|
||||
let xkey = ExtendedPrivateKey::<SigningKey>::new(seed).unwrap();
|
||||
let derived_key = xkey.derive_path(&chain).unwrap();
|
||||
assert_eq!(derived_key.chain_code, chain_code);
|
||||
assert_eq!(PrivateKey::to_bytes(&derived_key.private_key), private_key);
|
||||
assert_eq!(derived_key.chain_code(), chain_code);
|
||||
assert_eq!(PrivateKey::to_bytes(derived_key.private_key()), private_key);
|
||||
assert_eq!(PublicKey::to_bytes(&derived_key.public_key()), public_key);
|
||||
let request = DerivationRequest::new(DerivationAlgorithm::Ed25519, chain);
|
||||
let response = request.derive_with_master_seed(seed.to_vec()).unwrap();
|
||||
|
|
Loading…
Reference in New Issue