all crates: `cargo fmt`
This commit is contained in:
parent
625e8e490b
commit
0cb96782ef
|
@ -9,58 +9,58 @@ use std::{os::unix::net::UnixStream, str::FromStr};
|
||||||
fn secp256k1_test_suite() {
|
fn secp256k1_test_suite() {
|
||||||
use k256::SecretKey;
|
use k256::SecretKey;
|
||||||
|
|
||||||
let tests = test_data()
|
let tests = test_data().unwrap().remove("secp256k1").unwrap();
|
||||||
.unwrap()
|
|
||||||
.remove("secp256k1")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for seed_test in tests {
|
for seed_test in tests {
|
||||||
let seed = seed_test.seed;
|
let seed = seed_test.seed;
|
||||||
run_test(&seed, move |socket_path| -> Result<(), Box<dyn std::error::Error + Send>> {
|
run_test(
|
||||||
for test in seed_test.tests {
|
&seed,
|
||||||
let socket = UnixStream::connect(socket_path).unwrap();
|
move |socket_path| -> Result<(), Box<dyn std::error::Error + Send>> {
|
||||||
let mut client = Client::new(socket);
|
for test in seed_test.tests {
|
||||||
let chain = DerivationPath::from_str(test.chain).unwrap();
|
|
||||||
let chain_len = chain.len();
|
|
||||||
if chain_len < 2 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if chain.iter().take(2).any(|index| !index.is_hardened()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Consistency check: ensure the server and the client can each derive the same
|
|
||||||
// key using an XPrv, for all but the last XPrv, which is verified after this
|
|
||||||
for i in 2..chain_len {
|
|
||||||
// FIXME: Keyfork will only allow one request per session
|
|
||||||
let socket = UnixStream::connect(socket_path).unwrap();
|
let socket = UnixStream::connect(socket_path).unwrap();
|
||||||
let mut client = Client::new(socket);
|
let mut client = Client::new(socket);
|
||||||
let path = DerivationPath::from_str(test.chain).unwrap();
|
let chain = DerivationPath::from_str(test.chain).unwrap();
|
||||||
let left_path = path.inner()[..i]
|
let chain_len = chain.len();
|
||||||
.iter()
|
if chain_len < 2 {
|
||||||
.fold(DerivationPath::default(), |p, i| p.chain_push(i.clone()));
|
continue;
|
||||||
let right_path = path.inner()[i..]
|
}
|
||||||
.iter()
|
if chain.iter().take(2).any(|index| !index.is_hardened()) {
|
||||||
.fold(DerivationPath::default(), |p, i| p.chain_push(i.clone()));
|
continue;
|
||||||
let xprv = dbg!(client.request_xprv::<SecretKey>(&left_path)).unwrap();
|
}
|
||||||
let derived_xprv = xprv.derive_path(&right_path).unwrap();
|
// Consistency check: ensure the server and the client can each derive the same
|
||||||
let socket = UnixStream::connect(socket_path).unwrap();
|
// key using an XPrv, for all but the last XPrv, which is verified after this
|
||||||
let mut client = Client::new(socket);
|
for i in 2..chain_len {
|
||||||
let keyforkd_xprv = client.request_xprv::<SecretKey>(&path).unwrap();
|
// FIXME: Keyfork will only allow one request per session
|
||||||
assert_eq!(
|
let socket = UnixStream::connect(socket_path).unwrap();
|
||||||
derived_xprv, keyforkd_xprv,
|
let mut client = Client::new(socket);
|
||||||
"{left_path} + {right_path} != {path}"
|
let path = DerivationPath::from_str(test.chain).unwrap();
|
||||||
|
let left_path = path.inner()[..i]
|
||||||
|
.iter()
|
||||||
|
.fold(DerivationPath::default(), |p, i| p.chain_push(i.clone()));
|
||||||
|
let right_path = path.inner()[i..]
|
||||||
|
.iter()
|
||||||
|
.fold(DerivationPath::default(), |p, i| p.chain_push(i.clone()));
|
||||||
|
let xprv = dbg!(client.request_xprv::<SecretKey>(&left_path)).unwrap();
|
||||||
|
let derived_xprv = xprv.derive_path(&right_path).unwrap();
|
||||||
|
let socket = UnixStream::connect(socket_path).unwrap();
|
||||||
|
let mut client = Client::new(socket);
|
||||||
|
let keyforkd_xprv = client.request_xprv::<SecretKey>(&path).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
derived_xprv, keyforkd_xprv,
|
||||||
|
"{left_path} + {right_path} != {path}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let req = DerivationRequest::new(
|
||||||
|
DerivationAlgorithm::Secp256k1,
|
||||||
|
&DerivationPath::from_str(test.chain).unwrap(),
|
||||||
);
|
);
|
||||||
|
let response =
|
||||||
|
DerivationResponse::try_from(client.request(&req.into()).unwrap()).unwrap();
|
||||||
|
assert_eq!(&response.data, test.private_key.as_slice());
|
||||||
}
|
}
|
||||||
let req = DerivationRequest::new(
|
Ok(())
|
||||||
DerivationAlgorithm::Secp256k1,
|
},
|
||||||
&DerivationPath::from_str(test.chain).unwrap(),
|
)
|
||||||
);
|
|
||||||
let response =
|
|
||||||
DerivationResponse::try_from(client.request(&req.into()).unwrap()).unwrap();
|
|
||||||
assert_eq!(&response.data, test.private_key.as_slice());
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,6 +162,9 @@ mod tests {
|
||||||
.call(content.clone())
|
.call(content.clone())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(result, serialize(&Result::<Test, Infallible>::Ok(test)).unwrap());
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
serialize(&Result::<Test, Infallible>::Ok(test)).unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,10 @@ impl Keyforkd {
|
||||||
/// Create a new instance of Keyfork from a given seed.
|
/// Create a new instance of Keyfork from a given seed.
|
||||||
pub fn new(seed: Vec<u8>) -> Self {
|
pub fn new(seed: Vec<u8>) -> Self {
|
||||||
if seed.len() < 16 {
|
if seed.len() < 16 {
|
||||||
warn!("Entropy size is lower than 128 bits: {} bits.", seed.len() * 8);
|
warn!(
|
||||||
|
"Entropy size is lower than 128 bits: {} bits.",
|
||||||
|
seed.len() * 8
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Self {
|
Self {
|
||||||
seed: Arc::new(seed),
|
seed: Arc::new(seed),
|
||||||
|
@ -77,11 +80,11 @@ impl Service<Request> for Keyforkd {
|
||||||
.iter()
|
.iter()
|
||||||
.take(2)
|
.take(2)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, index)| {
|
.find(|(_, index)| !index.is_hardened())
|
||||||
!index.is_hardened()
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
return Err(DerivationError::InvalidDerivationPath(i, unhardened_index.inner()).into())
|
return Err(
|
||||||
|
DerivationError::InvalidDerivationPath(i, unhardened_index.inner()).into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
|
@ -111,10 +114,7 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn properly_derives_secp256k1() {
|
async fn properly_derives_secp256k1() {
|
||||||
let tests = test_data()
|
let tests = test_data().unwrap().remove("secp256k1").unwrap();
|
||||||
.unwrap()
|
|
||||||
.remove("secp256k1")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for per_seed in tests {
|
for per_seed in tests {
|
||||||
let seed = &per_seed.seed;
|
let seed = &per_seed.seed;
|
||||||
|
|
|
@ -90,7 +90,10 @@ where
|
||||||
let service = ServiceBuilder::new()
|
let service = ServiceBuilder::new()
|
||||||
.layer(middleware::BincodeLayer::new())
|
.layer(middleware::BincodeLayer::new())
|
||||||
.service(Keyforkd::new(seed.to_vec()));
|
.service(Keyforkd::new(seed.to_vec()));
|
||||||
server.run(service).await.expect(bug!("Unable to start service"));
|
server
|
||||||
|
.run(service)
|
||||||
|
.await
|
||||||
|
.expect(bug!("Unable to start service"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,10 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut client = Client::discover_socket()?;
|
let mut client = Client::discover_socket()?;
|
||||||
let request = DerivationRequest::new(algo, &path);
|
let request = DerivationRequest::new(algo, &path);
|
||||||
let response = client.request(&request.into())?;
|
let response = client.request(&request.into())?;
|
||||||
println!("{}", smex::encode(DerivationResponse::try_from(response)?.data));
|
println!(
|
||||||
|
"{}",
|
||||||
|
smex::encode(DerivationResponse::try_from(response)?.data)
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
use std::{env, process::ExitCode, str::FromStr};
|
use std::{env, process::ExitCode, str::FromStr};
|
||||||
|
|
||||||
use keyfork_derive_util::DerivationPath;
|
|
||||||
use keyfork_derive_path_data::paths;
|
use keyfork_derive_path_data::paths;
|
||||||
|
use keyfork_derive_util::DerivationPath;
|
||||||
use keyforkd_client::Client;
|
use keyforkd_client::Client;
|
||||||
|
|
||||||
use ed25519_dalek::SigningKey;
|
use ed25519_dalek::SigningKey;
|
||||||
|
@ -82,7 +82,10 @@ fn validate(
|
||||||
let index = paths::OPENPGP.inner().first().unwrap();
|
let index = paths::OPENPGP.inner().first().unwrap();
|
||||||
|
|
||||||
let path = DerivationPath::from_str(path)?;
|
let path = DerivationPath::from_str(path)?;
|
||||||
assert!(path.len() >= 2, "Expected path of at least m/{index}/account_id'");
|
assert!(
|
||||||
|
path.len() >= 2,
|
||||||
|
"Expected path of at least m/{index}/account_id'"
|
||||||
|
);
|
||||||
|
|
||||||
let given_index = path.iter().next().expect("checked .len() above");
|
let given_index = path.iter().next().expect("checked .len() above");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -189,7 +189,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(has_any_nonzero, bug!("hmac function returned all-zero master key"));
|
assert!(
|
||||||
|
has_any_nonzero,
|
||||||
|
bug!("hmac function returned all-zero master key")
|
||||||
|
);
|
||||||
|
|
||||||
Self::from_parts(
|
Self::from_parts(
|
||||||
private_key
|
private_key
|
||||||
|
@ -223,13 +226,11 @@ where
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_parts(key: &[u8; 32], depth: u8, chain_code: [u8; 32]) -> Result<Self> {
|
pub fn from_parts(key: &[u8; 32], depth: u8, chain_code: [u8; 32]) -> Result<Self> {
|
||||||
match K::from_bytes(key) {
|
match K::from_bytes(key) {
|
||||||
Ok(key) => {
|
Ok(key) => Ok(Self {
|
||||||
Ok(Self {
|
private_key: key,
|
||||||
private_key: key,
|
depth,
|
||||||
depth,
|
chain_code,
|
||||||
chain_code,
|
}),
|
||||||
})
|
|
||||||
}
|
|
||||||
Err(_) => Err(Error::InvalidKey),
|
Err(_) => Err(Error::InvalidKey),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,10 @@ pub mod public_key;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use crate::extended_key::{private_key::{ExtendedPrivateKey, Error as XPrvError, VariableLengthSeed}, public_key::{ExtendedPublicKey, Error as XPubError}};
|
pub use crate::extended_key::{
|
||||||
|
private_key::{Error as XPrvError, ExtendedPrivateKey, VariableLengthSeed},
|
||||||
|
public_key::{Error as XPubError, ExtendedPublicKey},
|
||||||
|
};
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
index::{DerivationIndex, Error as IndexError},
|
index::{DerivationIndex, Error as IndexError},
|
||||||
|
|
|
@ -110,7 +110,7 @@ impl PublicKey for k256::PublicKey {
|
||||||
|
|
||||||
fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, Self::Err> {
|
fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, Self::Err> {
|
||||||
use k256::elliptic_curve::ScalarPrimitive;
|
use k256::elliptic_curve::ScalarPrimitive;
|
||||||
use k256::{Secp256k1, Scalar};
|
use k256::{Scalar, Secp256k1};
|
||||||
|
|
||||||
// Construct a scalar from bytes
|
// Construct a scalar from bytes
|
||||||
let scalar = ScalarPrimitive::<Secp256k1>::from_bytes(&other.into());
|
let scalar = ScalarPrimitive::<Secp256k1>::from_bytes(&other.into());
|
||||||
|
|
|
@ -13,10 +13,7 @@ use keyfork_slip10_test_data::{test_data, Test};
|
||||||
fn secp256k1() {
|
fn secp256k1() {
|
||||||
use k256::SecretKey;
|
use k256::SecretKey;
|
||||||
|
|
||||||
let tests = test_data()
|
let tests = test_data().unwrap().remove("secp256k1").unwrap();
|
||||||
.unwrap()
|
|
||||||
.remove("secp256k1")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for per_seed in tests {
|
for per_seed in tests {
|
||||||
let seed = &per_seed.seed;
|
let seed = &per_seed.seed;
|
||||||
|
|
|
@ -35,7 +35,11 @@ fn run() -> Result<()> {
|
||||||
let openpgp = OpenPGP;
|
let openpgp = OpenPGP;
|
||||||
let prompt_handler = default_handler()?;
|
let prompt_handler = default_handler()?;
|
||||||
|
|
||||||
let bytes = openpgp.decrypt_all_shards_to_secret(key_discovery.as_deref(), messages_file, prompt_handler)?;
|
let bytes = openpgp.decrypt_all_shards_to_secret(
|
||||||
|
key_discovery.as_deref(),
|
||||||
|
messages_file,
|
||||||
|
prompt_handler,
|
||||||
|
)?;
|
||||||
print!("{}", smex::encode(bytes));
|
print!("{}", smex::encode(bytes));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use keyfork_prompt::default_handler;
|
use keyfork_prompt::default_handler;
|
||||||
use keyfork_shard::{Format, openpgp::OpenPGP};
|
use keyfork_shard::{openpgp::OpenPGP, Format};
|
||||||
|
|
||||||
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
@ -35,7 +35,11 @@ fn run() -> Result<()> {
|
||||||
let openpgp = OpenPGP;
|
let openpgp = OpenPGP;
|
||||||
let prompt_handler = default_handler()?;
|
let prompt_handler = default_handler()?;
|
||||||
|
|
||||||
openpgp.decrypt_one_shard_for_transport(key_discovery.as_deref(), messages_file, prompt_handler)?;
|
openpgp.decrypt_one_shard_for_transport(
|
||||||
|
key_discovery.as_deref(),
|
||||||
|
messages_file,
|
||||||
|
prompt_handler,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
//! Combine OpenPGP shards using remote transport and output the hex-encoded secret.
|
//! Combine OpenPGP shards using remote transport and output the hex-encoded secret.
|
||||||
|
|
||||||
use std::{
|
use std::{env, process::ExitCode};
|
||||||
env,
|
|
||||||
process::ExitCode,
|
|
||||||
};
|
|
||||||
|
|
||||||
use keyfork_shard::remote_decrypt;
|
use keyfork_shard::remote_decrypt;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::{env, path::PathBuf, process::ExitCode, str::FromStr};
|
use std::{env, path::PathBuf, process::ExitCode, str::FromStr};
|
||||||
|
|
||||||
use keyfork_shard::{Format, openpgp::OpenPGP};
|
use keyfork_shard::{openpgp::OpenPGP, Format};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum Error {
|
enum Error {
|
||||||
|
@ -52,7 +52,13 @@ fn run() -> Result<()> {
|
||||||
|
|
||||||
let openpgp = OpenPGP;
|
let openpgp = OpenPGP;
|
||||||
|
|
||||||
openpgp.shard_and_encrypt(threshold, max, &input, key_discovery.as_path(), std::io::stdout())?;
|
openpgp.shard_and_encrypt(
|
||||||
|
threshold,
|
||||||
|
max,
|
||||||
|
&input,
|
||||||
|
key_discovery.as_path(),
|
||||||
|
std::io::stdout(),
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,12 @@ use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
rc::Rc,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::Mutex,
|
sync::Mutex,
|
||||||
rc::Rc,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use blahaj::Share;
|
||||||
use keyfork_bug::bug;
|
use keyfork_bug::bug;
|
||||||
use keyfork_derive_openpgp::{
|
use keyfork_derive_openpgp::{
|
||||||
derive_util::{DerivationPath, VariableLengthSeed},
|
derive_util::{DerivationPath, VariableLengthSeed},
|
||||||
|
@ -25,7 +26,7 @@ use openpgp::{
|
||||||
stream::{DecryptionHelper, DecryptorBuilder, VerificationHelper},
|
stream::{DecryptionHelper, DecryptorBuilder, VerificationHelper},
|
||||||
Parse,
|
Parse,
|
||||||
},
|
},
|
||||||
policy::{NullPolicy, StandardPolicy, Policy},
|
policy::{NullPolicy, Policy, StandardPolicy},
|
||||||
serialize::{
|
serialize::{
|
||||||
stream::{ArbitraryWriter, Encryptor2, LiteralWriter, Message, Recipient, Signer},
|
stream::{ArbitraryWriter, Encryptor2, LiteralWriter, Message, Recipient, Signer},
|
||||||
Marshal,
|
Marshal,
|
||||||
|
@ -34,7 +35,6 @@ use openpgp::{
|
||||||
KeyID, PacketPile,
|
KeyID, PacketPile,
|
||||||
};
|
};
|
||||||
pub use sequoia_openpgp as openpgp;
|
pub use sequoia_openpgp as openpgp;
|
||||||
use blahaj::Share;
|
|
||||||
|
|
||||||
mod keyring;
|
mod keyring;
|
||||||
use keyring::Keyring;
|
use keyring::Keyring;
|
||||||
|
@ -238,7 +238,7 @@ impl OpenPGP {
|
||||||
let policy = StandardPolicy::new();
|
let policy = StandardPolicy::new();
|
||||||
let valid_cert = cert.with_policy(&policy, None).map_err(Error::Sequoia)?;
|
let valid_cert = cert.with_policy(&policy, None).map_err(Error::Sequoia)?;
|
||||||
if get_encryption_keys(&valid_cert).next().is_none() {
|
if get_encryption_keys(&valid_cert).next().is_none() {
|
||||||
return Err(Error::NoValidKeys(valid_cert.keyid()))
|
return Err(Error::NoValidKeys(valid_cert.keyid()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(certs.into_values().collect())
|
Ok(certs.into_values().collect())
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl FromStr for Options {
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
return Ok(Default::default())
|
return Ok(Default::default());
|
||||||
}
|
}
|
||||||
let values = s
|
let values = s
|
||||||
.split(',')
|
.split(',')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{Keyfork, create};
|
use super::{create, Keyfork};
|
||||||
use clap::{Args, Parser, Subcommand, ValueEnum};
|
use clap::{Args, Parser, Subcommand, ValueEnum};
|
||||||
use std::{fmt::Display, io::Write, path::PathBuf};
|
use std::{fmt::Display, io::Write, path::PathBuf};
|
||||||
|
|
||||||
|
@ -141,10 +141,9 @@ impl Display for Slug {
|
||||||
#[allow(clippy::redundant_at_rest_pattern)]
|
#[allow(clippy::redundant_at_rest_pattern)]
|
||||||
match (self.0.inner() & (0b1 << 31)).to_be_bytes().as_slice() {
|
match (self.0.inner() & (0b1 << 31)).to_be_bytes().as_slice() {
|
||||||
[0, 0, 0, 0] => Ok(()),
|
[0, 0, 0, 0] => Ok(()),
|
||||||
[0, 0, 0, bytes @ ..] | [0, 0, bytes @ ..] | [0, bytes @ ..] | [bytes @ ..] => f
|
[0, 0, 0, bytes @ ..] | [0, 0, bytes @ ..] | [0, bytes @ ..] | [bytes @ ..] => {
|
||||||
.write_str(
|
f.write_str(std::str::from_utf8(bytes).expect("slug constructed from non-utf8"))
|
||||||
std::str::from_utf8(bytes).expect("slug constructed from non-utf8"),
|
}
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use super::{
|
use super::{
|
||||||
create,
|
create,
|
||||||
derive::{self, Deriver},
|
derive::{self, Deriver},
|
||||||
provision,
|
provision, Keyfork,
|
||||||
Keyfork,
|
|
||||||
};
|
};
|
||||||
use crate::{clap_ext::*, config, openpgp_card::factory_reset_current_card};
|
use crate::{clap_ext::*, config, openpgp_card::factory_reset_current_card};
|
||||||
use card_backend_pcsc::PcscBackend;
|
use card_backend_pcsc::PcscBackend;
|
||||||
|
@ -20,7 +19,7 @@ use keyfork_derive_openpgp::{
|
||||||
openpgp::{
|
openpgp::{
|
||||||
self,
|
self,
|
||||||
armor::{Kind, Writer},
|
armor::{Kind, Writer},
|
||||||
packet::{UserID, signature::SignatureBuilder},
|
packet::{signature::SignatureBuilder, UserID},
|
||||||
policy::StandardPolicy,
|
policy::StandardPolicy,
|
||||||
serialize::{
|
serialize::{
|
||||||
stream::{Encryptor2, LiteralWriter, Message, Recipient},
|
stream::{Encryptor2, LiteralWriter, Message, Recipient},
|
||||||
|
@ -544,7 +543,9 @@ fn derive_key(seed: [u8; 64], index: u8) -> Result<openpgp::Cert, Box<dyn std::e
|
||||||
];
|
];
|
||||||
|
|
||||||
let subkey = DerivationIndex::new(u32::from(index), true)?;
|
let subkey = DerivationIndex::new(u32::from(index), true)?;
|
||||||
let path = keyfork_derive_path_data::paths::OPENPGP_SHARD.clone().chain_push(subkey);
|
let path = keyfork_derive_path_data::paths::OPENPGP_SHARD
|
||||||
|
.clone()
|
||||||
|
.chain_push(subkey);
|
||||||
let xprv = XPrv::new(seed)
|
let xprv = XPrv::new(seed)
|
||||||
.expect("could not construct master key from seed")
|
.expect("could not construct master key from seed")
|
||||||
.derive_path(&path)?;
|
.derive_path(&path)?;
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod recover;
|
||||||
mod shard;
|
mod shard;
|
||||||
|
|
||||||
pub fn create(path: &std::path::Path) -> std::io::Result<std::fs::File> {
|
pub fn create(path: &std::path::Path) -> std::io::Result<std::fs::File> {
|
||||||
eprintln!("Writing derived key to: {path}", path=path.display());
|
eprintln!("Writing derived key to: {path}", path = path.display());
|
||||||
std::fs::File::create(path)
|
std::fs::File::create(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,12 +96,7 @@ impl KeyforkCommands {
|
||||||
KeyforkCommands::Completion { shell } => {
|
KeyforkCommands::Completion { shell } => {
|
||||||
let mut command = Keyfork::command();
|
let mut command = Keyfork::command();
|
||||||
let command_name = command.get_name().to_string();
|
let command_name = command.get_name().to_string();
|
||||||
clap_complete::generate(
|
clap_complete::generate(*shell, &mut command, command_name, &mut std::io::stdout());
|
||||||
*shell,
|
|
||||||
&mut command,
|
|
||||||
command_name,
|
|
||||||
&mut std::io::stdout(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -94,7 +94,10 @@ impl Provisioner {
|
||||||
|
|
||||||
impl ValueEnum for Provisioner {
|
impl ValueEnum for Provisioner {
|
||||||
fn value_variants<'a>() -> &'a [Self] {
|
fn value_variants<'a>() -> &'a [Self] {
|
||||||
&[Self::OpenPGPCard(openpgp::OpenPGPCard), Self::Shard(openpgp::Shard)]
|
&[
|
||||||
|
Self::OpenPGPCard(openpgp::OpenPGPCard),
|
||||||
|
Self::Shard(openpgp::Shard),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_possible_value(&self) -> Option<PossibleValue> {
|
fn to_possible_value(&self) -> Option<PossibleValue> {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use super::Keyfork;
|
use super::Keyfork;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use std::path::PathBuf;
|
|
||||||
use nix::{
|
use nix::{
|
||||||
sys::wait::waitpid,
|
sys::wait::waitpid,
|
||||||
unistd::{fork, ForkResult},
|
unistd::{fork, ForkResult},
|
||||||
};
|
};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use keyfork_mnemonic::{English, Mnemonic};
|
use keyfork_mnemonic::{English, Mnemonic};
|
||||||
use keyfork_prompt::{
|
use keyfork_prompt::{
|
||||||
|
@ -86,7 +86,7 @@ pub struct Recover {
|
||||||
command: RecoverSubcommands,
|
command: RecoverSubcommands,
|
||||||
|
|
||||||
/// Daemonize the server once started, restoring control back to the shell.
|
/// Daemonize the server once started, restoring control back to the shell.
|
||||||
#[arg(long, global=true)]
|
#[arg(long, global = true)]
|
||||||
daemon: bool,
|
daemon: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,12 +102,12 @@ impl Recover {
|
||||||
// wait for the child to die, so we don't exit prematurely
|
// wait for the child to die, so we don't exit prematurely
|
||||||
waitpid(Some(child), None)?;
|
waitpid(Some(child), None)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
}
|
||||||
ForkResult::Child => {
|
ForkResult::Child => {
|
||||||
if let ForkResult::Parent { .. } = unsafe { fork() }? {
|
if let ForkResult::Parent { .. } = unsafe { fork() }? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
|
|
|
@ -109,14 +109,15 @@ impl ShardExec for OpenPGP {
|
||||||
output: &mut impl Write,
|
output: &mut impl Write,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
use keyfork_derive_openpgp::openpgp::{
|
use keyfork_derive_openpgp::openpgp::{
|
||||||
|
armor::{Kind, Writer},
|
||||||
serialize::Marshal,
|
serialize::Marshal,
|
||||||
armor::{Writer, Kind},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let openpgp = keyfork_shard::openpgp::OpenPGP;
|
let openpgp = keyfork_shard::openpgp::OpenPGP;
|
||||||
let prompt = default_handler()?;
|
let prompt = default_handler()?;
|
||||||
|
|
||||||
let (threshold, certs) = openpgp.decrypt_metadata_from_file(key_discovery, input, prompt)?;
|
let (threshold, certs) =
|
||||||
|
openpgp.decrypt_metadata_from_file(key_discovery, input, prompt)?;
|
||||||
let mut writer = Writer::new(output_pubkeys, Kind::PublicKey)?;
|
let mut writer = Writer::new(output_pubkeys, Kind::PublicKey)?;
|
||||||
for cert in certs {
|
for cert in certs {
|
||||||
cert.serialize(&mut writer)?;
|
cert.serialize(&mut writer)?;
|
||||||
|
@ -187,7 +188,7 @@ pub enum ShardSubcommands {
|
||||||
|
|
||||||
/// The path to discover private keys from.
|
/// The path to discover private keys from.
|
||||||
key_discovery: Option<PathBuf>,
|
key_discovery: Option<PathBuf>,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShardSubcommands {
|
impl ShardSubcommands {
|
||||||
|
@ -256,7 +257,11 @@ impl ShardSubcommands {
|
||||||
None => panic!("{COULD_NOT_DETERMINE_FORMAT}"),
|
None => panic!("{COULD_NOT_DETERMINE_FORMAT}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ShardSubcommands::Metadata { shardfile, output_pubkeys, key_discovery } => {
|
ShardSubcommands::Metadata {
|
||||||
|
shardfile,
|
||||||
|
output_pubkeys,
|
||||||
|
key_discovery,
|
||||||
|
} => {
|
||||||
let shard_content = std::fs::read_to_string(shardfile)?;
|
let shard_content = std::fs::read_to_string(shardfile)?;
|
||||||
if shard_content.contains("BEGIN PGP MESSAGE") {
|
if shard_content.contains("BEGIN PGP MESSAGE") {
|
||||||
let _ = format.insert(Format::OpenPGP(OpenPGP));
|
let _ = format.insert(Format::OpenPGP(OpenPGP));
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
#![allow(clippy::module_name_repetitions)]
|
#![allow(clippy::module_name_repetitions)]
|
||||||
|
|
||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
|
@ -8,9 +7,9 @@ use clap::Parser;
|
||||||
|
|
||||||
use keyfork_bin::{Bin, ClosureBin};
|
use keyfork_bin::{Bin, ClosureBin};
|
||||||
|
|
||||||
|
pub mod clap_ext;
|
||||||
mod cli;
|
mod cli;
|
||||||
mod config;
|
mod config;
|
||||||
pub mod clap_ext;
|
|
||||||
mod openpgp_card;
|
mod openpgp_card;
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
|
|
|
@ -171,7 +171,6 @@ fn dbg_elapsed(count: u64, instant: Instant) {
|
||||||
let framerate = count as f64 / elapsed as f64;
|
let framerate = count as f64 / elapsed as f64;
|
||||||
eprintln!("framerate: {count}/{elapsed} = {framerate}");
|
eprintln!("framerate: {count}/{elapsed} = {framerate}");
|
||||||
std::thread::sleep(std::time::Duration::from_secs(5));
|
std::thread::sleep(std::time::Duration::from_secs(5));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -45,7 +45,7 @@ fn main() -> Result<()> {
|
||||||
if let Err(e) = generate_bindings_file() {
|
if let Err(e) = generate_bindings_file() {
|
||||||
eprintln!("Building zbar-sys failed: {e}");
|
eprintln!("Building zbar-sys failed: {e}");
|
||||||
eprintln!("Ensure zbar headers, libclang, and pkg-config are installed");
|
eprintln!("Ensure zbar headers, libclang, and pkg-config are installed");
|
||||||
return Err(e)
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -43,12 +43,7 @@ impl Image {
|
||||||
/// Accepts raw data in the configured format. See: [`Image::set_format`]
|
/// Accepts raw data in the configured format. See: [`Image::set_format`]
|
||||||
fn set_data(&mut self, data: Vec<u8>) {
|
fn set_data(&mut self, data: Vec<u8>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::zbar_image_set_data(
|
sys::zbar_image_set_data(self.inner, data.as_ptr().cast(), data.len() as u64, None)
|
||||||
self.inner,
|
|
||||||
data.as_ptr().cast(),
|
|
||||||
data.len() as u64,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// keep data in self to avoid use after free when data goes out of scope
|
// keep data in self to avoid use after free when data goes out of scope
|
||||||
let _ = self.inner_data.insert(data);
|
let _ = self.inner_data.insert(data);
|
||||||
|
|
|
@ -58,10 +58,7 @@ impl ImageScanner {
|
||||||
/// Link: [`sys::zbar_scan_image`]
|
/// Link: [`sys::zbar_scan_image`]
|
||||||
///
|
///
|
||||||
/// TODO: return an iterator over scanned values
|
/// TODO: return an iterator over scanned values
|
||||||
pub fn scan_image(
|
pub fn scan_image(&mut self, image: &Image) -> Vec<Symbol> {
|
||||||
&mut self,
|
|
||||||
image: &Image,
|
|
||||||
) -> Vec<Symbol> {
|
|
||||||
unsafe { sys::zbar_scan_image(self.inner, image.inner) };
|
unsafe { sys::zbar_scan_image(self.inner, image.inner) };
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let mut symbol = unsafe { sys::zbar_image_first_symbol(image.inner) };
|
let mut symbol = unsafe { sys::zbar_image_first_symbol(image.inner) };
|
||||||
|
|
|
@ -11,6 +11,6 @@ pub use sys::zbar_config_e as Config;
|
||||||
pub use sys::zbar_modifier_e as Modifier;
|
pub use sys::zbar_modifier_e as Modifier;
|
||||||
pub use sys::zbar_orientation_e as Orientation;
|
pub use sys::zbar_orientation_e as Orientation;
|
||||||
|
|
||||||
pub mod image_scanner;
|
|
||||||
pub mod image;
|
pub mod image;
|
||||||
|
pub mod image_scanner;
|
||||||
pub mod symbol;
|
pub mod symbol;
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub trait Bin {
|
||||||
#[allow(clippy::missing_errors_doc)]
|
#[allow(clippy::missing_errors_doc)]
|
||||||
fn validate_args(&self, args: impl Iterator<Item = String>) -> ProcessResult<Self::Args>;
|
fn validate_args(&self, args: impl Iterator<Item = String>) -> ProcessResult<Self::Args>;
|
||||||
|
|
||||||
/// Run the binary
|
/// Run the binary
|
||||||
#[allow(clippy::missing_errors_doc)]
|
#[allow(clippy::missing_errors_doc)]
|
||||||
fn run(&self, args: Self::Args) -> ProcessResult;
|
fn run(&self, args: Self::Args) -> ProcessResult;
|
||||||
|
|
||||||
|
@ -102,10 +102,13 @@ pub trait Bin {
|
||||||
|
|
||||||
/// A Bin that doesn't take any arguments.
|
/// A Bin that doesn't take any arguments.
|
||||||
pub struct ClosureBin<F: Fn() -> ProcessResult> {
|
pub struct ClosureBin<F: Fn() -> ProcessResult> {
|
||||||
closure: F
|
closure: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F> ClosureBin<F> where F: Fn() -> ProcessResult {
|
impl<F> ClosureBin<F>
|
||||||
|
where
|
||||||
|
F: Fn() -> ProcessResult,
|
||||||
|
{
|
||||||
/// Create a new Bin from a closure.
|
/// Create a new Bin from a closure.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -120,13 +123,14 @@ impl<F> ClosureBin<F> where F: Fn() -> ProcessResult {
|
||||||
/// bin.main();
|
/// bin.main();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(closure: F) -> Self {
|
pub fn new(closure: F) -> Self {
|
||||||
Self {
|
Self { closure }
|
||||||
closure
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F> Bin for ClosureBin<F> where F: Fn() -> ProcessResult {
|
impl<F> Bin for ClosureBin<F>
|
||||||
|
where
|
||||||
|
F: Fn() -> ProcessResult,
|
||||||
|
{
|
||||||
type Args = ();
|
type Args = ();
|
||||||
|
|
||||||
fn validate_args(&self, _args: impl Iterator<Item = String>) -> ProcessResult<Self::Args> {
|
fn validate_args(&self, _args: impl Iterator<Item = String>) -> ProcessResult<Self::Args> {
|
||||||
|
|
|
@ -8,7 +8,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
input.read_line(&mut line)?;
|
input.read_line(&mut line)?;
|
||||||
let decoded = smex::decode(line.trim())?;
|
let decoded = smex::decode(line.trim())?;
|
||||||
|
|
||||||
let mnemonic = Mnemonic::from_raw_bytes(&decoded) ;
|
let mnemonic = Mnemonic::from_raw_bytes(&decoded);
|
||||||
|
|
||||||
println!("{mnemonic}");
|
println!("{mnemonic}");
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,9 @@ impl Wordlist for English {
|
||||||
let mut words = wordlist_file.lines().skip(1).map(|x| x.trim().to_string());
|
let mut words = wordlist_file.lines().skip(1).map(|x| x.trim().to_string());
|
||||||
English {
|
English {
|
||||||
words: std::array::from_fn(|_| {
|
words: std::array::from_fn(|_| {
|
||||||
words.next().expect(bug!("wordlist {} should have 2048 words"))
|
words
|
||||||
|
.next()
|
||||||
|
.expect(bug!("wordlist {} should have 2048 words"))
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -283,7 +285,7 @@ where
|
||||||
return Err(MnemonicGenerationError::InvalidByteLength(bit_count));
|
return Err(MnemonicGenerationError::InvalidByteLength(bit_count));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok( Self::from_raw_bytes(bytes) )
|
Ok(Self::from_raw_bytes(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a [`Mnemonic`] from the provided data and [`Wordlist`]. The data may be of a size
|
/// Generate a [`Mnemonic`] from the provided data and [`Wordlist`]. The data may be of a size
|
||||||
|
|
|
@ -148,7 +148,9 @@ where
|
||||||
.queue(cursor::MoveTo(0, 0))
|
.queue(cursor::MoveTo(0, 0))
|
||||||
.expect(bug!("can't move to origin"));
|
.expect(bug!("can't move to origin"));
|
||||||
}
|
}
|
||||||
self.write.flush().expect(bug!("can't execute terminal reset commands"));
|
self.write
|
||||||
|
.flush()
|
||||||
|
.expect(bug!("can't execute terminal reset commands"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,12 +351,14 @@ where
|
||||||
KeyCode::Left | KeyCode::Up => {
|
KeyCode::Left | KeyCode::Up => {
|
||||||
active_choice = active_choice.saturating_sub(1);
|
active_choice = active_choice.saturating_sub(1);
|
||||||
}
|
}
|
||||||
KeyCode::Right | KeyCode::Down => match choices.len().saturating_sub(active_choice) {
|
KeyCode::Right | KeyCode::Down => {
|
||||||
0 | 1 => {}
|
match choices.len().saturating_sub(active_choice) {
|
||||||
_ => {
|
0 | 1 => {}
|
||||||
active_choice += 1;
|
_ => {
|
||||||
|
active_choice += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
KeyCode::Enter => {
|
KeyCode::Enter => {
|
||||||
return Ok(active_choice);
|
return Ok(active_choice);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,9 +87,7 @@ impl Validator for SecurePinValidator {
|
||||||
if !range.contains(&ch) {
|
if !range.contains(&ch) {
|
||||||
return Err(Box::new(PinError::InvalidCharacters(ch, index)));
|
return Err(Box::new(PinError::InvalidCharacters(ch, index)));
|
||||||
}
|
}
|
||||||
if [-1, 1].contains(&(ch as i32 - last_char))
|
if [-1, 1].contains(&(ch as i32 - last_char)) && !ignore_sequential_characters {
|
||||||
&& !ignore_sequential_characters
|
|
||||||
{
|
|
||||||
score += 1;
|
score += 1;
|
||||||
}
|
}
|
||||||
last_char = ch as i32;
|
last_char = ch as i32;
|
||||||
|
@ -102,7 +100,7 @@ impl Validator for SecurePinValidator {
|
||||||
score += s.chars().count() - chars.len();
|
score += s.chars().count() - chars.len();
|
||||||
}
|
}
|
||||||
if score * 2 > s.chars().count() {
|
if score * 2 > s.chars().count() {
|
||||||
return Err(Box::new(PinError::InsecurePIN))
|
return Err(Box::new(PinError::InsecurePIN));
|
||||||
}
|
}
|
||||||
Ok(s)
|
Ok(s)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue