diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2018-05-03 15:19:58 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2018-05-03 15:25:37 +0200 |
commit | 75ae87e1d8ee5f7ac15bd6dd335893b4488e2963 (patch) | |
tree | 92a2c0c288cf2dab7fe6b29388c54e1fee08a0a1 /tool | |
parent | 2100f1b17bd633891b55a1855a65238379e0d041 (diff) |
tool: Improve sqv.
- Canonicalizing TPKs turned out to be quite expensive, even though
we do not check binding signatures at this point. If we want sqv
to be a drop-in replacement for gpgv, it needs to be able to
handle keyrings with a similar performance.
- This patch builds and canonicalizes TPKs iff we actually need
them, resulting in a performance similar to gpgv.
Diffstat (limited to 'tool')
-rw-r--r-- | tool/src/sqv.rs | 112 |
1 files changed, 85 insertions, 27 deletions
diff --git a/tool/src/sqv.rs b/tool/src/sqv.rs index b5e64805..d8cf3c3c 100644 --- a/tool/src/sqv.rs +++ b/tool/src/sqv.rs @@ -14,9 +14,8 @@ use std::process::exit; use clap::{App, Arg, AppSettings}; -use openpgp::{HashAlgo, TPK, Packet, Signature, KeyID}; +use openpgp::{HashAlgo, TPK, Packet, Signature, KeyID, Message}; use openpgp::parse::PacketParser; -use openpgp::tpk::TPKParser; use openpgp::parse::HashedReader; // The argument parser. @@ -51,6 +50,32 @@ fn cli_build() -> App<'static, 'static> { .long("trace")) } +/// Given a vector of signatures, the keyid of the (sub)key that +/// created the signature, and a TPK containing this (sub)key, +/// store (or merge) that TPK in the vector. +fn remember_tpk(sigs: &mut Vec<(Signature, KeyID, Option<TPK>)>, + keyid: &KeyID, tpk: &TPK, trace: bool) { + for &mut (_, ref issuer, ref mut issuer_tpko) in sigs.iter_mut() { + if *issuer == *keyid { + if let Some(issuer_tpk) = issuer_tpko.take() { + if trace { + eprintln!("Found key {} again. Merging.", + issuer); + } + + *issuer_tpko + = issuer_tpk.merge(tpk.clone()).ok(); + } else { + if trace { + eprintln!("Found key {}.", issuer); + } + + *issuer_tpko = Some(tpk.clone()); + } + } + } +} + fn real_main() -> Result<(), failure::Error> { let matches = cli_build().get_matches(); @@ -152,37 +177,70 @@ fn real_main() -> Result<(), failure::Error> { for filename in matches.values_of_os("keyring") .expect("No keyring specified.") { + // Load the keyring. + let mut ppo = PacketParser::from_file(filename)?; + + // We store packets in an accumulator until we are sure that + // we want to build and use a TPK. + let mut acc = vec![]; + + // Do we want it? If so, what is the KeyID of the (sub)key? + let mut want = None; + // Iterate over each TPK in the keyring. - if let Some(pp) = PacketParser::from_file(filename)? { - for tpk in TPKParser::new(pp.into_iter()) { - // Iterate over each key in each TPK. - for key in tpk.keys() { - let keyid = key.keyid(); + while let Some(pp) = ppo { + match pp.packet { + Packet::PublicKey(ref key) => { + // A new TPK starts here. Check if we want the + // current one. + if let Some(ref keyid) = want { + // Build the TPK... + let tpk = TPK::from_message(Message::from_packets(acc))?; + acc = vec![]; + + // ... and remember it. + remember_tpk(&mut sigs, keyid, &tpk, trace); + } - // Now, see if we need the key. - for &mut (_, ref issuer, ref mut issuer_tpko) in &mut sigs { + // Reset accumulator. + acc.clear(); + want = None; + + // Now, see if we need the new key. + let keyid = key.keyid(); + for &(_, ref issuer, _) in &sigs { if *issuer == keyid { - if let Some(issuer_tpk) = issuer_tpko.take() { - if trace { - eprintln!("Found key {} again. Merging.", - issuer); - } - - *issuer_tpko - = issuer_tpk.merge(tpk.clone()).ok(); - } else { - if trace { - eprintln!("Found key {}.", issuer); - } - - *issuer_tpko = Some(tpk.clone()); - } + want = Some(keyid); + break; } } - } + }, + Packet::PublicSubkey(ref key) => { + // Now, see if we need the new key. + let keyid = key.keyid(); + for &(_, ref issuer, _) in &sigs { + if *issuer == keyid { + eprintln!("want subkey {}", keyid); + want = Some(keyid); + break; + } + } + }, + _ => (), } - } else { - eprintln!("File is empty."); + + // Get the next packet, and remember the current one. + let (packet, _packet_depth, tmp, _pp_depth) = pp.recurse()?; + acc.push(packet); + ppo = tmp; + } + + // This was the last TPK. Check if we want it. + if let Some(ref keyid) = want { + // Build the TPK... + let tpk = TPK::from_message(Message::from_packets(acc))?; + // ... and remember it. + remember_tpk(&mut sigs, keyid, &tpk, trace); } } |