keyfork: impl `shard transport`
This commit is contained in:
parent
d548276bc3
commit
6fc2c47391
|
@ -1,10 +1,12 @@
|
|||
use super::Keyfork;
|
||||
use clap::{builder::PossibleValue, Parser, Subcommand, ValueEnum};
|
||||
use std::{
|
||||
io::{stdin, stdout, BufRead, BufReader, Read, Write},
|
||||
io::{stdin, stdout, Read, Write},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
const COULD_NOT_DETERMINE_FORMAT: &str = "could not determine format, try including --format";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Format {
|
||||
OpenPGP(OpenPGP),
|
||||
|
@ -42,6 +44,14 @@ trait ShardExec {
|
|||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where
|
||||
T: AsRef<Path>;
|
||||
|
||||
fn decrypt<T>(
|
||||
&self,
|
||||
key_discovery: Option<T>,
|
||||
input: impl Read + Send + Sync,
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where
|
||||
T: AsRef<Path>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -99,6 +109,32 @@ impl ShardExec for OpenPGP {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn decrypt<T>(
|
||||
&self,
|
||||
key_discovery: Option<T>,
|
||||
input: impl Read + Send + Sync,
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let certs = key_discovery
|
||||
.map(|kd| keyfork_shard::openpgp::discover_certs(kd.as_ref()))
|
||||
.transpose()?
|
||||
.unwrap_or(vec![]);
|
||||
|
||||
let mut encrypted_messages = keyfork_shard::openpgp::parse_messages(input)?;
|
||||
let encrypted_metadata = encrypted_messages
|
||||
.pop_front()
|
||||
.expect("any pgp encrypted message");
|
||||
|
||||
keyfork_shard::openpgp::decrypt(
|
||||
&certs,
|
||||
&encrypted_metadata,
|
||||
encrypted_messages.make_contiguous(),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -125,6 +161,13 @@ pub enum ShardSubcommands {
|
|||
key_discovery: PathBuf,
|
||||
},
|
||||
|
||||
/// Decrypt a single share and re-encrypt it to an ephemeral symmetric key using mnemonic-based
|
||||
/// prompts. The mnemonics can be sent over insecure channels.
|
||||
Transport {
|
||||
/// The path to discover private keys from.
|
||||
key_discovery: Option<PathBuf>,
|
||||
},
|
||||
|
||||
/// Combine multiple encrypted shares into a hex-encoded secret, printed to stdout.
|
||||
///
|
||||
/// This command only accepts input from `keyfork shard split`, and is dependent on the format
|
||||
|
@ -143,8 +186,15 @@ impl ShardSubcommands {
|
|||
shard: &Shard,
|
||||
_keyfork: &Keyfork,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let stdin = stdin();
|
||||
let mut stdin = stdin();
|
||||
let mut stdout = stdout();
|
||||
let mut input = String::new();
|
||||
stdin.read_to_string(&mut input)?;
|
||||
let mut format = shard.format.clone();
|
||||
// bang sandwich macro fun
|
||||
if input.contains("BEGIN PGP MESSAGE") && !matches!(self, ShardSubcommands::Split { .. }) {
|
||||
let _ = format.insert(Format::OpenPGP(OpenPGP));
|
||||
}
|
||||
match self {
|
||||
ShardSubcommands::Split {
|
||||
threshold,
|
||||
|
@ -152,30 +202,30 @@ impl ShardSubcommands {
|
|||
key_discovery,
|
||||
} => {
|
||||
assert!(threshold <= max, "threshold {threshold} <= max {max}");
|
||||
let mut input = BufReader::new(stdin);
|
||||
let mut hex_line = String::new();
|
||||
input.read_line(&mut hex_line)?;
|
||||
let secret = smex::decode(hex_line.trim())?;
|
||||
match &shard.format {
|
||||
let secret = smex::decode(input.trim())?;
|
||||
match format {
|
||||
Some(Format::OpenPGP(o)) => {
|
||||
o.split(*threshold, *max, key_discovery, &secret, &mut stdout)
|
||||
}
|
||||
Some(Format::P256(_p)) => {
|
||||
todo!()
|
||||
}
|
||||
None => panic!("--format was not given"),
|
||||
None => panic!("{COULD_NOT_DETERMINE_FORMAT}"),
|
||||
}
|
||||
}
|
||||
ShardSubcommands::Combine {
|
||||
key_discovery,
|
||||
} => match &shard.format {
|
||||
ShardSubcommands::Transport { key_discovery } => match format {
|
||||
Some(Format::OpenPGP(o)) => o.decrypt(key_discovery.as_ref(), input.as_bytes()),
|
||||
Some(Format::P256(_p)) => todo!(),
|
||||
None => panic!("{COULD_NOT_DETERMINE_FORMAT}"),
|
||||
},
|
||||
ShardSubcommands::Combine { key_discovery } => match format {
|
||||
Some(Format::OpenPGP(o)) => {
|
||||
o.combine(key_discovery.as_ref(), stdin, &mut stdout)
|
||||
o.combine(key_discovery.as_ref(), input.as_bytes(), &mut stdout)
|
||||
}
|
||||
Some(Format::P256(_p)) => {
|
||||
todo!()
|
||||
}
|
||||
None => panic!("--format was not given"),
|
||||
None => panic!("{COULD_NOT_DETERMINE_FORMAT}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue