keyfork wizard generate-shard-secret: cache all seen cards instead of last seen card

This commit is contained in:
Ryan Heywood 2024-01-08 13:13:08 -05:00
parent 8792ef69e1
commit 203d190955
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
1 changed files with 11 additions and 13 deletions

View File

@ -1,13 +1,9 @@
use super::Keyfork; use super::Keyfork;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use std::collections::HashSet;
use card_backend_pcsc::PcscBackend; use card_backend_pcsc::PcscBackend;
use openpgp_card::card_do::ApplicationIdentifier; use openpgp_card_sequoia::{state::Open, types::KeyType, Card};
use openpgp_card_sequoia::{
state::Open,
types::KeyType,
Card,
};
use keyfork_derive_openpgp::openpgp::{self, packet::UserID, types::KeyFlags, Cert}; use keyfork_derive_openpgp::openpgp::{self, packet::UserID, types::KeyFlags, Cert};
use keyfork_derive_util::{ use keyfork_derive_util::{
@ -49,7 +45,7 @@ fn derive_key(seed: &[u8], index: u8) -> Result<Cert> {
// TODO: extract into crate // TODO: extract into crate
/// Factory reset the current card so long as it does not match the last-used backend. /// Factory reset the current card so long as it does not match the last-used backend.
fn factory_reset_current_card( fn factory_reset_current_card(
previous_backend: &mut Option<ApplicationIdentifier>, seen_cards: &mut HashSet<String>,
cert: &Cert, cert: &Cert,
) -> Result<()> { ) -> Result<()> {
let policy = openpgp::policy::NullPolicy::new(); let policy = openpgp::policy::NullPolicy::new();
@ -75,12 +71,12 @@ fn factory_reset_current_card(
if let Some(current_backend) = PcscBackend::cards(None)?.next().transpose()? { if let Some(current_backend) = PcscBackend::cards(None)?.next().transpose()? {
let mut card = Card::<Open>::new(current_backend)?; let mut card = Card::<Open>::new(current_backend)?;
let mut transaction = card.transaction()?; let mut transaction = card.transaction()?;
let application_identifier = transaction.application_identifier()?; let application_identifier = transaction.application_identifier()?.ident();
if previous_backend.is_some_and(|pb| pb == application_identifier) { if seen_cards.contains(&application_identifier) {
// we were given the same card, error // we were given the same card, error
panic!("Previously used card {application_identifier} was reused"); panic!("Previously used card {application_identifier} was reused");
} else { } else {
let _ = previous_backend.insert(application_identifier); seen_cards.insert(application_identifier);
} }
transaction.factory_reset()?; transaction.factory_reset()?;
let mut admin = transaction.to_admin_card("12345678")?; let mut admin = transaction.to_admin_card("12345678")?;
@ -98,15 +94,17 @@ fn generate_shard_secret(threshold: u8, max: u8, keys_per_shard: u8) -> Result<(
let seed = keyfork_plumbing::generate_entropy_of_size(256 / 8)?; let seed = keyfork_plumbing::generate_entropy_of_size(256 / 8)?;
let mut pm = PromptManager::new(std::io::stdin(), std::io::stderr())?; let mut pm = PromptManager::new(std::io::stdin(), std::io::stderr())?;
let mut certs = vec![]; let mut certs = vec![];
let mut last_card = None; let mut seen_cards: HashSet<String> = HashSet::new();
for index in 0..max { for index in 0..max {
let cert = derive_key(&seed, index)?; let cert = derive_key(&seed, index)?;
for i in 0..keys_per_shard { for i in 0..keys_per_shard {
pm.prompt_message(&Message::Text(format!( pm.prompt_message(&Message::Text(format!(
"Please insert user {index} key {i}" "Please insert key #{} for user #{}",
i + 1,
index + 1,
)))?; )))?;
factory_reset_current_card(&mut last_card, &cert)?; factory_reset_current_card(&mut seen_cards, &cert)?;
} }
certs.push(cert); certs.push(cert);
} }