diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-11-26 17:54:04 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-11-27 14:09:26 +0100 |
commit | 6fa1c0c42d21c7876c594f9c658742f6639f86b9 (patch) | |
tree | e38d797dbbf38c7ce5a1c8ca45a04a7ecbe316b6 | |
parent | a52f66d26bdef3ce9c8948aa058dff39048e16c3 (diff) |
openpgp: Fix Signature::get_issuer to return set of issuers.
- A signature can contain multiple hints as to who created the
signature. Return all those hints to the caller.
- Adapt all callers accordingly.
- Fixes #264.
-rw-r--r-- | openpgp/examples/web-of-trust.rs | 7 | ||||
-rw-r--r-- | openpgp/src/packet/signature/mod.rs | 28 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 16 | ||||
-rw-r--r-- | tool/src/commands/mod.rs | 5 |
4 files changed, 34 insertions, 22 deletions
diff --git a/openpgp/examples/web-of-trust.rs b/openpgp/examples/web-of-trust.rs index 754a7b13..34cbe289 100644 --- a/openpgp/examples/web-of-trust.rs +++ b/openpgp/examples/web-of-trust.rs @@ -10,6 +10,7 @@ use std::env; extern crate sequoia_openpgp as openpgp; +use crate::openpgp::KeyID; use crate::openpgp::tpk::TPKParser; use crate::openpgp::parse::Parse; @@ -39,14 +40,12 @@ fn main() { let keyid = tpk.keyid(); for uidb in tpk.userids() { for tps in uidb.certifications() { - if let Some(issuer) = tps.get_issuer() { + for issuer in tps.get_issuers() { println!("{}, {:?}, {}", - issuer.as_u64().unwrap(), + KeyID::from(issuer).as_u64().unwrap(), String::from_utf8_lossy( uidb.userid().value()), keyid.as_u64().unwrap()); - } else { - eprintln!("No issuer!?"); } } } diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs index 4fb15d18..a754bec7 100644 --- a/openpgp/src/packet/signature/mod.rs +++ b/openpgp/src/packet/signature/mod.rs @@ -19,7 +19,6 @@ use crate::packet::{ key, Key, }; -use crate::KeyID; use crate::packet::UserID; use crate::packet::UserAttribute; use crate::Packet; @@ -476,13 +475,25 @@ impl Signature4 { ::std::mem::replace(&mut self.level, level) } - /// Gets the issuer. - pub fn get_issuer(&self) -> Option<KeyID> { - if let Some(id) = self.issuer() { - Some(id) - } else { - None - } + /// Collects all the issuers. + /// + /// A signature can contain multiple hints as to who issued the + /// signature. + pub fn get_issuers(&self) -> std::collections::HashSet<crate::KeyHandle> { + use crate::packet::signature::subpacket:: SubpacketValue; + + self.hashed_area().iter() + .chain(self.unhashed_area().iter()) + .filter_map(|(_, _, subpacket)| { + match subpacket.value() { + SubpacketValue::Issuer(i) => + Some(crate::KeyHandle::KeyID(i.clone())), + SubpacketValue::IssuerFingerprint(i) => + Some(crate::KeyHandle::Fingerprint(i.clone())), + _ => None, + } + }) + .collect() } /// Normalizes the signature. @@ -1098,6 +1109,7 @@ impl From<Signature4> for super::Signature { #[cfg(test)] mod test { use super::*; + use crate::KeyID; use crate::conversions::Time; use crate::crypto; use crate::crypto::mpis::MPI; diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index cca238dc..43120f87 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -606,8 +606,8 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> { // // In this case, we get the issuer from the // signature itself. - if let Some(issuer) = sig.get_issuer() { - issuers.push(issuer); + if let Some(issuer) = sig.get_issuers().iter().next() { + issuers.push(issuer.clone().into()); } else { issuers.push(KeyID::wildcard()); } @@ -656,9 +656,9 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> { IMessageLayer::SignatureGroup { sigs, .. } => { results.new_signature_group(); for sig in sigs.into_iter() { - if let Some(issuer) = sig.get_issuer() { + if let Some(issuer) = sig.get_issuers().iter().next() { let r = if let Some((i, j)) = - self.keys.get(&issuer) + self.keys.get(&issuer.clone().into()) { let tpk = &self.tpks[*i]; let (binding, revoked, key) @@ -1421,8 +1421,8 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { // // In this case, we get the issuer from the // signature itself. - if let Some(issuer) = sig.get_issuer() { - issuers.push(issuer); + if let Some(issuer) = sig.get_issuers().iter().next() { + issuers.push(issuer.clone().into()); } else { issuers.push(KeyID::wildcard()); } @@ -1518,9 +1518,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { IMessageLayer::SignatureGroup { sigs, .. } => { results.new_signature_group(); for sig in sigs.into_iter() { - if let Some(issuer) = sig.get_issuer() { + if let Some(issuer) = sig.get_issuers().iter().next() { results.push_verification_result( - if let Some((i, j)) = self.keys.get(&issuer) { + if let Some((i, j)) = self.keys.get(&issuer.clone().into()) { let tpk = &self.tpks[*i]; let (binding, revoked, key) = tpk.keys_all().nth(*j).unwrap(); diff --git a/tool/src/commands/mod.rs b/tool/src/commands/mod.rs index 6da5f56b..a7b76038 100644 --- a/tool/src/commands/mod.rs +++ b/tool/src/commands/mod.rs @@ -238,8 +238,9 @@ impl<'a> VHelper<'a> { use self::VerificationResult::*; for result in results { if let MissingKey { sig } = result { - let issuer = sig.get_issuer() - .expect("missing key checksum has an issuer"); + let issuer = sig.get_issuers().iter().nth(0) + .expect("missing key checksum has an issuer") + .to_string(); let what = match sig.level() { 0 => "checksum".into(), n => format!("level {} notarizing checksum", n), |