keyforkd: potentially working, but untested, example

This commit is contained in:
Ryan Heywood 2023-09-07 10:06:34 -05:00
parent d20d9d965d
commit 88dd6476df
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
5 changed files with 86 additions and 15 deletions

9
Cargo.lock generated
View File

@ -413,6 +413,7 @@ dependencies = [
"hex-literal", "hex-literal",
"hmac", "hmac",
"k256", "k256",
"keyfork-mnemonic-util",
"ripemd", "ripemd",
"serde", "serde",
"sha2", "sha2",
@ -735,18 +736,18 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.186" version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f5db24220c009de9bd45e69fb2938f4b6d2df856aa9304ce377b3180f83b7c1" checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.186" version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ad697f7e0b65af4983a4ce8f56ed5b357e8d3c36651bf6a7e13639c17b8e670" checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -26,6 +26,7 @@ thiserror = "1.0.47"
# Optional, not personally audited # Optional, not personally audited
k256 = { version = "0.13.1", default-features = false, features = ["std", "arithmetic"], optional = true } k256 = { version = "0.13.1", default-features = false, features = ["std", "arithmetic"], optional = true }
ed25519-dalek = { version = "2.0.0", optional = true } ed25519-dalek = { version = "2.0.0", optional = true }
keyfork-mnemonic-util = { version = "0.1.0", path = "../keyfork-mnemonic-util" }
[dev-dependencies] [dev-dependencies]
hex-literal = "0.4.1" hex-literal = "0.4.1"

View File

@ -7,6 +7,7 @@ pub mod index;
pub mod path; pub mod path;
pub mod private_key; pub mod private_key;
pub mod public_key; pub mod public_key;
pub mod request;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View File

@ -0,0 +1,73 @@
use crate::{extended_key::private_key::Error as XPrvError, DerivationPath, ExtendedPrivateKey};
use keyfork_mnemonic_util::Mnemonic;
use serde::{Deserialize, Serialize};
#[derive(Debug, thiserror::Error)]
pub enum DerivationError {
#[error("algorithm not supported")]
Algorithm,
#[error("{0}")]
ExtendedPrivateKey(#[from] XPrvError),
}
pub type Result<T, E = DerivationError> = std::result::Result<T, E>;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum DerivationAlgorithm {
Ed25519,
Secp256k1,
}
impl DerivationAlgorithm {
pub fn derive(&self, seed: Vec<u8>, path: &DerivationPath) -> Result<DerivationResponse> {
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(),
})
}
#[allow(unreachable_patterns)]
_ => Err(DerivationError::Algorithm),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DerivationRequest {
algorithm: DerivationAlgorithm,
path: DerivationPath,
}
impl DerivationRequest {
pub fn new(algorithm: DerivationAlgorithm, path: DerivationPath) -> Self {
Self { algorithm, path }
}
pub fn derive_with_mnemonic(&self, mnemonic: &Mnemonic) -> Result<DerivationResponse> {
self.derive_with_master_seed(mnemonic.seed())
}
pub fn derive_with_master_seed(&self, seed: Vec<u8>) -> Result<DerivationResponse> {
self.algorithm.derive(seed, &self.path)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DerivationResponse {
algorithm: DerivationAlgorithm,
data: Vec<u8>,
}

View File

@ -1,8 +1,7 @@
use std::{future::Future, pin::Pin, sync::Arc, task::Poll}; use std::{future::Future, pin::Pin, sync::Arc, task::Poll};
use keyfork_derive_util::DerivationPath; use keyfork_derive_util::request::{DerivationError, DerivationRequest, DerivationResponse};
use keyfork_mnemonic_util::Mnemonic; use keyfork_mnemonic_util::Mnemonic;
use thiserror::Error;
use tower::Service; use tower::Service;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -10,10 +9,6 @@ pub struct Keyforkd {
mnemonic: Arc<Mnemonic>, mnemonic: Arc<Mnemonic>,
} }
// Currently, this can't be instantiated, therefore it is a never-type
#[derive(Debug, Error)]
pub enum DerivationError {}
impl Keyforkd { impl Keyforkd {
pub fn new(mnemonic: Mnemonic) -> Self { pub fn new(mnemonic: Mnemonic) -> Self {
Self { Self {
@ -22,8 +17,8 @@ impl Keyforkd {
} }
} }
impl Service<DerivationPath> for Keyforkd { impl Service<DerivationRequest> for Keyforkd {
type Response = Vec<u8>; type Response = DerivationResponse;
type Error = DerivationError; type Error = DerivationError;
@ -37,8 +32,8 @@ impl Service<DerivationPath> for Keyforkd {
} }
#[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))]
fn call(&mut self, req: DerivationPath) -> Self::Future { fn call(&mut self, req: DerivationRequest) -> Self::Future {
dbg!(&req, &self.mnemonic); let app = self.clone();
Box::pin(async { Ok(vec![]) }) Box::pin(async { req.derive_with_mnemonic(&app.mnemonic) })
} }
} }