summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2022-02-22 12:28:27 +0100
committerJustus Winter <justus@sequoia-pgp.org>2022-02-22 14:12:27 +0100
commit95567183719ef14ecd098ac8be9714ef2c4a93a5 (patch)
tree913ce89ed02ad827be086625041b0480ff6b214d
parent347416175320c0b93ef71debece5b341d4e36fd5 (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/NEWS1
-rw-r--r--openpgp/src/fingerprint.rs40
-rw-r--r--openpgp/src/keyid.rs4
-rw-r--r--openpgp/src/serialize.rs8
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()),
}