keyfork-shard: first pass of reusable prompthandler
This commit is contained in:
parent
b15d088905
commit
354eae5a6a
|
@ -7,6 +7,7 @@ use std::{
|
|||
process::ExitCode,
|
||||
};
|
||||
|
||||
use keyfork_prompt::{DefaultTerminal, default_terminal};
|
||||
use keyfork_shard::{openpgp::OpenPGP, Format};
|
||||
|
||||
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
||||
|
@ -31,8 +32,10 @@ fn run() -> Result<()> {
|
|||
_ => panic!("Usage: {program_name} <shard> [key_discovery]"),
|
||||
};
|
||||
|
||||
let openpgp = OpenPGP;
|
||||
let bytes = openpgp.decrypt_all_shards_to_secret(key_discovery.as_deref(), messages_file)?;
|
||||
let openpgp = OpenPGP::<DefaultTerminal>::new();
|
||||
let prompt_handler = default_terminal()?;
|
||||
|
||||
let bytes = openpgp.decrypt_all_shards_to_secret(key_discovery.as_deref(), messages_file, prompt_handler)?;
|
||||
print!("{}", smex::encode(bytes));
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::{
|
|||
process::ExitCode,
|
||||
};
|
||||
|
||||
use keyfork_prompt::{DefaultTerminal, default_terminal};
|
||||
use keyfork_shard::{Format, openpgp::OpenPGP};
|
||||
|
||||
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
||||
|
@ -31,9 +32,10 @@ fn run() -> Result<()> {
|
|||
_ => panic!("Usage: {program_name} <shard> [key_discovery]"),
|
||||
};
|
||||
|
||||
let openpgp = OpenPGP;
|
||||
let openpgp = OpenPGP::<DefaultTerminal>::new();
|
||||
let prompt_handler = default_terminal()?;
|
||||
|
||||
openpgp.decrypt_one_shard_for_transport(key_discovery.as_deref(), messages_file)?;
|
||||
openpgp.decrypt_one_shard_for_transport(key_discovery.as_deref(), messages_file, prompt_handler)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::{env, path::PathBuf, process::ExitCode, str::FromStr};
|
||||
|
||||
use keyfork_prompt::terminal::DefaultTerminal;
|
||||
use keyfork_shard::{Format, openpgp::OpenPGP};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -50,7 +51,7 @@ fn run() -> Result<()> {
|
|||
smex::decode(line?)?
|
||||
};
|
||||
|
||||
let openpgp = OpenPGP;
|
||||
let openpgp = OpenPGP::<DefaultTerminal>::new();
|
||||
|
||||
openpgp.shard_and_encrypt(threshold, max, &input, key_discovery.as_path(), std::io::stdout())?;
|
||||
Ok(())
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use std::io::{stdin, stdout, Read, Write};
|
||||
use std::{
|
||||
io::{stdin, stdout, Read, Write},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use aes_gcm::{
|
||||
aead::{consts::U12, Aead, AeadCore, OsRng},
|
||||
|
@ -122,6 +125,7 @@ pub trait Format {
|
|||
&self,
|
||||
private_keys: Option<Self::PrivateKeyData>,
|
||||
encrypted_messages: &[Self::EncryptedData],
|
||||
prompt: Arc<Mutex<impl PromptHandler>>,
|
||||
) -> Result<(Vec<Share>, u8), Self::Error>;
|
||||
|
||||
/// Decrypt a single share and associated metadata from a reaable input. For the current
|
||||
|
@ -135,6 +139,7 @@ pub trait Format {
|
|||
&self,
|
||||
private_keys: Option<Self::PrivateKeyData>,
|
||||
encrypted_data: &[Self::EncryptedData],
|
||||
prompt: Arc<Mutex<impl PromptHandler>>,
|
||||
) -> Result<(Share, u8), Self::Error>;
|
||||
|
||||
/// Decrypt multiple shares and combine them to recreate a secret.
|
||||
|
@ -146,12 +151,17 @@ pub trait Format {
|
|||
&self,
|
||||
private_key_discovery: Option<impl KeyDiscovery<Self>>,
|
||||
reader: impl Read + Send + Sync,
|
||||
prompt: impl PromptHandler,
|
||||
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
||||
let private_keys = private_key_discovery
|
||||
.map(|p| p.discover_private_keys())
|
||||
.transpose()?;
|
||||
let encrypted_messages = self.parse_shard_file(reader)?;
|
||||
let (shares, threshold) = self.decrypt_all_shards(private_keys, &encrypted_messages)?;
|
||||
let (shares, threshold) = self.decrypt_all_shards(
|
||||
private_keys,
|
||||
&encrypted_messages,
|
||||
Arc::new(Mutex::new(prompt)),
|
||||
)?;
|
||||
|
||||
let secret = Sharks(threshold)
|
||||
.recover(&shares)
|
||||
|
@ -171,8 +181,9 @@ pub trait Format {
|
|||
&self,
|
||||
private_key_discovery: Option<impl KeyDiscovery<Self>>,
|
||||
reader: impl Read + Send + Sync,
|
||||
prompt: impl PromptHandler,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut pm = Terminal::new(stdin(), stdout())?;
|
||||
let prompt = Arc::new(Mutex::new(prompt));
|
||||
|
||||
// parse input
|
||||
let private_keys = private_key_discovery
|
||||
|
@ -187,7 +198,10 @@ pub trait Format {
|
|||
// receive remote data via scanning QR code from camera
|
||||
#[cfg(feature = "qrcode")]
|
||||
{
|
||||
pm.prompt_message(PromptMessage::Text(QRCODE_PROMPT.to_string()))?;
|
||||
prompt
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_message(PromptMessage::Text(QRCODE_PROMPT.to_string()))?;
|
||||
if let Ok(Some(hex)) =
|
||||
keyfork_qrcode::scan_camera(std::time::Duration::from_secs(30), 0)
|
||||
{
|
||||
|
@ -195,7 +209,10 @@ pub trait Format {
|
|||
nonce_data = Some(decoded_data[..12].try_into().map_err(|_| InvalidData)?);
|
||||
pubkey_data = Some(decoded_data[12..].try_into().map_err(|_| InvalidData)?)
|
||||
} else {
|
||||
pm.prompt_message(PromptMessage::Text(QRCODE_ERROR.to_string()))?;
|
||||
prompt
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_message(PromptMessage::Text(QRCODE_ERROR.to_string()))?;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -206,7 +223,9 @@ pub trait Format {
|
|||
let validator = MnemonicSetValidator {
|
||||
word_lengths: [9, 24],
|
||||
};
|
||||
let [nonce_mnemonic, pubkey_mnemonic] = pm
|
||||
let [nonce_mnemonic, pubkey_mnemonic] = prompt
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_validated_wordlist::<English, _>(
|
||||
QRCODE_COULDNT_READ,
|
||||
3,
|
||||
|
@ -237,7 +256,8 @@ pub trait Format {
|
|||
let shared_key = Aes256Gcm::new_from_slice(&hkdf_output)?;
|
||||
|
||||
// decrypt a single shard and create the payload
|
||||
let (share, threshold) = self.decrypt_one_shard(private_keys, &encrypted_messages)?;
|
||||
let (share, threshold) =
|
||||
self.decrypt_one_shard(private_keys, &encrypted_messages, prompt.clone())?;
|
||||
let mut payload = Vec::from(&share);
|
||||
payload.insert(0, HUNK_VERSION);
|
||||
payload.insert(1, threshold);
|
||||
|
@ -285,7 +305,7 @@ pub trait Format {
|
|||
let mut qrcode_data = our_pubkey_mnemonic.to_bytes();
|
||||
qrcode_data.extend(payload_mnemonic.as_bytes());
|
||||
if let Ok(qrcode) = qrencode(&smex::encode(&qrcode_data), ErrorCorrection::Highest) {
|
||||
pm.prompt_message(PromptMessage::Text(
|
||||
prompt.lock().unwrap().prompt_message(PromptMessage::Text(
|
||||
concat!(
|
||||
"A QR code will be displayed after this prompt. ",
|
||||
"Send the QR code back to the operator combining the shards. ",
|
||||
|
@ -293,11 +313,17 @@ pub trait Format {
|
|||
)
|
||||
.to_string(),
|
||||
))?;
|
||||
pm.prompt_message(PromptMessage::Data(qrcode))?;
|
||||
prompt
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_message(PromptMessage::Data(qrcode))?;
|
||||
}
|
||||
}
|
||||
|
||||
pm.prompt_message(PromptMessage::Text(format!(
|
||||
prompt
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_message(PromptMessage::Text(format!(
|
||||
"Upon request, these words should be sent: {our_pubkey_mnemonic} {payload_mnemonic}"
|
||||
)))?;
|
||||
|
||||
|
|
|
@ -5,12 +5,15 @@ use std::{
|
|||
io::{Read, Write},
|
||||
path::Path,
|
||||
str::FromStr,
|
||||
sync::{Arc, Mutex},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use keyfork_derive_openpgp::{
|
||||
derive_util::{DerivationPath, VariableLengthSeed},
|
||||
XPrv,
|
||||
};
|
||||
use keyfork_prompt::PromptHandler;
|
||||
use openpgp::{
|
||||
armor::{Kind, Writer},
|
||||
cert::{Cert, CertParser, ValidCert},
|
||||
|
@ -176,9 +179,20 @@ impl EncryptedMessage {
|
|||
}
|
||||
|
||||
///
|
||||
pub struct OpenPGP;
|
||||
pub struct OpenPGP<P: PromptHandler> {
|
||||
p: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl OpenPGP {
|
||||
impl<P: PromptHandler> OpenPGP<P> {
|
||||
#[allow(clippy::new_without_default, missing_docs)]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
p: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: PromptHandler> OpenPGP<P> {
|
||||
/// Read all OpenPGP certificates in a path and return a [`Vec`] of them. Certificates are read
|
||||
/// from a file, or from files one level deep in a directory.
|
||||
///
|
||||
|
@ -209,7 +223,7 @@ impl OpenPGP {
|
|||
}
|
||||
}
|
||||
|
||||
impl Format for OpenPGP {
|
||||
impl<P: PromptHandler> Format for OpenPGP<P> {
|
||||
type Error = Error;
|
||||
type PublicKey = Cert;
|
||||
type PrivateKeyData = Vec<Cert>;
|
||||
|
@ -400,12 +414,14 @@ impl Format for OpenPGP {
|
|||
&self,
|
||||
private_keys: Option<Self::PrivateKeyData>,
|
||||
encrypted_data: &[Self::EncryptedData],
|
||||
prompt: Arc<Mutex<impl PromptHandler>>,
|
||||
) -> std::result::Result<(Vec<Share>, u8), Self::Error> {
|
||||
// Be as liberal as possible when decrypting.
|
||||
// We don't want to invalidate someone's keys just because the old sig expired.
|
||||
let policy = NullPolicy::new();
|
||||
let mut keyring = Keyring::new(private_keys.unwrap_or_default())?;
|
||||
let mut manager = SmartcardManager::new()?;
|
||||
|
||||
let mut keyring = Keyring::new(private_keys.unwrap_or_default(), prompt.clone())?;
|
||||
let mut manager = SmartcardManager::new(prompt.clone())?;
|
||||
|
||||
let mut encrypted_messages = encrypted_data.iter();
|
||||
|
||||
|
@ -457,10 +473,12 @@ impl Format for OpenPGP {
|
|||
&self,
|
||||
private_keys: Option<Self::PrivateKeyData>,
|
||||
encrypted_data: &[Self::EncryptedData],
|
||||
prompt: Arc<Mutex<impl PromptHandler>>,
|
||||
) -> std::result::Result<(Share, u8), Self::Error> {
|
||||
let policy = NullPolicy::new();
|
||||
let mut keyring = Keyring::new(private_keys.unwrap_or_default())?;
|
||||
let mut manager = SmartcardManager::new()?;
|
||||
|
||||
let mut keyring = Keyring::new(private_keys.unwrap_or_default(), prompt.clone())?;
|
||||
let mut manager = SmartcardManager::new(prompt.clone())?;
|
||||
|
||||
let mut encrypted_messages = encrypted_data.iter();
|
||||
|
||||
|
@ -499,22 +517,22 @@ impl Format for OpenPGP {
|
|||
}
|
||||
}
|
||||
|
||||
impl KeyDiscovery<OpenPGP> for &Path {
|
||||
fn discover_public_keys(&self) -> Result<Vec<<OpenPGP as Format>::PublicKey>> {
|
||||
OpenPGP::discover_certs(self)
|
||||
impl<P: PromptHandler> KeyDiscovery<OpenPGP<P>> for &Path {
|
||||
fn discover_public_keys(&self) -> Result<Vec<<OpenPGP<P> as Format>::PublicKey>> {
|
||||
OpenPGP::<P>::discover_certs(self)
|
||||
}
|
||||
|
||||
fn discover_private_keys(&self) -> Result<<OpenPGP as Format>::PrivateKeyData> {
|
||||
todo!()
|
||||
fn discover_private_keys(&self) -> Result<<OpenPGP<P> as Format>::PrivateKeyData> {
|
||||
OpenPGP::<P>::discover_certs(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyDiscovery<OpenPGP> for &[Cert] {
|
||||
fn discover_public_keys(&self) -> Result<Vec<<OpenPGP as Format>::PublicKey>> {
|
||||
impl<P: PromptHandler> KeyDiscovery<OpenPGP<P>> for &[Cert] {
|
||||
fn discover_public_keys(&self) -> Result<Vec<<OpenPGP<P> as Format>::PublicKey>> {
|
||||
Ok(self.to_vec())
|
||||
}
|
||||
|
||||
fn discover_private_keys(&self) -> Result<<OpenPGP as Format>::PrivateKeyData> {
|
||||
fn discover_private_keys(&self) -> Result<<OpenPGP<P> as Format>::PrivateKeyData> {
|
||||
Ok(self.to_vec())
|
||||
}
|
||||
}
|
||||
|
@ -575,12 +593,12 @@ fn decode_metadata_v1(buf: &[u8]) -> Result<(u8, Cert, Vec<Cert>)> {
|
|||
|
||||
// NOTE: When using single-decryptor mechanism, use this method with `threshold = 1` to return a
|
||||
// single message.
|
||||
fn decrypt_with_manager(
|
||||
fn decrypt_with_manager<P: PromptHandler>(
|
||||
threshold: u8,
|
||||
messages: &mut HashMap<KeyID, EncryptedMessage>,
|
||||
certs: &[Cert],
|
||||
policy: &dyn Policy,
|
||||
manager: &mut SmartcardManager,
|
||||
manager: &mut SmartcardManager<P>,
|
||||
) -> Result<HashMap<KeyID, Vec<u8>>> {
|
||||
let mut decrypted_messages = HashMap::new();
|
||||
|
||||
|
@ -620,11 +638,11 @@ fn decrypt_with_manager(
|
|||
|
||||
// NOTE: When using single-decryptor mechanism, only a single key should be provided in Keyring to
|
||||
// decrypt messages with.
|
||||
fn decrypt_with_keyring(
|
||||
fn decrypt_with_keyring<P: PromptHandler>(
|
||||
messages: &mut HashMap<KeyID, EncryptedMessage>,
|
||||
certs: &[Cert],
|
||||
policy: &NullPolicy,
|
||||
keyring: &mut Keyring,
|
||||
keyring: &mut Keyring<P>,
|
||||
) -> Result<HashMap<KeyID, Vec<u8>>, Error> {
|
||||
let mut decrypted_messages = HashMap::new();
|
||||
|
||||
|
@ -654,11 +672,11 @@ fn decrypt_with_keyring(
|
|||
Ok(decrypted_messages)
|
||||
}
|
||||
|
||||
fn decrypt_metadata(
|
||||
fn decrypt_metadata<P: PromptHandler>(
|
||||
message: &EncryptedMessage,
|
||||
policy: &NullPolicy,
|
||||
keyring: &mut Keyring,
|
||||
manager: &mut SmartcardManager,
|
||||
keyring: &mut Keyring<P>,
|
||||
manager: &mut SmartcardManager<P>,
|
||||
) -> Result<Vec<u8>> {
|
||||
Ok(if keyring.is_empty() {
|
||||
manager.load_any_card()?;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use keyfork_prompt::{Error as PromptError, DefaultTerminal, default_terminal, PromptHandler};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use keyfork_prompt::{Error as PromptError, PromptHandler};
|
||||
|
||||
use super::openpgp::{
|
||||
self,
|
||||
|
@ -22,18 +24,18 @@ pub enum Error {
|
|||
|
||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
||||
pub struct Keyring {
|
||||
pub struct Keyring<P: PromptHandler> {
|
||||
full_certs: Vec<Cert>,
|
||||
root: Option<Cert>,
|
||||
pm: DefaultTerminal,
|
||||
pm: Arc<Mutex<P>>,
|
||||
}
|
||||
|
||||
impl Keyring {
|
||||
pub fn new(certs: impl AsRef<[Cert]>) -> Result<Self> {
|
||||
impl<P: PromptHandler> Keyring<P> {
|
||||
pub fn new(certs: impl AsRef<[Cert]>, p: Arc<Mutex<P>>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
full_certs: certs.as_ref().to_vec(),
|
||||
root: Default::default(),
|
||||
pm: default_terminal()?,
|
||||
pm: p,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -57,7 +59,7 @@ impl Keyring {
|
|||
}
|
||||
}
|
||||
|
||||
impl VerificationHelper for &mut Keyring {
|
||||
impl<P: PromptHandler> VerificationHelper for &mut Keyring<P> {
|
||||
fn get_certs(&mut self, ids: &[KeyHandle]) -> openpgp::Result<Vec<Cert>> {
|
||||
Ok(ids
|
||||
.iter()
|
||||
|
@ -93,7 +95,7 @@ impl VerificationHelper for &mut Keyring {
|
|||
}
|
||||
}
|
||||
|
||||
impl DecryptionHelper for &mut Keyring {
|
||||
impl<P: PromptHandler> DecryptionHelper for &mut Keyring<P> {
|
||||
fn decrypt<D>(
|
||||
&mut self,
|
||||
pkesks: &[PKESK],
|
||||
|
@ -137,6 +139,8 @@ impl DecryptionHelper for &mut Keyring {
|
|||
};
|
||||
let passphrase = self
|
||||
.pm
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_passphrase(&message)
|
||||
.context("Decryption passphrase")?;
|
||||
secret_key
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use keyfork_prompt::{
|
||||
default_terminal,
|
||||
validators::{PinValidator, Validator},
|
||||
DefaultTerminal, Error as PromptError, Message, PromptHandler,
|
||||
Error as PromptError, Message, PromptHandler,
|
||||
};
|
||||
|
||||
use super::openpgp::{
|
||||
|
@ -66,19 +68,19 @@ fn format_name(input: impl AsRef<str>) -> String {
|
|||
}
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct SmartcardManager {
|
||||
pub struct SmartcardManager<P: PromptHandler> {
|
||||
current_card: Option<Card<Open>>,
|
||||
root: Option<Cert>,
|
||||
pm: DefaultTerminal,
|
||||
pm: Arc<Mutex<P>>,
|
||||
pin_cache: HashMap<Fingerprint, String>,
|
||||
}
|
||||
|
||||
impl SmartcardManager {
|
||||
pub fn new() -> Result<Self> {
|
||||
impl<P: PromptHandler> SmartcardManager<P> {
|
||||
pub fn new(p: Arc<Mutex<P>>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
current_card: None,
|
||||
root: None,
|
||||
pm: default_terminal()?,
|
||||
pm: p,
|
||||
pin_cache: Default::default(),
|
||||
})
|
||||
}
|
||||
|
@ -96,9 +98,13 @@ impl SmartcardManager {
|
|||
if let Some(c) = PcscBackend::cards(None)?.next().transpose()? {
|
||||
break c;
|
||||
}
|
||||
self.pm.prompt_message(Message::Text(
|
||||
"No smart card was found. Please plug in a smart card and press enter".to_string(),
|
||||
))?;
|
||||
self.pm
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_message(Message::Text(
|
||||
"No smart card was found. Please plug in a smart card and press enter"
|
||||
.to_string(),
|
||||
))?;
|
||||
};
|
||||
let mut card = Card::<Open>::new(card_backend).map_err(Error::OpenSmartCard)?;
|
||||
let transaction = card.transaction().map_err(Error::Transaction)?;
|
||||
|
@ -152,16 +158,19 @@ impl SmartcardManager {
|
|||
}
|
||||
}
|
||||
|
||||
self.pm.prompt_message(Message::Text(
|
||||
"Please plug in a smart card and press enter".to_string(),
|
||||
))?;
|
||||
self.pm
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_message(Message::Text(
|
||||
"Please plug in a smart card and press enter".to_string(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl VerificationHelper for &mut SmartcardManager {
|
||||
impl<P: PromptHandler> VerificationHelper for &mut SmartcardManager<P> {
|
||||
fn get_certs(&mut self, ids: &[openpgp::KeyHandle]) -> openpgp::Result<Vec<Cert>> {
|
||||
#[allow(clippy::flat_map_option)]
|
||||
Ok(ids
|
||||
|
@ -194,7 +203,7 @@ impl VerificationHelper for &mut SmartcardManager {
|
|||
}
|
||||
}
|
||||
|
||||
impl DecryptionHelper for &mut SmartcardManager {
|
||||
impl<P: PromptHandler> DecryptionHelper for &mut SmartcardManager<P> {
|
||||
fn decrypt<D>(
|
||||
&mut self,
|
||||
pkesks: &[PKESK],
|
||||
|
@ -254,6 +263,8 @@ impl DecryptionHelper for &mut SmartcardManager {
|
|||
};
|
||||
let temp_pin = self
|
||||
.pm
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_validated_passphrase(&message, 3, &pin_validator)?;
|
||||
let verification_status = transaction.verify_user_pin(temp_pin.as_str().trim());
|
||||
match verification_status {
|
||||
|
@ -265,6 +276,8 @@ impl DecryptionHelper for &mut SmartcardManager {
|
|||
// NOTE: This should not be hit, because of the above validator.
|
||||
Err(CardError::CardStatus(StatusBytes::IncorrectParametersCommandDataField)) => {
|
||||
self.pm
|
||||
.lock()
|
||||
.unwrap()
|
||||
.prompt_message(Message::Text("Invalid PIN length entered.".to_string()))?;
|
||||
}
|
||||
Err(_) => {}
|
||||
|
|
|
@ -3,6 +3,7 @@ use clap::{Parser, Subcommand};
|
|||
use std::path::PathBuf;
|
||||
|
||||
use keyfork_mnemonic_util::{English, Mnemonic};
|
||||
use keyfork_prompt::{default_terminal, DefaultTerminal};
|
||||
use keyfork_shard::{remote_decrypt, Format};
|
||||
|
||||
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
||||
|
@ -34,10 +35,14 @@ impl RecoverSubcommands {
|
|||
} => {
|
||||
let content = std::fs::read_to_string(shard_file)?;
|
||||
if content.contains("BEGIN PGP MESSAGE") {
|
||||
let openpgp = keyfork_shard::openpgp::OpenPGP;
|
||||
let openpgp = keyfork_shard::openpgp::OpenPGP::<DefaultTerminal>::new();
|
||||
let prompt_handler = default_terminal()?;
|
||||
// TODO: remove .clone() by making handle() consume self
|
||||
let seed = openpgp
|
||||
.decrypt_all_shards_to_secret(key_discovery.as_deref(), content.as_bytes())?;
|
||||
let seed = openpgp.decrypt_all_shards_to_secret(
|
||||
key_discovery.as_deref(),
|
||||
content.as_bytes(),
|
||||
prompt_handler,
|
||||
)?;
|
||||
Ok(seed)
|
||||
} else {
|
||||
panic!("unknown format of shard file");
|
||||
|
@ -50,7 +55,6 @@ impl RecoverSubcommands {
|
|||
}
|
||||
RecoverSubcommands::Mnemonic {} => {
|
||||
use keyfork_prompt::{
|
||||
default_terminal,
|
||||
validators::{
|
||||
mnemonic::{MnemonicChoiceValidator, WordLength},
|
||||
Validator,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::Keyfork;
|
||||
use clap::{builder::PossibleValue, Parser, Subcommand, ValueEnum};
|
||||
use keyfork_prompt::{default_terminal, DefaultTerminal};
|
||||
use keyfork_shard::Format as _;
|
||||
use std::{
|
||||
io::{stdin, stdout, Read, Write},
|
||||
|
@ -63,7 +64,7 @@ impl ShardExec for OpenPGP {
|
|||
secret: &[u8],
|
||||
output: &mut (impl Write + Send + Sync),
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let opgp = keyfork_shard::openpgp::OpenPGP;
|
||||
let opgp = keyfork_shard::openpgp::OpenPGP::<DefaultTerminal>::new();
|
||||
opgp.shard_and_encrypt(threshold, max, secret, key_discovery, output)
|
||||
}
|
||||
|
||||
|
@ -72,10 +73,10 @@ impl ShardExec for OpenPGP {
|
|||
key_discovery: Option<&Path>,
|
||||
input: impl Read + Send + Sync,
|
||||
output: &mut impl Write,
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
{
|
||||
let openpgp = keyfork_shard::openpgp::OpenPGP;
|
||||
let bytes = openpgp.decrypt_all_shards_to_secret(key_discovery, input)?;
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let openpgp = keyfork_shard::openpgp::OpenPGP::<DefaultTerminal>::new();
|
||||
let prompt = default_terminal()?;
|
||||
let bytes = openpgp.decrypt_all_shards_to_secret(key_discovery, input, prompt)?;
|
||||
write!(output, "{}", smex::encode(bytes))?;
|
||||
|
||||
Ok(())
|
||||
|
@ -85,10 +86,10 @@ impl ShardExec for OpenPGP {
|
|||
&self,
|
||||
key_discovery: Option<&Path>,
|
||||
input: impl Read + Send + Sync,
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
{
|
||||
let openpgp = keyfork_shard::openpgp::OpenPGP;
|
||||
openpgp.decrypt_one_shard_for_transport(key_discovery, input)?;
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let openpgp = keyfork_shard::openpgp::OpenPGP::<DefaultTerminal>::new();
|
||||
let prompt = default_terminal()?;
|
||||
openpgp.decrypt_one_shard_for_transport(key_discovery, input, prompt)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use keyfork_derive_openpgp::{
|
|||
use keyfork_derive_util::{DerivationIndex, DerivationPath};
|
||||
use keyfork_prompt::{
|
||||
validators::{PinValidator, Validator},
|
||||
Message, PromptHandler, Terminal,
|
||||
Message, PromptHandler, DefaultTerminal, default_terminal
|
||||
};
|
||||
|
||||
use keyfork_shard::{Format, openpgp::OpenPGP};
|
||||
|
@ -105,7 +105,7 @@ fn generate_shard_secret(
|
|||
output_file: &Option<PathBuf>,
|
||||
) -> Result<()> {
|
||||
let seed = keyfork_entropy::generate_entropy_of_const_size::<{256 / 8}>()?;
|
||||
let mut pm = Terminal::new(std::io::stdin(), std::io::stderr())?;
|
||||
let mut pm = default_terminal()?;
|
||||
let mut certs = vec![];
|
||||
let mut seen_cards: HashSet<String> = HashSet::new();
|
||||
let stdout = std::io::stdout();
|
||||
|
@ -165,7 +165,7 @@ fn generate_shard_secret(
|
|||
certs.push(cert);
|
||||
}
|
||||
|
||||
let opgp = OpenPGP;
|
||||
let opgp = OpenPGP::<DefaultTerminal>::new();
|
||||
|
||||
if let Some(output_file) = output_file {
|
||||
let output = File::create(output_file)?;
|
||||
|
|
Loading…
Reference in New Issue