diff options
-rw-r--r-- | guide/src/chapter_03.md | 2 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/signature.rs | 4 | ||||
-rw-r--r-- | openpgp/src/cert/mod.rs | 14 | ||||
-rw-r--r-- | openpgp/src/packet/one_pass_sig.rs | 2 | ||||
-rw-r--r-- | openpgp/src/packet/signature/mod.rs | 4 | ||||
-rw-r--r-- | openpgp/src/packet/signature/subpacket.rs | 111 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 2 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 2 | ||||
-rw-r--r-- | tool/src/commands/inspect.rs | 38 |
9 files changed, 98 insertions, 81 deletions
diff --git a/guide/src/chapter_03.md b/guide/src/chapter_03.md index 4d48717c..eef988ca 100644 --- a/guide/src/chapter_03.md +++ b/guide/src/chapter_03.md @@ -142,7 +142,7 @@ fn main() { // Finally, we expect the signature itself. if let openpgp::Packet::Signature(ref signature) = packets[2] { - assert_eq!(signature.issuer_fingerprint().unwrap().to_string(), + assert_eq!(signature.issuer_fingerprints().nth(0).unwrap().to_string(), "67A4 8753 A380 A6B3 B7DF 7DC5 E6C6 897A 4CEF 8924"); } else { panic!("expected signature packet"); diff --git a/openpgp-ffi/src/packet/signature.rs b/openpgp-ffi/src/packet/signature.rs index b6ee4061..d746a13c 100644 --- a/openpgp-ffi/src/packet/signature.rs +++ b/openpgp-ffi/src/packet/signature.rs @@ -53,7 +53,7 @@ fn pgp_signature_into_packet(s: *mut Signature) -> *mut Packet { /// subpacket, this still returns NULL. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_signature_issuer(sig: *const Signature) -> Maybe<KeyID> { - sig.ref_raw().issuer().move_into_raw() + sig.ref_raw().issuers().nth(0).move_into_raw() } /// Returns the value of the `Signature` packet's IssuerFingerprint subpacket. @@ -64,7 +64,7 @@ fn pgp_signature_issuer(sig: *const Signature) -> Maybe<KeyID> { #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_signature_issuer_fingerprint(sig: *const Signature) -> Maybe<Fingerprint> { - sig.ref_raw().issuer_fingerprint().move_into_raw() + sig.ref_raw().issuer_fingerprints().nth(0).move_into_raw() } diff --git a/openpgp/src/cert/mod.rs b/openpgp/src/cert/mod.rs index b0c4b9e3..279635ab 100644 --- a/openpgp/src/cert/mod.rs +++ b/openpgp/src/cert/mod.rs @@ -3949,9 +3949,10 @@ mod test { .build(&mut keypair, &cert, None) .unwrap(); assert_eq!(sig.typ(), SignatureType::KeyRevocation); - assert_eq!(sig.issuer(), Some(&cert.keyid())); - assert_eq!(sig.issuer_fingerprint(), - Some(&cert.fingerprint())); + assert_eq!(sig.issuers().collect::<Vec<_>>(), + vec![ &cert.keyid() ]); + assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(), + vec![ &cert.fingerprint() ]); let cert = cert.merge_packets(sig).unwrap(); assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, None)); @@ -3972,9 +3973,10 @@ mod test { .unwrap(); assert_eq!(sig.typ(), SignatureType::KeyRevocation); - assert_eq!(sig.issuer(), Some(&other.keyid())); - assert_eq!(sig.issuer_fingerprint(), - Some(&other.fingerprint())); + assert_eq!(sig.issuers().collect::<Vec<_>>(), + vec![ &other.keyid() ]); + assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(), + vec![ &other.fingerprint() ]); } #[test] diff --git a/openpgp/src/packet/one_pass_sig.rs b/openpgp/src/packet/one_pass_sig.rs index a6861d6e..d0524c21 100644 --- a/openpgp/src/packet/one_pass_sig.rs +++ b/openpgp/src/packet/one_pass_sig.rs @@ -150,7 +150,7 @@ impl<'a> std::convert::TryFrom<&'a Signature> for OnePassSig3 { type Error = anyhow::Error; fn try_from(s: &'a Signature) -> Result<Self> { - let issuer = match s.issuer() { + let issuer = match s.issuers().nth(0) { Some(i) => i.clone(), None => return Err(Error::InvalidArgument( diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs index 407384a0..25f0a4fd 100644 --- a/openpgp/src/packet/signature/mod.rs +++ b/openpgp/src/packet/signature/mod.rs @@ -1380,7 +1380,9 @@ impl SignatureBuilder { } // Make sure we have an issuer packet. - if self.issuer().is_none() && self.issuer_fingerprint().is_none() { + if self.issuers().next().is_none() + && self.issuer_fingerprints().next().is_none() + { self = self.set_issuer(signer.public().keyid())? .set_issuer_fingerprint(signer.public().fingerprint())?; } diff --git a/openpgp/src/packet/signature/subpacket.rs b/openpgp/src/packet/signature/subpacket.rs index 953d84c9..7edc22b7 100644 --- a/openpgp/src/packet/signature/subpacket.rs +++ b/openpgp/src/packet/signature/subpacket.rs @@ -27,8 +27,7 @@ //! //! # Examples //! -//! If a signature packet includes an issuer fingerprint subpacket, -//! print it: +//! Print any Issuer Fingerprint subpackets: //! //! ```rust //! # extern crate sequoia_openpgp as openpgp; @@ -42,8 +41,8 @@ //! let mut ppr = PacketParser::from_bytes(message_data)?; //! while let PacketParserResult::Some(mut pp) = ppr { //! if let Packet::Signature(ref sig) = pp.packet { -//! if let Some(fp) = sig.issuer_fingerprint() { -//! eprintln!("Signature issued by: {}", fp.to_string()); +//! for fp in sig.issuer_fingerprints() { +//! eprintln!("Signature allegedly issued by: {}", fp.to_string()); //! } //! } //! @@ -1369,25 +1368,19 @@ impl SubpacketAreas { }) } - /// Returns the value of the Issuer subpacket, which contains the - /// KeyID of the key that allegedly created this signature. + /// Returns the value of any Issuer subpackets. /// - /// If the subpacket is not present, this returns `None`. - /// - /// Note: if the signature contains multiple instances of this - /// subpacket, only the last one is considered. - pub fn issuer(&self) -> Option<&KeyID> { + /// This returns all instances of the Issuer subpacket in both the + /// hashed subpacket area and the unhashed subpacket area. + pub fn issuers(&self) -> impl Iterator<Item=&KeyID> { // 8-octet Key ID - if let Some(sb) - = self.subpacket(SubpacketTag::Issuer) { - if let SubpacketValue::Issuer(v) = &sb.value { - Some(v) - } else { - None - } - } else { - None - } + self.subpackets(SubpacketTag::Issuer) + .map(|sb| { + match sb.value { + SubpacketValue::Issuer(ref keyid) => keyid, + _ => unreachable!(), + } + }) } /// Returns the value of all Notation Data packets. @@ -1703,29 +1696,21 @@ impl SubpacketAreas { } } - /// Returns the value of the Issuer Fingerprint subpacket, which - /// contains the fingerprint of the key that allegedly created - /// this signature. + /// Returns the value of any Issuer Fingerprint subpackets. /// - /// This subpacket should be preferred to the Issuer subpacket, - /// because Fingerprints are not subject to collisions. - /// - /// If the subpacket is not present, this returns `None`. - /// - /// Note: if the signature contains multiple instances of this - /// subpacket, only the last one is considered. - pub fn issuer_fingerprint(&self) -> Option<&Fingerprint> { + /// This returns all instances of the Issuer Fingerprint subpacket + /// in both the hashed subpacket area and the unhashed subpacket + /// area. + pub fn issuer_fingerprints(&self) -> impl Iterator<Item=&Fingerprint> + { // 1 octet key version number, N octets of fingerprint - if let Some(sb) - = self.subpacket(SubpacketTag::IssuerFingerprint) { - if let SubpacketValue::IssuerFingerprint(v) = &sb.value { - Some(v) - } else { - None - } - } else { - None - } + self.subpackets(SubpacketTag::IssuerFingerprint) + .map(|sb| { + match sb.value { + SubpacketValue::IssuerFingerprint(ref fpr) => fpr, + _ => unreachable!(), + } + }) } /// Returns the value of the Preferred AEAD Algorithms subpacket, @@ -1872,7 +1857,6 @@ impl SubpacketAreas { /// Unknown subpackets are assumed to only safely occur in the /// hashed subpacket area. Thus, any instances of them in the /// unhashed area are ignored. - #[cfg(test)] fn subpackets(&self, tag: SubpacketTag) -> impl Iterator<Item = &Subpacket> { // It would be nice to do: @@ -5163,7 +5147,8 @@ fn accessors() { sig = sig.set_issuer(fp.clone().into()).unwrap(); let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap(); - assert_eq!(sig_.issuer(), Some(&fp.clone().into())); + assert_eq!(sig_.issuers().collect::<Vec<_>>(), + vec![ &fp.clone().into() ]); let pref = vec![HashAlgorithm::SHA512, HashAlgorithm::SHA384, @@ -5251,7 +5236,8 @@ fn accessors() { sig = sig.set_issuer_fingerprint(fp.clone()).unwrap(); let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap(); - assert_eq!(sig_.issuer_fingerprint(), Some(&fp)); + assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(), + vec![ &fp ]); let pref = vec![AEADAlgorithm::EAX, AEADAlgorithm::OCB]; @@ -5328,13 +5314,13 @@ fn subpacket_test_1 () { assert!(got2 && got16 && got33); - let fp = sig.issuer_fingerprint().unwrap().to_string(); + let fp = sig.issuer_fingerprints().nth(0).unwrap().to_string(); // eprintln!("Issuer: {}", fp); assert!( fp == "7FAF 6ED7 2381 4355 7BDF 7ED2 6863 C9AD 5B4D 22D3" || fp == "C03F A641 1B03 AE12 5764 6118 7223 B566 78E0 2528"); - let hex = format!("{:X}", sig.issuer_fingerprint().unwrap()); + let hex = format!("{:X}", sig.issuer_fingerprints().nth(0).unwrap()); assert!( hex == "7FAF6ED7238143557BDF7ED26863C9AD5B4D22D3" || hex == "C03FA6411B03AE12576461187223B56678E02528"); @@ -5514,7 +5500,7 @@ fn subpacket_test_2() { })); let keyid = "F004 B9A4 5C58 6126".parse().unwrap(); - assert_eq!(sig.issuer(), Some(&keyid)); + assert_eq!(sig.issuers().collect::<Vec<_>>(), vec![ &keyid ]); assert_eq!(sig.subpacket(SubpacketTag::Issuer), Some(&Subpacket { length: 9.into(), @@ -5523,7 +5509,7 @@ fn subpacket_test_2() { })); let fp = "361A96BDE1A65B6D6C25AE9FF004B9A45C586126".parse().unwrap(); - assert_eq!(sig.issuer_fingerprint(), Some(&fp)); + assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(), vec![ &fp ]); assert_eq!(sig.subpacket(SubpacketTag::IssuerFingerprint), Some(&Subpacket { length: 22.into(), @@ -5634,7 +5620,8 @@ fn subpacket_test_2() { let keyid = "CEAD 0621 0934 7957".parse().unwrap(); - assert_eq!(sig.issuer(), Some(&keyid)); + assert_eq!(sig.issuers().collect::<Vec<_>>(), + vec![ &keyid ]); assert_eq!(sig.subpacket(SubpacketTag::Issuer), Some(&Subpacket { length: 9.into(), @@ -5643,7 +5630,8 @@ fn subpacket_test_2() { })); let fp = "B59B8817F519DCE10AFD85E4CEAD062109347957".parse().unwrap(); - assert_eq!(sig.issuer_fingerprint(), Some(&fp)); + assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(), + vec![ &fp ]); assert_eq!(sig.subpacket(SubpacketTag::IssuerFingerprint), Some(&Subpacket { length: 22.into(), @@ -5837,7 +5825,7 @@ fn subpacket_test_2() { })); let keyid = "CEAD 0621 0934 7957".parse().unwrap(); - assert_eq!(sig.issuer(), Some(&keyid)); + assert_eq!(sig.issuers().collect::<Vec<_>>(), vec! [&keyid ]); assert_eq!(sig.subpacket(SubpacketTag::Issuer), Some(&Subpacket { length: 9.into(), @@ -5846,7 +5834,8 @@ fn subpacket_test_2() { })); let fp = "B59B8817F519DCE10AFD85E4CEAD062109347957".parse().unwrap(); - assert_eq!(sig.issuer_fingerprint(), Some(&fp)); + assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(), + vec![ &fp ]); assert_eq!(sig.subpacket(SubpacketTag::IssuerFingerprint), Some(&Subpacket { length: 22.into(), @@ -5886,8 +5875,10 @@ fn issuer_default() -> Result<()> { // no issuer or issuer_fingerprint present, use default let sig_ = sig.sign_hash(&mut keypair, hash.clone())?; - assert_eq!(sig_.issuer(), Some(&keypair.public().keyid())); - assert_eq!(sig_.issuer_fingerprint(), Some(&keypair.public().fingerprint())); + assert_eq!(sig_.issuers().collect::<Vec<_>>(), + vec![ &keypair.public().keyid() ]); + assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(), + vec![ &keypair.public().fingerprint() ]); let fp = Fingerprint::from_bytes(b"bbbbbbbbbbbbbbbbbbbb"); @@ -5897,8 +5888,9 @@ fn issuer_default() -> Result<()> { sig = sig.set_issuer(fp.clone().into())?; let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone())?; - assert_eq!(sig_.issuer(), Some(&fp.clone().into())); - assert!(sig_.issuer_fingerprint().is_none()); + assert_eq!(sig_.issuers().collect::<Vec<_>>(), + vec![ &fp.clone().into() ]); + assert_eq!(sig_.issuer_fingerprints().count(), 0); // issuer_fingerprint subpacket present, do not override let mut sig = signature::SignatureBuilder::new(crate::types::SignatureType::Binary); @@ -5906,7 +5898,8 @@ fn issuer_default() -> Result<()> { sig = sig.set_issuer_fingerprint(fp.clone())?; let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone())?; - assert_eq!(sig_.issuer_fingerprint(), Some(&fp)); - assert!(sig_.issuer().is_none()); + assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(), + vec![ &fp ]); + assert_eq!(sig_.issuers().count(), 0); Ok(()) } diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index 36f3cf9f..89943f24 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -3028,7 +3028,7 @@ mod test { sig, .. }) = &results[0] { assert_eq!( - &sig.issuer_fingerprint().unwrap() + &sig.issuer_fingerprints().nth(0).unwrap() .to_string(), match i { 0 => "8E8C 33FA 4626 3379 76D9 7978 069C 0C34 8DD8 2C19", diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index 2ff14398..15e9cb9d 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -2892,7 +2892,7 @@ mod test { let mut good = 0; while let PacketParserResult::Some(pp) = ppr { if let Packet::Signature(ref sig) = pp.packet { - let key = keys.get(&sig.issuer_fingerprint().unwrap()) + let key = keys.get(&sig.issuer_fingerprints().nth(0).unwrap()) .unwrap(); sig.verify(key).unwrap(); good += 1; diff --git a/tool/src/commands/inspect.rs b/tool/src/commands/inspect.rs index 6f5d080c..c1f12120 100644 --- a/tool/src/commands/inspect.rs +++ b/tool/src/commands/inspect.rs @@ -4,7 +4,7 @@ use std::io::{self, Read}; use clap; extern crate sequoia_openpgp as openpgp; -use crate::openpgp::{Packet, Result}; +use crate::openpgp::{KeyHandle, Packet, Result}; use crate::openpgp::cert::prelude::*; use openpgp::packet::{ Signature, @@ -351,10 +351,20 @@ fn inspect_signatures(output: &mut dyn io::Write, writeln!(output, " Kind: {}", signature_type)?, } - if let Some(fp) = sig.issuer_fingerprint() { - writeln!(output, " Signed by: {}", fp)?; - } else if let Some(kid) = sig.issuer() { - writeln!(output, " Signed by: {}", kid)?; + let mut fps: Vec<_> = sig.issuer_fingerprints().collect(); + fps.sort(); + fps.dedup(); + let fps: Vec<KeyHandle> = fps.into_iter().map(|fp| fp.into()).collect(); + for fp in fps.iter() { + writeln!(output, " Alleged signer: {}", fp)?; + } + let mut keyids: Vec<_> = sig.issuers().collect(); + keyids.sort(); + keyids.dedup(); + for keyid in keyids { + if ! fps.iter().any(|fp| fp.aliases(&keyid.into())) { + writeln!(output, " Alleged signer: {}", keyid)?; + } } } if ! sigs.is_empty() { @@ -370,10 +380,20 @@ fn inspect_certifications(output: &mut dyn io::Write, print_certifications: bool) -> Result<()> { if print_certifications { for sig in certs { - if let Some(fp) = sig.issuer_fingerprint() { - writeln!(output, " Certified by: {}", fp)?; - } else if let Some(kid) = sig.issuer() { - writeln!(output, " Certified by: {}", kid)?; + let mut fps: Vec<_> = sig.issuer_fingerprints().collect(); + fps.sort(); + fps.dedup(); + let fps: Vec<KeyHandle> = fps.into_iter().map(|fp| fp.into()).collect(); + for fp in fps.iter() { + writeln!(output, "Alleged certifier: {}", fp)?; + } + let mut keyids: Vec<_> = sig.issuers().collect(); + keyids.sort(); + keyids.dedup(); + for keyid in keyids { + if ! fps.iter().any(|fp| fp.aliases(&keyid.into())) { + writeln!(output, "Alleged certifier: {}", keyid)?; + } } } if ! certs.is_empty() { |