summaryrefslogtreecommitdiffstats
path: root/openpgp/examples/sign-detached.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/examples/sign-detached.rs')
-rw-r--r--openpgp/examples/sign-detached.rs99
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();
}