70 lines
2.0 KiB
Rust
70 lines
2.0 KiB
Rust
use std::{env, process::ExitCode, str::FromStr};
|
|
|
|
use keyfork_derive_path_data::paths;
|
|
use keyfork_derive_util::{DerivationPath, ExtendedPrivateKey, PathError};
|
|
use keyforkd_client::Client;
|
|
|
|
use ed25519_dalek::SigningKey;
|
|
|
|
type XPrv = ExtendedPrivateKey<SigningKey>;
|
|
|
|
/// Any error that can occur while deriving a key.
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum Error {
|
|
/// The given path could not be parsed.
|
|
#[error("Could not parse the given path: {0}")]
|
|
PathFormat(#[from] PathError),
|
|
|
|
/// The request to derive data failed.
|
|
#[error("Unable to perform key derivation request: {0}")]
|
|
KeyforkdClient(#[from] keyforkd_client::Error),
|
|
}
|
|
|
|
#[allow(missing_docs)]
|
|
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
|
|
|
fn validate(path: &str) -> Result<DerivationPath> {
|
|
let index = paths::AGE.inner().first().unwrap();
|
|
|
|
let path = DerivationPath::from_str(path)?;
|
|
assert!(
|
|
path.len() >= 2,
|
|
"Expected path of at least m/{index}/account_id'"
|
|
);
|
|
|
|
let given_index = path.iter().next().expect("checked .len() above");
|
|
assert_eq!(
|
|
index, given_index,
|
|
"Expected derivation path starting with m/{index}, got: {given_index}",
|
|
);
|
|
|
|
Ok(path)
|
|
}
|
|
|
|
fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut args = env::args();
|
|
let program_name = args.next().expect("program name");
|
|
let args = args.collect::<Vec<_>>();
|
|
let path = match args.as_slice() {
|
|
[path] => validate(path)?,
|
|
_ => panic!("Usage: {program_name} path"),
|
|
};
|
|
|
|
let mut client = Client::discover_socket()?;
|
|
// TODO: should this key be clamped to Curve25519 specs?
|
|
let xprv: XPrv = client.request_xprv(&path)?;
|
|
let hrp = bech32::Hrp::parse("AGE-SECRET-KEY-")?;
|
|
let age_key = bech32::encode::<bech32::Bech32>(hrp, &xprv.private_key().to_bytes())?;
|
|
println!("{}", age_key.to_uppercase());
|
|
Ok(())
|
|
}
|
|
|
|
fn main() -> ExitCode {
|
|
if let Err(e) = run() {
|
|
eprintln!("Error: {e}");
|
|
ExitCode::FAILURE
|
|
} else {
|
|
ExitCode::SUCCESS
|
|
}
|
|
}
|