keyfork-derive-path-data: initial commit

This commit is contained in:
Ryan Heywood 2023-10-07 23:42:45 -05:00
parent 0f31cd2424
commit fa5d5ede1d
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
8 changed files with 68 additions and 4 deletions

8
Cargo.lock generated
View File

@ -893,6 +893,13 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "keyfork-derive-path-data"
version = "0.1.0"
dependencies = [
"keyfork-derive-util",
]
[[package]] [[package]]
name = "keyfork-derive-util" name = "keyfork-derive-util"
version = "0.1.0" version = "0.1.0"
@ -954,6 +961,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bincode", "bincode",
"hex-literal", "hex-literal",
"keyfork-derive-path-data",
"keyfork-derive-util", "keyfork-derive-util",
"keyfork-frame", "keyfork-frame",
"keyfork-mnemonic-util", "keyfork-mnemonic-util",

View File

@ -3,9 +3,10 @@
resolver = "2" resolver = "2"
members = [ members = [
"keyfork", "keyfork",
"keyfork-derive-util",
"keyfork-derive-key", "keyfork-derive-key",
"keyfork-derive-openpgp", "keyfork-derive-openpgp",
"keyfork-derive-path-data",
"keyfork-derive-util",
"keyfork-frame", "keyfork-frame",
"keyfork-mnemonic-util", "keyfork-mnemonic-util",
"keyfork-plumbing", "keyfork-plumbing",

View File

@ -0,0 +1,9 @@
[package]
name = "keyfork-derive-path-data"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
keyfork-derive-util = { version = "0.1.0", path = "../keyfork-derive-util", default-features = false }

View File

@ -0,0 +1,26 @@
use keyfork_derive_util::{DerivationPath, DerivationIndex};
pub static OPENPGP: DerivationIndex = DerivationIndex::new_unchecked(7366512, true);
pub enum Target {
OpenPGP(DerivationIndex),
}
impl std::fmt::Display for Target {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::OpenPGP(account) => {
write!(f, "OpenPGP key (account {account})")
}
}
}
}
/// Determine the closest [`Target`] for the given path. This method is intended to be used by
/// `keyforkd` to provide an optional textual prompt to what a client is attempting to derive.
pub fn guess_target(path: &DerivationPath) -> Option<Target> {
Some(match Vec::from_iter(path.iter())[..] {
[t, index] if t == &OPENPGP => Target::OpenPGP(index.clone()),
_ => return None,
})
}

View File

@ -25,11 +25,16 @@ impl DerivationIndex {
/// # Errors /// # Errors
/// ///
/// Returns an error if the index is larger than the hardened flag. /// Returns an error if the index is larger than the hardened flag.
pub fn new(index: u32, hardened: bool) -> Result<Self> { pub const fn new(index: u32, hardened: bool) -> Result<Self> {
if index & (0b1 << 31) > 0 { if index & (0b1 << 31) > 0 {
return Err(Error::IndexTooLarge(index)); return Err(Error::IndexTooLarge(index));
} }
Ok(Self(index | (u32::from(hardened) << 31))) Ok(Self(index | ((hardened as u32) << 31)))
}
#[doc(hidden)]
pub const fn new_unchecked(index: u32, hardened: bool) -> Self {
Self(index | ((hardened as u32) << 31))
} }
/* /*
@ -39,6 +44,10 @@ impl DerivationIndex {
} }
*/ */
pub fn inner(&self) -> u32 {
self.0
}
pub(crate) fn to_bytes(&self) -> [u8; 4] { pub(crate) fn to_bytes(&self) -> [u8; 4] {
self.0.to_be_bytes() self.0.to_be_bytes()
} }

View File

@ -207,7 +207,7 @@ impl Mnemonic {
bits[index * 11 + bit] = (word & (1 << (10 - bit))) > 0; bits[index * 11 + bit] = (word & (1 << (10 - bit))) > 0;
} }
} }
// remove checksum bits // remove checksum bits
bits.truncate(bits.len() - bits.len() % 32); bits.truncate(bits.len() - bits.len() % 32);

View File

@ -28,6 +28,7 @@ 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"] }
keyfork-derive-path-data = { version = "0.1.0", path = "../keyfork-derive-path-data" }
[dev-dependencies] [dev-dependencies]
hex-literal = "0.4.1" hex-literal = "0.4.1"

View File

@ -1,7 +1,9 @@
use std::{future::Future, pin::Pin, sync::Arc, task::Poll}; use std::{future::Future, pin::Pin, sync::Arc, task::Poll};
use keyfork_derive_util::request::{DerivationError, DerivationRequest, DerivationResponse}; use keyfork_derive_util::request::{DerivationError, DerivationRequest, DerivationResponse};
use keyfork_derive_path_data::guess_target;
use tower::Service; use tower::Service;
use tracing::info;
// NOTE: All values implemented in Keyforkd must implement Clone with low overhead, either by // NOTE: All values implemented in Keyforkd must implement Clone with low overhead, either by
// using an Arc or by having a small signature. This is because Service<T> takes &mut self. // using an Arc or by having a small signature. This is because Service<T> takes &mut self.
@ -50,6 +52,14 @@ impl Service<DerivationRequest> for Keyforkd {
if len < 2 { if len < 2 {
return Err(KeyforkdRequestError::InvalidDerivationLength(len)); return Err(KeyforkdRequestError::InvalidDerivationLength(len));
} }
#[cfg(feature = "tracing")]
if let Some(target) = guess_target(req.path()) {
info!("Deriving path: {target}");
} else {
info!("Deriving path: {}", req.path());
}
req.derive_with_master_seed((*seed).clone()) req.derive_with_master_seed((*seed).clone())
.map_err(KeyforkdRequestError::from) .map_err(KeyforkdRequestError::from)
}) })