diff options
Diffstat (limited to 'openpgp/examples/sign-detached.rs')
-rw-r--r-- | openpgp/examples/sign-detached.rs | 99 |
1 files changed, 15 insertions, 84 deletions
diff --git a/openpgp/examples/sign-detached.rs b/openpgp/examples/sign-detached.rs index 4cc0b021..a4052907 100644 --- a/openpgp/examples/sign-detached.rs +++ b/openpgp/examples/sign-detached.rs @@ -2,19 +2,15 @@ use std::env; use std::io; -use std::iter; -extern crate time; extern crate openpgp; -use openpgp::{armor, Key, Signature}; -use openpgp::constants::{SignatureType, HashAlgorithm}; -use openpgp::SecretKey; -use openpgp::serialize::Serialize; +use openpgp::armor; +use openpgp::serialize::stream::{wrap, Signer}; fn main() { let args: Vec<String> = env::args().collect(); if args.len() < 2 { - panic!("A simple encryption filter.\n\n\ + panic!("A simple filter creating a detached signature.\n\n\ Usage: {} <secret-keyfile> [<secret-keyfile>...] \ <input >output\n", args[0]); } @@ -29,87 +25,22 @@ fn main() { .expect("Failed to read key") }).collect(); - // Hash the file. - let hash_algo = HashAlgorithm::SHA512; - let hashes = openpgp::hash_file(io::stdin(), &[hash_algo]) - .expect("Failed to hash file"); - - // Get the one hash we computed. - let hash = &hashes[0].1; - // Compose a writer stack corresponding to the output format and // packet structure we want. First, we want the output to be as // armored. - let mut sink = armor::Writer::new(io::stdout(), armor::Kind::Message); - - for tsk in tsks { - // We need to find all (sub)keys capable of signing. - let can_sign = |key: &Key, sig: &Signature| -> bool { - sig.key_flags().can_sign() - // Check expiry. - && ! sig.signature_expired() - && ! sig.key_expired(key) - }; - - // Gather all signing-capable subkeys. - let subkeys = tsk.subkeys().filter_map(|skb| { - let key = skb.subkey(); - // The first signature is the most recent binding - // signature. - if skb.selfsigs().next() - .map(|sig| can_sign(key, sig)) - .unwrap_or(false) { - Some(key) - } else { - None - } - }); + let sink = armor::Writer::new(io::stdout(), armor::Kind::Signature); - // Check if the primary key is signing-capable. - let primary_can_sign = - // The key capabilities are defined by the most recent - // binding signature of the primary user id (or the - // most recent user id binding if no user id is marked - // as primary). In any case, this is the first user id. - tsk.userids().next().map(|ub| { - ub.selfsigs().next() - .map(|sig| can_sign(tsk.primary(), sig)) - .unwrap_or(false) - }).unwrap_or(false); + // Now, create a signer that emits a detached signature. + let mut signer = Signer::detached( + wrap(sink), &tsks.iter().collect::<Vec<&openpgp::TPK>>()) + .expect("Failed to create signer"); - // If the primary key is signing-capable, prepend to - // subkeys via iterator magic. - let keys = - iter::once(tsk.primary()) - .filter(|_| primary_can_sign) - .chain(subkeys); + // Finally, just copy all the data. + io::copy(&mut io::stdin(), &mut signer) + .expect("Failed to sign data"); - // For every suitable key, compute and emit a signature. - for key in keys { - if let &SecretKey::Unencrypted { mpis: ref sec } = - key.secret.as_ref().expect("No secret key") - { - // Clone hash so that we can hash the signature - // packet, and compute the digest. - let mut hash = hash.clone(); - - // Make and hash a signature packet. - let mut sig = Signature::new(SignatureType::Binary); - sig.set_signature_creation_time(time::now()) - .expect("Failed to set creation time"); - sig.set_issuer_fingerprint(key.fingerprint()) - .expect("Failed to set issuer fingerprint"); - sig.set_issuer(key.keyid()) - .expect("Failed to set issuer"); - - // Make signature. - sig.sign_hash(&key, sec, hash_algo, hash) - .expect("Failed to compute signature"); - - // And emit the packet. - sig.serialize(&mut sink) - .expect("Failed to write packet"); - } - } - } + // Teardown the stack to ensure all the data is written. + let _ = signer.into_inner() + .expect("Failed to write data") + .unwrap(); } |