From 7a80799115b3106ced3dc4ad55666f5a38472305 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 19 Oct 2023 20:10:02 -0500 Subject: [PATCH] keyfork-shard: derive cert from combined secret to ensure data integrity --- keyfork-shard/src/openpgp.rs | 29 ++++++++++++++++++++++++++-- keyfork-shard/src/openpgp/keyring.rs | 4 ++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/keyfork-shard/src/openpgp.rs b/keyfork-shard/src/openpgp.rs index 76c0b4c..d1619a6 100644 --- a/keyfork-shard/src/openpgp.rs +++ b/keyfork-shard/src/openpgp.rs @@ -20,7 +20,7 @@ use openpgp::{ Marshal, }, types::KeyFlags, - KeyID, PacketPile + KeyID, PacketPile, }; pub use sequoia_openpgp as openpgp; use sharks::{Share, Sharks}; @@ -106,7 +106,7 @@ pub fn discover_certs(path: impl AsRef) -> Result> { } } -pub fn parse_messages(reader: impl Read + Send + Sync) -> Result >{ +pub fn parse_messages(reader: impl Read + Send + Sync) -> Result> { let mut pkesks = Vec::new(); let mut encrypted_messages = VecDeque::new(); @@ -234,6 +234,31 @@ pub fn combine( .map_err(|e| WrappedError(e.to_string()))?; let secret = Sharks(threshold).recover(&shares)?; + let userid = UserID::from("keyfork-sss"); + let kdr = DerivationRequest::new( + DerivationAlgorithm::Ed25519, + &DerivationPath::from_str("m/7366512'/0'")?, + ) + .derive_with_master_seed(secret.to_vec())?; + let derived_cert = keyfork_derive_openpgp::derive( + kdr, + &[KeyFlags::empty().set_certification().set_signing()], + userid, + )?; + + // NOTE: Signatures on certs will be different. Compare fingerprints instead. + if Some(derived_cert.fingerprint()) != keyring.root_cert().map(Cert::fingerprint) { + return Err(WrappedError(format!( + "Derived {} != expected {}", + derived_cert.fingerprint(), + keyring + .root_cert() + .expect("cert was previously set") + .fingerprint() + )) + .into()); + } + output.write_all(smex::encode(&secret).as_bytes())?; Ok(()) diff --git a/keyfork-shard/src/openpgp/keyring.rs b/keyfork-shard/src/openpgp/keyring.rs index 9610c3b..a79fb95 100644 --- a/keyfork-shard/src/openpgp/keyring.rs +++ b/keyfork-shard/src/openpgp/keyring.rs @@ -47,6 +47,10 @@ impl Keyring { cert } + pub fn root_cert(&self) -> Option<&Cert> { + self.root.as_ref() + } + pub fn get_cert_for_primary_keyid<'a>(&'a self, keyid: &KeyID) -> Option<&'a Cert> { self.full_certs.iter().find(|cert| &cert.keyid() == keyid) }