keyfork wizard generate-shard-secret: allow exporting certificates and cross-sign generated keys
This commit is contained in:
parent
c95ed0b729
commit
8756c3d233
|
@ -9,9 +9,10 @@ use keyfork_derive_openpgp::{
|
||||||
openpgp::{
|
openpgp::{
|
||||||
self,
|
self,
|
||||||
armor::{Kind, Writer},
|
armor::{Kind, Writer},
|
||||||
packet::UserID,
|
packet::{UserID, signature::SignatureBuilder},
|
||||||
serialize::Marshal,
|
serialize::Marshal,
|
||||||
types::KeyFlags,
|
types::{SignatureType, KeyFlags},
|
||||||
|
policy::StandardPolicy,
|
||||||
Cert,
|
Cert,
|
||||||
},
|
},
|
||||||
XPrv,
|
XPrv,
|
||||||
|
@ -20,8 +21,7 @@ use keyfork_derive_path_data::paths;
|
||||||
use keyfork_derive_util::DerivationIndex;
|
use keyfork_derive_util::DerivationIndex;
|
||||||
use keyfork_mnemonic::Mnemonic;
|
use keyfork_mnemonic::Mnemonic;
|
||||||
use keyfork_prompt::{
|
use keyfork_prompt::{
|
||||||
default_handler,
|
default_handler, prompt_validated_passphrase,
|
||||||
prompt_validated_passphrase,
|
|
||||||
validators::{SecurePinValidator, Validator},
|
validators::{SecurePinValidator, Validator},
|
||||||
Message,
|
Message,
|
||||||
};
|
};
|
||||||
|
@ -133,6 +133,10 @@ pub struct GenerateShardSecret {
|
||||||
/// The file to write the generated shard file to.
|
/// The file to write the generated shard file to.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
output: Option<PathBuf>,
|
output: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// The file to write generated certificates to.
|
||||||
|
#[arg(long)]
|
||||||
|
cert_output: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a 256 bit secret and shard the secret to previously known OpenPGP certificates,
|
/// Create a 256 bit secret and shard the secret to previously known OpenPGP certificates,
|
||||||
|
@ -172,6 +176,41 @@ impl WizardSubcommands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cross_sign_certs(certs: &mut [Cert]) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let policy = StandardPolicy::new();
|
||||||
|
for signing_cert in certs.to_vec() {
|
||||||
|
let mut certify_key = signing_cert
|
||||||
|
.with_policy(&policy, None)?
|
||||||
|
.keys()
|
||||||
|
.unencrypted_secret()
|
||||||
|
.for_certification()
|
||||||
|
.next()
|
||||||
|
.expect("certify key unusable/not found")
|
||||||
|
.key()
|
||||||
|
.clone()
|
||||||
|
.into_keypair()?;
|
||||||
|
for signable_cert in certs.iter_mut() {
|
||||||
|
let sb = SignatureBuilder::new(SignatureType::GenericCertification);
|
||||||
|
let userid = signable_cert
|
||||||
|
.userids()
|
||||||
|
.next()
|
||||||
|
.expect("a signable user ID is necessary to create web of trust");
|
||||||
|
let signature = sb.sign_userid_binding(
|
||||||
|
&mut certify_key,
|
||||||
|
signable_cert.primary_key().key(),
|
||||||
|
&*userid,
|
||||||
|
)?;
|
||||||
|
let changed;
|
||||||
|
(*signable_cert, changed) = signable_cert.clone().insert_packets2(signature)?;
|
||||||
|
assert!(
|
||||||
|
changed,
|
||||||
|
"OpenPGP certificate was unchanged after inserting packets"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
impl GenerateShardSecret {
|
impl GenerateShardSecret {
|
||||||
fn handle(&self) -> Result<()> {
|
fn handle(&self) -> Result<()> {
|
||||||
let seed = keyfork_entropy::generate_entropy_of_const_size::<{ 256 / 8 }>()?;
|
let seed = keyfork_entropy::generate_entropy_of_const_size::<{ 256 / 8 }>()?;
|
||||||
|
@ -237,6 +276,8 @@ impl GenerateShardSecret {
|
||||||
certs.push(cert);
|
certs.push(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cross_sign_certs(&mut certs)?;
|
||||||
|
|
||||||
let opgp = OpenPGP;
|
let opgp = OpenPGP;
|
||||||
|
|
||||||
if let Some(output_file) = self.output.as_ref() {
|
if let Some(output_file) = self.output.as_ref() {
|
||||||
|
@ -251,6 +292,16 @@ impl GenerateShardSecret {
|
||||||
std::io::stdout(),
|
std::io::stdout(),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(cert_output_file) = self.cert_output.as_ref() {
|
||||||
|
let output = File::create(cert_output_file)?;
|
||||||
|
let mut writer = Writer::new(output, Kind::PublicKey)?;
|
||||||
|
for cert in certs {
|
||||||
|
cert.serialize(&mut writer)?;
|
||||||
|
}
|
||||||
|
writer.finalize()?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue