diff --git a/keyfork-shard/src/openpgp.rs b/keyfork-shard/src/openpgp.rs index 787a745..defa06c 100644 --- a/keyfork-shard/src/openpgp.rs +++ b/keyfork-shard/src/openpgp.rs @@ -34,6 +34,13 @@ use keyring::Keyring; mod smartcard; use smartcard::SmartcardManager; +/// Shard metadata verson 1: +/// 1 byte: Version +/// 1 byte: Threshold +/// OpenPGP Packet Pile of Certs +const SHARD_METADATA_VERSION: u8 = 1; +const SHARD_METADATA_OFFSET: usize = 2; + #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Error with creating Share: {0}")] @@ -221,7 +228,18 @@ pub fn combine( metadata.decrypt_with(&policy, &mut keyring)? }; - let mut cert_parser = CertParser::from_bytes(&content).map_err(Error::Sequoia)?; + assert_eq!( + SHARD_METADATA_VERSION, content[0], + "incompatible metadata version" + ); + // TODO: this should be removed along with the `threshold` option. + assert_eq!( + threshold, content[1], + "threshold does not match stored threshold" + ); + + let mut cert_parser = + CertParser::from_bytes(&content[SHARD_METADATA_OFFSET..]).map_err(Error::Sequoia)?; let root_cert = match cert_parser.next() { Some(Ok(c)) => c, Some(Err(e)) => panic!("Could not find root (first) certificate: {e}"), @@ -402,7 +420,7 @@ pub fn split(threshold: u8, certs: Vec, secret: &[u8], output: impl Write) messages.push(message_output); } - let mut pp = vec![]; + let mut pp = vec![SHARD_METADATA_VERSION, threshold]; // store derived cert to verify provided shares derived_cert.serialize(&mut pp).map_err(Error::Sequoia)?; for recipient in &total_recipients { @@ -410,7 +428,7 @@ pub fn split(threshold: u8, certs: Vec, secret: &[u8], output: impl Write) } // verify packet pile - for (packet_cert, cert) in openpgp::cert::CertParser::from_bytes(&pp) + for (packet_cert, cert) in openpgp::cert::CertParser::from_bytes(&pp[2..]) .map_err(Error::Sequoia)? .skip(1) .zip(total_recipients.iter())