summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2020-08-12 15:48:36 +0200
committerNeal H. Walfield <neal@pep.foundation>2020-08-12 15:55:09 +0200
commitd4fe2832c9bf1d49b87a301bd0a46caa45018477 (patch)
tree2dbdf9b430456aec4a7878cc6ab53abe92166876
parent2aa8c003a99afef4e8199e92cfa403a5048cdf7c (diff)
openpgp: Change accessors to return all issuers.
- Unlike the `Signature Creation Time` subpacket, there are legitimate reasons to have multiple `Issuer` subpackets and `Issuer Fingerprint` subpackets. - Rename `SubpacketAreas::issuer` to `SubpacketAreas::issuers` and return all `Issuer` subpackets. - Likewise, Rename `SubpacketAreas::issuer_fingerprint` to `SubpacketAreas::issuer_fingerprints` and return all `Issuer Fingerprint` subpackets. - Change `sq` to list all issuers. Deduplicate first, however.
-rw-r--r--guide/src/chapter_03.md2
-rw-r--r--openpgp-ffi/src/packet/signature.rs4
-rw-r--r--openpgp/src/cert/mod.rs14
-rw-r--r--openpgp/src/packet/one_pass_sig.rs2
-rw-r--r--openpgp/src/packet/signature/mod.rs4
-rw-r--r--openpgp/src/packet/signature/subpacket.rs111
-rw-r--r--openpgp/src/parse/stream.rs2
-rw-r--r--openpgp/src/serialize/stream.rs2
-rw-r--r--tool/src/commands/inspect.rs38
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() {