keyfork wizard generate-shard-secret: write to given output file
This commit is contained in:
parent
4782a15af9
commit
33aeae1177
|
@ -145,7 +145,7 @@ On an airgapped system, run the following command to generate a file containing
|
|||
encrypted shards of a generated seed:
|
||||
|
||||
```sh
|
||||
keyfork wizard generate-shard-secret --threshold $N --max $M --keys-per-shard $I > shards.pgp
|
||||
keyfork wizard generate-shard-secret --threshold $N --max $M --keys-per-shard $I --output shards.pgp
|
||||
```
|
||||
|
||||
Once generated, the shards file can be safely stored in any location, as the
|
||||
|
|
|
@ -20,6 +20,7 @@ It is recommended to use smart cards dedicated to the purpose of seed recovery.
|
|||
secret.
|
||||
* `max`: The maximum amount of shardholders.
|
||||
* `keys-per-shard`: The amount of smart cardsz to provision per-shardholder.
|
||||
* `output`: The file to write the generated shard to.
|
||||
|
||||
### Prompts
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::Keyfork;
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::{collections::HashSet, io::IsTerminal};
|
||||
use std::{collections::HashSet, io::IsTerminal, path::PathBuf, fs::OpenOptions};
|
||||
|
||||
use card_backend_pcsc::PcscBackend;
|
||||
use openpgp_card_sequoia::{state::Open, types::KeyType, Card};
|
||||
|
@ -12,7 +12,7 @@ use keyfork_derive_util::{
|
|||
};
|
||||
use keyfork_prompt::{
|
||||
validators::{PinValidator, Validator},
|
||||
Message, Terminal, PromptHandler,
|
||||
Message, PromptHandler, Terminal,
|
||||
};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
|
@ -100,16 +100,18 @@ fn factory_reset_current_card(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_shard_secret(threshold: u8, max: u8, keys_per_shard: u8) -> Result<()> {
|
||||
fn generate_shard_secret(threshold: u8, max: u8, keys_per_shard: u8, output_file: &Option<PathBuf>) -> Result<()> {
|
||||
let seed = keyfork_entropy::generate_entropy_of_size(256 / 8)?;
|
||||
let mut pm = Terminal::new(std::io::stdin(), std::io::stderr())?;
|
||||
let mut certs = vec![];
|
||||
let mut seen_cards: HashSet<String> = HashSet::new();
|
||||
let stdout = std::io::stdout();
|
||||
assert!(
|
||||
!stdout.is_terminal(),
|
||||
"not printing shard to terminal, redirect output"
|
||||
);
|
||||
if output_file.is_none() {
|
||||
assert!(
|
||||
!stdout.is_terminal(),
|
||||
"not printing shard to terminal, redirect output"
|
||||
);
|
||||
}
|
||||
|
||||
let user_pin_validator = PinValidator {
|
||||
min_length: Some(6),
|
||||
|
@ -145,7 +147,12 @@ fn generate_shard_secret(threshold: u8, max: u8, keys_per_shard: u8) -> Result<(
|
|||
certs.push(cert);
|
||||
}
|
||||
|
||||
keyfork_shard::openpgp::split(threshold, certs, &seed, std::io::stdout())?;
|
||||
if let Some(output_file) = output_file {
|
||||
let output = OpenOptions::new().write(true).open(output_file)?;
|
||||
keyfork_shard::openpgp::split(threshold, certs, &seed, output)?;
|
||||
} else {
|
||||
keyfork_shard::openpgp::split(threshold, certs, &seed, std::io::stdout())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -168,6 +175,10 @@ pub enum WizardSubcommands {
|
|||
/// The amount of smart cards to provision per-shard.
|
||||
#[arg(long, default_value = "1")]
|
||||
keys_per_shard: u8,
|
||||
|
||||
/// The file to write the generated shard file to.
|
||||
#[arg(long)]
|
||||
output: Option<PathBuf>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -178,7 +189,8 @@ impl WizardSubcommands {
|
|||
threshold,
|
||||
max,
|
||||
keys_per_shard,
|
||||
} => generate_shard_secret(*threshold, *max, *keys_per_shard),
|
||||
output,
|
||||
} => generate_shard_secret(*threshold, *max, *keys_per_shard, output),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue