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"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
|
"hex-literal",
|
||||||
"keyfork-derive-util",
|
"keyfork-derive-util",
|
||||||
"keyfork-frame",
|
"keyfork-frame",
|
||||||
"keyfork-mnemonic-util",
|
"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 keyfork_mnemonic_util::Mnemonic;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -24,20 +24,20 @@ impl DerivationAlgorithm {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(feature = "ed25519")]
|
#[cfg(feature = "ed25519")]
|
||||||
Self::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 key = ExtendedPrivateKey::<ed25519_dalek::SigningKey>::new(seed)?;
|
||||||
let derived_key = key.derive_path(path)?;
|
let derived_key = key.derive_path(path)?;
|
||||||
Ok(DerivationResponse {
|
Ok(DerivationResponse {
|
||||||
algorithm: self.clone(),
|
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)]
|
#[allow(unreachable_patterns)]
|
||||||
|
@ -68,6 +68,6 @@ impl DerivationRequest {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct DerivationResponse {
|
pub struct DerivationResponse {
|
||||||
algorithm: DerivationAlgorithm,
|
pub algorithm: DerivationAlgorithm,
|
||||||
data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::*;
|
use crate::{request::*, *};
|
||||||
use hex_literal::hex;
|
use hex_literal::hex;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
@ -65,6 +65,9 @@ fn secp256k1() {
|
||||||
assert_eq!(derived_key.chain_code, chain_code);
|
assert_eq!(derived_key.chain_code, chain_code);
|
||||||
assert_eq!(derived_key.private_key.to_bytes().as_slice(), private_key);
|
assert_eq!(derived_key.private_key.to_bytes().as_slice(), private_key);
|
||||||
assert_eq!(derived_key.public_key().to_bytes(), public_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;
|
use ed25519_dalek::SigningKey;
|
||||||
|
|
||||||
// seed, chain, chain code, private, public
|
// seed, chain, chain code, private, public
|
||||||
let tests = [(
|
let tests = [
|
||||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
(
|
||||||
DerivationPath::from_str("m").unwrap(),
|
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||||
hex!("90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb"),
|
DerivationPath::from_str("m").unwrap(),
|
||||||
hex!("2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7"),
|
hex!("90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb"),
|
||||||
hex!("00a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed"),
|
hex!("2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7"),
|
||||||
), (
|
hex!("00a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed"),
|
||||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
),
|
||||||
DerivationPath::from_str("m/0'").unwrap(),
|
(
|
||||||
hex!("8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69"),
|
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||||
hex!("68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3"),
|
DerivationPath::from_str("m/0'").unwrap(),
|
||||||
hex!("008c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c"),
|
hex!("8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69"),
|
||||||
), (
|
hex!("68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3"),
|
||||||
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
hex!("008c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c"),
|
||||||
DerivationPath::from_str("m/0'/1'/2'/2'/1000000000'").unwrap(),
|
),
|
||||||
hex!("68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230"),
|
(
|
||||||
hex!("8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793"),
|
&hex!("000102030405060708090a0b0c0d0e0f")[..],
|
||||||
hex!("003c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a"),
|
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 {
|
for (seed, chain, chain_code, private_key, public_key) in tests {
|
||||||
let xkey = ExtendedPrivateKey::<SigningKey>::new(seed).unwrap();
|
let xkey = ExtendedPrivateKey::<SigningKey>::new(seed).unwrap();
|
||||||
let derived_key = xkey.derive_path(&chain).unwrap();
|
let derived_key = xkey.derive_path(&chain).unwrap();
|
||||||
assert_eq!(derived_key.chain_code, chain_code);
|
assert_eq!(derived_key.chain_code, chain_code);
|
||||||
assert_eq!(PrivateKey::to_bytes(&derived_key.private_key), private_key);
|
assert_eq!(PrivateKey::to_bytes(&derived_key.private_key), private_key);
|
||||||
assert_eq!(PublicKey::to_bytes(&derived_key.public_key()), public_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
|
# Personally audited
|
||||||
thiserror = "1.0.47"
|
thiserror = "1.0.47"
|
||||||
serde = { version = "1.0.186", features = ["derive"] }
|
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) })
|
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