keyforkd, keyfork-derive-util: add some tests, fix algo switcharound
This commit is contained in:
parent
c39d8343c7
commit
0d6753ef47
|
@ -453,6 +453,7 @@ name = "keyforkd"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"hex-literal",
|
||||
"keyfork-derive-util",
|
||||
"keyfork-frame",
|
||||
"keyfork-mnemonic-util",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{extended_key::private_key::Error as XPrvError, DerivationPath, ExtendedPrivateKey};
|
||||
use crate::{extended_key::private_key::Error as XPrvError, DerivationPath, ExtendedPrivateKey, PrivateKey};
|
||||
use keyfork_mnemonic_util::Mnemonic;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -24,20 +24,20 @@ impl DerivationAlgorithm {
|
|||
match self {
|
||||
#[cfg(feature = "ed25519")]
|
||||
Self::Ed25519 => {
|
||||
let key = ExtendedPrivateKey::<k256::SecretKey>::new(seed)?;
|
||||
let derived_key = key.derive_path(path)?;
|
||||
Ok(DerivationResponse {
|
||||
algorithm: self.clone(),
|
||||
data: derived_key.private_key.to_bytes().to_vec(),
|
||||
})
|
||||
}
|
||||
#[cfg(feature = "secp256k1")]
|
||||
Self::Secp256k1 => {
|
||||
let key = ExtendedPrivateKey::<ed25519_dalek::SigningKey>::new(seed)?;
|
||||
let derived_key = key.derive_path(path)?;
|
||||
Ok(DerivationResponse {
|
||||
algorithm: self.clone(),
|
||||
data: derived_key.private_key.to_bytes().to_vec(),
|
||||
data: PrivateKey::to_bytes(&derived_key.private_key).to_vec(),
|
||||
})
|
||||
}
|
||||
#[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(),
|
||||
})
|
||||
}
|
||||
#[allow(unreachable_patterns)]
|
||||
|
@ -68,6 +68,6 @@ impl DerivationRequest {
|
|||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct DerivationResponse {
|
||||
algorithm: DerivationAlgorithm,
|
||||
data: Vec<u8>,
|
||||
pub algorithm: DerivationAlgorithm,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::*;
|
||||
use crate::{request::*, *};
|
||||
use hex_literal::hex;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -65,6 +65,9 @@ fn secp256k1() {
|
|||
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();
|
||||
assert_eq!(response.data, private_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,30 +77,37 @@ fn ed25519() {
|
|||
use ed25519_dalek::SigningKey;
|
||||
|
||||
// seed, chain, chain code, private, public
|
||||
let tests = [(
|
||||
let tests = [
|
||||
(
|
||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||
DerivationPath::from_str("m").unwrap(),
|
||||
hex!("90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb"),
|
||||
hex!("2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7"),
|
||||
hex!("00a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed"),
|
||||
), (
|
||||
),
|
||||
(
|
||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||
DerivationPath::from_str("m/0'").unwrap(),
|
||||
hex!("8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69"),
|
||||
hex!("68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3"),
|
||||
hex!("008c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c"),
|
||||
), (
|
||||
),
|
||||
(
|
||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||
DerivationPath::from_str("m/0'/1'/2'/2'/1000000000'").unwrap(),
|
||||
hex!("68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230"),
|
||||
hex!("8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793"),
|
||||
hex!("003c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a"),
|
||||
)];
|
||||
),
|
||||
];
|
||||
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!(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();
|
||||
assert_eq!(response.data, private_key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,3 +28,6 @@ tower = { version = "0.4.13", features = ["tokio", "util"] }
|
|||
# Personally audited
|
||||
thiserror = "1.0.47"
|
||||
serde = { version = "1.0.186", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.4.1"
|
||||
|
|
|
@ -40,3 +40,50 @@ impl Service<DerivationRequest> for Keyforkd {
|
|||
Box::pin(async { req.derive_with_mnemonic(&mnemonic) })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use hex_literal::hex;
|
||||
use keyfork_derive_util::{request::*, DerivationPath};
|
||||
use keyfork_mnemonic_util::Wordlist;
|
||||
use std::str::FromStr;
|
||||
use tower::ServiceExt;
|
||||
|
||||
#[tokio::test]
|
||||
async fn properly_derives_data() {
|
||||
// Pulled from keyfork-derive-util's tests, which is more extensively tested.
|
||||
let tests = [
|
||||
(
|
||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||
DerivationPath::from_str("m").unwrap(),
|
||||
hex!("90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb"),
|
||||
hex!("2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7"),
|
||||
hex!("00a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed"),
|
||||
),
|
||||
(
|
||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||
DerivationPath::from_str("m/0'").unwrap(),
|
||||
hex!("8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69"),
|
||||
hex!("68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3"),
|
||||
hex!("008c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c"),
|
||||
),
|
||||
(
|
||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||
DerivationPath::from_str("m/0'/1'/2'/2'/1000000000'").unwrap(),
|
||||
hex!("68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230"),
|
||||
hex!("8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793"),
|
||||
hex!("003c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a"),
|
||||
),
|
||||
];
|
||||
let wordlist = Wordlist::default().arc();
|
||||
for (seed, path, _, private_key, _) in tests {
|
||||
let mnemonic = Mnemonic::from_entropy(&seed[..], wordlist.clone()).unwrap();
|
||||
assert_eq!(mnemonic.seed(), seed);
|
||||
let req = DerivationRequest::new(DerivationAlgorithm::Ed25519, path);
|
||||
let mut keyforkd = Keyforkd::new(mnemonic);
|
||||
let response = keyforkd.ready().await.unwrap().call(req).await.unwrap();
|
||||
assert_eq!(response.data, private_key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue