diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2022-02-22 12:28:27 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2022-02-22 14:12:27 +0100 |
commit | 95567183719ef14ecd098ac8be9714ef2c4a93a5 (patch) | |
tree | 913ce89ed02ad827be086625041b0480ff6b214d | |
parent | 347416175320c0b93ef71debece5b341d4e36fd5 (diff) |
openpgp: Support v5 fingerprints.
- Supporting v5 fingerprints is important so that we can process
signature subpackets containing them, even if we don't yet support
any v5 formats. Consider being part of a group of recipients
where one of the recipients has a v5 key: then, the intended
recipient fingerprint subpacket contains a v5 fingerprint for that
v5 recipient. See also #820.
-rw-r--r-- | openpgp/NEWS | 1 | ||||
-rw-r--r-- | openpgp/src/fingerprint.rs | 40 | ||||
-rw-r--r-- | openpgp/src/keyid.rs | 4 | ||||
-rw-r--r-- | openpgp/src/serialize.rs | 8 |
4 files changed, 49 insertions, 4 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS index 22b822d9..450ce629 100644 --- a/openpgp/NEWS +++ b/openpgp/NEWS @@ -5,6 +5,7 @@ * Changes in 1.8.0 ** New functionality - crypto::Signer::acceptable_hashes + - Fingerprint::V5 * Changes in 1.7.0 ** Notable fixes - sequoia-openpgp can now be compiled to WASM. diff --git a/openpgp/src/fingerprint.rs b/openpgp/src/fingerprint.rs index eb411923..43ec22d0 100644 --- a/openpgp/src/fingerprint.rs +++ b/openpgp/src/fingerprint.rs @@ -49,6 +49,10 @@ use quickcheck::{Arbitrary, Gen}; pub enum Fingerprint { /// A 20 byte SHA-1 hash of the public key packet as defined in the RFC. V4([u8;20]), + + /// A v5 OpenPGP fingerprint. + V5([u8; 32]), + /// Used for holding fingerprint data that is not a V4 fingerprint, e.g. a /// V3 fingerprint (deprecated) or otherwise wrong-length data. Invalid(Box<[u8]>), @@ -116,6 +120,10 @@ impl Fingerprint { let mut fp : [u8; 20] = Default::default(); fp.copy_from_slice(raw); Fingerprint::V4(fp) + } else if raw.len() == 32 { + let mut fp: [u8; 32] = Default::default(); + fp.copy_from_slice(raw); + Fingerprint::V5(fp) } else { Fingerprint::Invalid(raw.to_vec().into_boxed_slice()) } @@ -142,6 +150,7 @@ impl Fingerprint { pub fn as_bytes(&self) -> &[u8] { match self { Fingerprint::V4(ref fp) => fp, + Fingerprint::V5(fp) => fp, Fingerprint::Invalid(ref fp) => fp, } } @@ -241,6 +250,9 @@ impl Fingerprint { // Since we have no idea how to format an invalid fingerprint, // just format it like a V4 fingerprint and hope for the best. + // XXX: v5 fingerprints have no human-readable formatting by + // choice. + let mut output = Vec::with_capacity( // Each byte results in to hex characters. raw.len() * 2 @@ -343,9 +355,15 @@ impl Fingerprint { #[cfg(test)] impl Arbitrary for Fingerprint { fn arbitrary(g: &mut Gen) -> Self { - let mut fp = [0; 20]; - fp.iter_mut().for_each(|p| *p = Arbitrary::arbitrary(g)); - Fingerprint::V4(fp) + if Arbitrary::arbitrary(g) { + let mut fp = [0; 20]; + fp.iter_mut().for_each(|p| *p = Arbitrary::arbitrary(g)); + Fingerprint::V4(fp) + } else { + let mut fp = [0; 32]; + fp.iter_mut().for_each(|p| *p = Arbitrary::arbitrary(g)); + Fingerprint::V5(fp) + } } } @@ -354,10 +372,24 @@ mod tests { use super::*; #[test] - fn hex_formatting() { + fn v4_hex_formatting() { let fp = "0123 4567 89AB CDEF 0123 4567 89AB CDEF 0123 4567" .parse::<Fingerprint>().unwrap(); + assert!(matches!(&fp, Fingerprint::V4(_))); assert_eq!(format!("{:X}", fp), "0123456789ABCDEF0123456789ABCDEF01234567"); assert_eq!(format!("{:x}", fp), "0123456789abcdef0123456789abcdef01234567"); } + + #[test] + fn v5_hex_formatting() -> crate::Result<()> { + let fp = "0123 4567 89AB CDEF 0123 4567 89AB CDEF \ + 0123 4567 89AB CDEF 0123 4567 89AB CDEF" + .parse::<Fingerprint>()?; + assert!(matches!(&fp, Fingerprint::V5(_))); + assert_eq!(format!("{:X}", fp), "0123456789ABCDEF0123456789ABCDEF\ + 0123456789ABCDEF0123456789ABCDEF"); + assert_eq!(format!("{:x}", fp), "0123456789abcdef0123456789abcdef\ + 0123456789abcdef0123456789abcdef"); + Ok(()) + } } diff --git a/openpgp/src/keyid.rs b/openpgp/src/keyid.rs index b4689488..e93c603d 100644 --- a/openpgp/src/keyid.rs +++ b/openpgp/src/keyid.rs @@ -140,6 +140,8 @@ impl From<&Fingerprint> for KeyID { match fp { Fingerprint::V4(fp) => KeyID::from_bytes(&fp[fp.len() - 8..]), + Fingerprint::V5(fp) => + KeyID::Invalid(fp.iter().cloned().collect()), Fingerprint::Invalid(fp) => { KeyID::Invalid(fp.clone()) } @@ -152,6 +154,8 @@ impl From<Fingerprint> for KeyID { match fp { Fingerprint::V4(fp) => KeyID::from_bytes(&fp[fp.len() - 8..]), + Fingerprint::V5(fp) => + KeyID::Invalid(fp.into()), Fingerprint::Invalid(fp) => { KeyID::Invalid(fp) } diff --git a/openpgp/src/serialize.rs b/openpgp/src/serialize.rs index c953bcb2..dea98dc1 100644 --- a/openpgp/src/serialize.rs +++ b/openpgp/src/serialize.rs @@ -1457,6 +1457,10 @@ impl Marshal for SubpacketValue { o.write_all(&[4])?; o.write_all(fp.as_bytes())?; }, + Fingerprint::V5(_) => { + o.write_all(&[5])?; + o.write_all(fp.as_bytes())?; + }, _ => return Err(Error::InvalidArgument( "Unknown kind of fingerprint".into()).into()), } @@ -1469,6 +1473,10 @@ impl Marshal for SubpacketValue { o.write_all(&[4])?; o.write_all(fp.as_bytes())?; }, + Fingerprint::V5(_) => { + o.write_all(&[5])?; + o.write_all(fp.as_bytes())?; + }, _ => return Err(Error::InvalidArgument( "Unknown kind of fingerprint".into()).into()), } |