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:
|
encrypted shards of a generated seed:
|
||||||
|
|
||||||
```sh
|
```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
|
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.
|
secret.
|
||||||
* `max`: The maximum amount of shardholders.
|
* `max`: The maximum amount of shardholders.
|
||||||
* `keys-per-shard`: The amount of smart cardsz to provision per-shardholder.
|
* `keys-per-shard`: The amount of smart cardsz to provision per-shardholder.
|
||||||
|
* `output`: The file to write the generated shard to.
|
||||||
|
|
||||||
### Prompts
|
### Prompts
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::Keyfork;
|
use super::Keyfork;
|
||||||
use clap::{Parser, Subcommand};
|
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 card_backend_pcsc::PcscBackend;
|
||||||
use openpgp_card_sequoia::{state::Open, types::KeyType, Card};
|
use openpgp_card_sequoia::{state::Open, types::KeyType, Card};
|
||||||
|
@ -12,7 +12,7 @@ use keyfork_derive_util::{
|
||||||
};
|
};
|
||||||
use keyfork_prompt::{
|
use keyfork_prompt::{
|
||||||
validators::{PinValidator, Validator},
|
validators::{PinValidator, Validator},
|
||||||
Message, Terminal, PromptHandler,
|
Message, PromptHandler, Terminal,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
@ -100,16 +100,18 @@ fn factory_reset_current_card(
|
||||||
Ok(())
|
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 seed = keyfork_entropy::generate_entropy_of_size(256 / 8)?;
|
||||||
let mut pm = Terminal::new(std::io::stdin(), std::io::stderr())?;
|
let mut pm = Terminal::new(std::io::stdin(), std::io::stderr())?;
|
||||||
let mut certs = vec![];
|
let mut certs = vec![];
|
||||||
let mut seen_cards: HashSet<String> = HashSet::new();
|
let mut seen_cards: HashSet<String> = HashSet::new();
|
||||||
let stdout = std::io::stdout();
|
let stdout = std::io::stdout();
|
||||||
assert!(
|
if output_file.is_none() {
|
||||||
!stdout.is_terminal(),
|
assert!(
|
||||||
"not printing shard to terminal, redirect output"
|
!stdout.is_terminal(),
|
||||||
);
|
"not printing shard to terminal, redirect output"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let user_pin_validator = PinValidator {
|
let user_pin_validator = PinValidator {
|
||||||
min_length: Some(6),
|
min_length: Some(6),
|
||||||
|
@ -145,7 +147,12 @@ fn generate_shard_secret(threshold: u8, max: u8, keys_per_shard: u8) -> Result<(
|
||||||
certs.push(cert);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +175,10 @@ pub enum WizardSubcommands {
|
||||||
/// The amount of smart cards to provision per-shard.
|
/// The amount of smart cards to provision per-shard.
|
||||||
#[arg(long, default_value = "1")]
|
#[arg(long, default_value = "1")]
|
||||||
keys_per_shard: u8,
|
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,
|
threshold,
|
||||||
max,
|
max,
|
||||||
keys_per_shard,
|
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