summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-11-19 15:50:23 +0100
committerJustus Winter <justus@sequoia-pgp.org>2019-11-19 15:50:23 +0100
commit1ddc1dd61b45b41801c1d1c364cd6789314cb8f3 (patch)
treeb34baf591fce5f778cd2f132ead705d39abbff47
parentcf9b92f5f9238b8322d09833b92c886dda219924 (diff)
openpgp: Use the builder pattern for stream::Signer.
- See #375.
-rw-r--r--guide/src/chapter_01.md16
-rw-r--r--ipc/examples/gpg-agent-sign.rs23
-rw-r--r--ipc/tests/gpg-agent.rs9
-rw-r--r--openpgp-ffi/include/sequoia/openpgp.h6
-rw-r--r--openpgp-ffi/src/serialize.rs61
-rw-r--r--openpgp/examples/generate-sign-verify.rs4
-rw-r--r--openpgp/examples/notarize.rs16
-rw-r--r--openpgp/examples/sign-detached.rs15
-rw-r--r--openpgp/examples/sign.rs16
-rw-r--r--openpgp/src/crypto/asymmetric.rs11
-rw-r--r--openpgp/src/parse/stream.rs5
-rw-r--r--openpgp/src/serialize/stream.rs132
-rw-r--r--tool/src/commands/mod.rs14
-rw-r--r--tool/src/commands/sign.rs38
-rw-r--r--tool/tests/sq-sign.rs5
15 files changed, 195 insertions, 176 deletions
diff --git a/guide/src/chapter_01.md b/guide/src/chapter_01.md
index fad70067..fcce2101 100644
--- a/guide/src/chapter_01.md
+++ b/guide/src/chapter_01.md
@@ -52,13 +52,13 @@ fn main() {
# // Get the keypair to do the signing from the TPK.
# let key : key::UnspecifiedSecret
# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into();
-# let mut keypair = key.into_keypair()?;
+# let keypair = key.into_keypair()?;
#
# // Start streaming an OpenPGP message.
# let message = Message::new(sink);
#
# // We want to sign a literal data packet.
-# let signer = Signer::new(message, vec![&mut keypair], None)?;
+# let signer = Signer::new(message, keypair).build()?;
#
# // Emit a literal data packet.
# let mut literal_writer = LiteralWriter::new(signer, None, None, None)?;
@@ -197,13 +197,13 @@ fn generate() -> openpgp::Result<openpgp::TPK> {
# // Get the keypair to do the signing from the TPK.
# let key : key::UnspecifiedSecret
# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into();
-# let mut keypair = key.into_keypair()?;
+# let keypair = key.into_keypair()?;
#
# // Start streaming an OpenPGP message.
# let message = Message::new(sink);
#
# // We want to sign a literal data packet.
-# let signer = Signer::new(message, vec![&mut keypair], None)?;
+# let signer = Signer::new(message, keypair).build()?;
#
# // Emit a literal data packet.
# let mut literal_writer = LiteralWriter::new(signer, None, None, None)?;
@@ -342,13 +342,13 @@ fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK)
// Get the keypair to do the signing from the TPK.
let key : key::UnspecifiedSecret
= tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into();
- let mut keypair = key.into_keypair()?;
+ let keypair = key.into_keypair()?;
// Start streaming an OpenPGP message.
let message = Message::new(sink);
// We want to sign a literal data packet.
- let signer = Signer::new(message, vec![&mut keypair], None)?;
+ let signer = Signer::new(message, keypair).build()?;
// Emit a literal data packet.
let mut literal_writer = LiteralWriter::new(signer, None, None, None)?;
@@ -498,13 +498,13 @@ Verified data can be read from this using [`io::Read`].
# // Get the keypair to do the signing from the TPK.
# let key : key::UnspecifiedSecret
# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into();
-# let mut keypair = key.into_keypair()?;
+# let keypair = key.into_keypair()?;
#
# // Start streaming an OpenPGP message.
# let message = Message::new(sink);
#
# // We want to sign a literal data packet.
-# let signer = Signer::new(message, vec![&mut keypair], None)?;
+# let signer = Signer::new(message, keypair).build()?;
#
# // Emit a literal data packet.
# let mut literal_writer = LiteralWriter::new(signer, None, None, None)?;
diff --git a/ipc/examples/gpg-agent-sign.rs b/ipc/examples/gpg-agent-sign.rs
index 1a089622..c4b3d6c0 100644
--- a/ipc/examples/gpg-agent-sign.rs
+++ b/ipc/examples/gpg-agent-sign.rs
@@ -38,14 +38,11 @@ fn main() {
}).collect::<Vec<_>>();
// Construct a KeyPair for every signing-capable (sub)key.
- let mut keypairs = tpks.iter().flat_map(|tpk| tpk.keys_valid().signing_capable().filter_map(|(_, _, key)| {
- KeyPair::new(&ctx, key).ok()
- })).collect::<Vec<KeyPair<_>>>();
-
- // Well, this is awkward...
- let signers = keypairs.iter_mut()
- .map(|s| -> &mut dyn openpgp::crypto::Signer<_> { s })
- .collect();
+ let mut signers = tpks.iter().flat_map(|tpk| {
+ tpk.keys_valid().signing_capable().filter_map(|(_, _, key)| {
+ KeyPair::new(&ctx, key).ok()
+ })
+ }).collect::<Vec<KeyPair<_>>>();
// Compose a writer stack corresponding to the output format and
// packet structure we want. First, we want the output to be
@@ -56,9 +53,13 @@ fn main() {
// Stream an OpenPGP message.
let message = Message::new(sink);
- // Now, create a signer that emits a signature.
- let signer = Signer::new(message, signers, None)
- .expect("Failed to create signer");
+ // Now, create a signer that emits the signature(s).
+ let mut signer =
+ Signer::new(message, signers.pop().expect("No key for signing"));
+ for s in signers {
+ signer = signer.add_signer(s);
+ }
+ let signer = signer.build().expect("Failed to create signer");
// Then, create a literal writer to wrap the data in a literal
// message packet.
diff --git a/ipc/tests/gpg-agent.rs b/ipc/tests/gpg-agent.rs
index d707b7b0..dab1fb74 100644
--- a/ipc/tests/gpg-agent.rs
+++ b/ipc/tests/gpg-agent.rs
@@ -94,7 +94,7 @@ fn sign() {
tpk.as_tsk().serialize(&mut buf).unwrap();
gpg_import(&ctx, &buf);
- let mut keypair = KeyPair::new(
+ let keypair = KeyPair::new(
&ctx, tpk.keys_valid().signing_capable().take(1).next().unwrap().2)
.unwrap();
@@ -104,9 +104,10 @@ fn sign() {
let message = Message::new(&mut message);
// We want to sign a literal data packet.
- let signer = Signer::new(message, vec![&mut keypair],
- HashAlgorithm::SHA512)
- .unwrap();
+ let signer = Signer::new(message, keypair)
+ // XXX: Is this necessary? If so, it shouldn't.
+ .hash_algo(HashAlgorithm::SHA512).unwrap()
+ .build().unwrap();
// Emit a literal data packet.
let mut literal_writer = LiteralWriter::new(
diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h
index 6aeca8e9..6dadcbc0 100644
--- a/openpgp-ffi/include/sequoia/openpgp.h
+++ b/openpgp-ffi/include/sequoia/openpgp.h
@@ -1583,6 +1583,12 @@ pgp_writer_stack_t pgp_arbitrary_writer_new (pgp_error_t *errp,
/// For every signing key, a signer writes a one-pass-signature
/// packet, then hashes and emits the data stream, then for every key
/// writes a signature packet.
+///
+/// The signers are consumed.
+///
+/// The hash is performed using the algorithm specified in
+/// `hash_algo`. Pass 0 for the default (which is what you usually
+/// want).
/*/
pgp_writer_stack_t pgp_signer_new (pgp_error_t *errp,
pgp_writer_stack_t inner,
diff --git a/openpgp-ffi/src/serialize.rs b/openpgp-ffi/src/serialize.rs
index e799888c..2b123673 100644
--- a/openpgp-ffi/src/serialize.rs
+++ b/openpgp-ffi/src/serialize.rs
@@ -15,7 +15,6 @@ extern crate time;
use self::openpgp::constants::{
AEADAlgorithm,
- HashAlgorithm,
SymmetricAlgorithm,
};
@@ -143,6 +142,8 @@ pub extern "C" fn pgp_arbitrary_writer_new
/// packet, then hashes and emits the data stream, then for every key
/// writes a signature packet.
///
+/// The signers are consumed.
+///
/// The hash is performed using the algorithm specified in
/// `hash_algo`. Pass 0 for the default (which is what you usually
/// want).
@@ -162,18 +163,23 @@ pub extern "C" fn pgp_signer_new
let signers = unsafe {
slice::from_raw_parts(signers, signers_len)
};
- let signers = signers.into_iter().map(
- |s| -> &mut dyn self::openpgp::crypto::Signer<_> {
- let signer = *s;
- ffi_param_ref_mut!(signer).as_mut()
- }
- ).collect();
- let hash_algo : Option<HashAlgorithm> = if hash_algo == 0 {
- None
- } else {
- Some(hash_algo.into())
- };
- ffi_try_box!(Signer::new(*inner, signers, hash_algo))
+ let mut signers = signers.iter().map(|s| {
+ *ffi_param_move!(*s)
+ }).collect::<Vec<_>>();
+
+ let mut signer =
+ Signer::new(*inner, ffi_try!(signers.pop().ok_or_else(|| {
+ failure::format_err!("signers is empty")
+ })));
+ for s in signers {
+ signer = signer.add_signer(s);
+ }
+
+ if hash_algo != 0 {
+ signer = ffi_try!(signer.hash_algo(hash_algo.into()));
+ }
+
+ ffi_try_box!(signer.build())
}
/// Creates a signer for a detached signature.
@@ -195,18 +201,23 @@ pub extern "C" fn pgp_signer_new_detached
let signers = unsafe {
slice::from_raw_parts(signers, signers_len)
};
- let signers = signers.into_iter().map(
- |s| -> &mut dyn self::openpgp::crypto::Signer<_> {
- let signer = *s;
- ffi_param_ref_mut!(signer).as_mut()
- }
- ).collect();
- let hash_algo : Option<HashAlgorithm> = if hash_algo == 0 {
- None
- } else {
- Some(hash_algo.into())
- };
- ffi_try_box!(Signer::detached(*inner, signers, hash_algo))
+ let mut signers = signers.iter().map(|s| {
+ *ffi_param_move!(*s)
+ }).collect::<Vec<_>>();
+
+ let mut signer =
+ Signer::new(*inner, ffi_try!(signers.pop().ok_or_else(|| {
+ failure::format_err!("signers is empty")
+ })));
+ for s in signers {
+ signer = signer.add_signer(s);
+ }
+
+ if hash_algo != 0 {
+ signer = ffi_try!(signer.hash_algo(hash_algo.into()));
+ }
+
+ ffi_try_box!(signer.detached().build())
}
/// Writes a literal data packet.
diff --git a/openpgp/examples/generate-sign-verify.rs b/openpgp/examples/generate-sign-verify.rs
index bddacc71..e22e5760 100644
--- a/openpgp/examples/generate-sign-verify.rs
+++ b/openpgp/examples/generate-sign-verify.rs
@@ -40,14 +40,14 @@ fn generate() -> openpgp::Result<openpgp::TPK> {
fn sign(sink: &mut dyn Write, plaintext: &str, tsk: &openpgp::TPK)
-> openpgp::Result<()> {
// Get the keypair to do the signing from the TPK.
- let mut keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2
+ let keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2
.clone().mark_parts_secret().into_keypair()?;
// Start streaming an OpenPGP message.
let message = Message::new(sink);
// We want to sign a literal data packet.
- let signer = Signer::new(message, vec![&mut keypair], None)?;
+ let signer = Signer::new(message, keypair).build()?;
// Emit a literal data packet.
let mut literal_writer = LiteralWriter::new(signer, None, None, None)?;
diff --git a/openpgp/examples/notarize.rs b/openpgp/examples/notarize.rs
index eedcc01e..c627d4f1 100644
--- a/openpgp/examples/notarize.rs
+++ b/openpgp/examples/notarize.rs
@@ -7,7 +7,6 @@ use std::io;
extern crate sequoia_openpgp as openpgp;
use crate::openpgp::{
armor,
- crypto,
Packet,
parse::{Parse, PacketParserResult},
serialize::Serialize,
@@ -60,14 +59,13 @@ fn main() {
// Stream an OpenPGP message.
let message = Message::new(sink);
- // Now, create a signer that emits a detached signature.
- let mut signer = Signer::new(
- message,
- keys.iter_mut()
- .map(|s| -> &mut dyn crypto::Signer<_> { s })
- .collect(),
- None)
- .expect("Failed to create signer");
+ // Now, create a signer that emits the signature(s).
+ let mut signer =
+ Signer::new(message, keys.pop().expect("No key for signing"));
+ for s in keys {
+ signer = signer.add_signer(s);
+ }
+ let mut signer = signer.build().expect("Failed to create signer");
// Create a parser for the message to be notarized.
let mut input = io::stdin();
diff --git a/openpgp/examples/sign-detached.rs b/openpgp/examples/sign-detached.rs
index d4d8d40d..98202bd2 100644
--- a/openpgp/examples/sign-detached.rs
+++ b/openpgp/examples/sign-detached.rs
@@ -6,7 +6,6 @@ extern crate rpassword;
extern crate sequoia_openpgp as openpgp;
use crate::openpgp::armor;
-use crate::openpgp::crypto;
use crate::openpgp::parse::Parse;
use crate::openpgp::serialize::stream::{Message, Signer};
@@ -56,12 +55,14 @@ fn main() {
// Stream an OpenPGP message.
let message = Message::new(sink);
- // Now, create a signer that emits a detached signature.
- let mut signer = Signer::detached(
- message,
- keys.iter_mut().map(|s| -> &mut dyn crypto::Signer<_> { s }).collect(),
- None)
- .expect("Failed to create signer");
+ // Now, create a signer that emits the detached signature(s).
+ let mut signer =
+ Signer::new(message, keys.pop().expect("No key for signing"));
+ for s in keys {
+ signer = signer.add_signer(s);
+ }
+ let mut signer =
+ signer.detached().build().expect("Failed to create signer");
// Copy all the data.
io::copy(&mut io::stdin(), &mut signer)
diff --git a/openpgp/examples/sign.rs b/openpgp/examples/sign.rs
index 7a7bcd91..2304865f 100644
--- a/openpgp/examples/sign.rs
+++ b/openpgp/examples/sign.rs
@@ -5,7 +5,6 @@ use std::io;
extern crate sequoia_openpgp as openpgp;
use crate::openpgp::armor;
-use crate::openpgp::crypto;
use crate::openpgp::parse::Parse;
use crate::openpgp::serialize::stream::{Message, LiteralWriter, Signer};
@@ -55,14 +54,13 @@ fn main() {
// Stream an OpenPGP message.
let message = Message::new(sink);
- // Now, create a signer that emits a signature.
- let signer = Signer::new(
- message,
- keys.iter_mut()
- .map(|s| -> &mut dyn crypto::Signer<_> { s })
- .collect(),
- None)
- .expect("Failed to create signer");
+ // Now, create a signer that emits the signature(s).
+ let mut signer =
+ Signer::new(message, keys.pop().expect("No key for signing"));
+ for s in keys {
+ signer = signer.add_signer(s);
+ }
+ let signer = signer.build().expect("Failed to create signer");
// Then, create a literal writer to wrap the data in a literal
// message packet.
diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs
index 9232bd14..144bcc4c 100644
--- a/openpgp/src/crypto/asymmetric.rs
+++ b/openpgp/src/crypto/asymmetric.rs
@@ -27,6 +27,17 @@ pub trait Signer<R>
-> Result<mpis::Signature>;
}
+impl<R: key::KeyRole> Signer<R> for Box<dyn Signer<R>> {
+ fn public(&self) -> &Key<key::PublicParts, R> {
+ self.as_ref().public()
+ }
+
+ fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
+ -> Result<mpis::Signature> {
+ self.as_mut().sign(hash_algo, digest)
+ }
+}
+
/// Decrypts a message.
///
/// This is a low-level mechanism to decrypt an arbitrary OpenPGP
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs
index 3f33e833..fff01171 100644
--- a/openpgp/src/parse/stream.rs
+++ b/openpgp/src/parse/stream.rs
@@ -1900,10 +1900,11 @@ mod test {
let mut buf = vec![];
{
let key = tpk.keys_all().signing_capable().nth(0).unwrap().2;
- let mut keypair = key.clone().mark_parts_secret().into_keypair().unwrap();
+ let keypair =
+ key.clone().mark_parts_secret().into_keypair().unwrap();
let m = Message::new(&mut buf);
- let signer = Signer::new(m, vec![&mut keypair], None).unwrap();
+ let signer = Signer::new(m, keypair).build().unwrap();
let mut ls = LiteralWriter::new(signer, None, None, None).unwrap();
ls.write_all(&mut vec![42u8; 30 * 1024 * 1024]).unwrap();
diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs
index 9d386675..38c14fa7 100644
--- a/openpgp/src/serialize/stream.rs
+++ b/openpgp/src/serialize/stream.rs
@@ -205,8 +205,8 @@ pub struct Signer<'a> {
// take our inner reader. If that happens, we only update the
// digests.
inner: Option<writer::BoxStack<'a, Cookie>>,
- signers: Vec<&'a mut dyn crypto::Signer<key::UnspecifiedRole>>,
- intended_recipients: Option<Vec<Fingerprint>>,
+ signers: Vec<Box<dyn crypto::Signer<key::UnspecifiedRole> + 'a>>,
+ intended_recipients: Vec<Fingerprint>,
detached: bool,
hash: crypto::hash::Context,
cookie: Cookie,
@@ -239,7 +239,7 @@ impl<'a> Signer<'a> {
/// let mut o = vec![];
/// {
/// let message = Message::new(&mut o);
- /// let signer = Signer::new(message, vec![&mut signing_keypair], None)?;
+ /// let signer = Signer::new(message, signing_keypair).build()?;
/// let mut ls = LiteralWriter::new(signer, None, None, None)?;
/// ls.write_all(b"Make it so, number one!")?;
/// ls.finalize()?;
@@ -273,34 +273,48 @@ impl<'a> Signer<'a> {
/// # Ok(())
/// # }
/// ```
- pub fn new<H>(inner: writer::Stack<'a, Cookie>,
- signers: Vec<&'a mut dyn crypto::Signer<
- key::UnspecifiedRole>>,
- hash_algo: H)
- -> Result<writer::Stack<'a, Cookie>>
- where H: Into<Option<HashAlgorithm>>
+ pub fn new<S>(inner: writer::Stack<'a, Cookie>, signer: S) -> Self
+ where S: crypto::Signer<key::UnspecifiedRole> + 'a
{
- Self::make(inner, signers, None, false,
- hash_algo.into().unwrap_or_default())
+ let inner = writer::BoxStack::from(inner);
+ let level = inner.cookie_ref().level + 1;
+ Signer {
+ inner: Some(inner),
+ signers: vec![Box::new(signer)],
+ intended_recipients: Vec::new(),
+ detached: false,
+ hash: HashAlgorithm::default().context().unwrap(),
+ cookie: Cookie {
+ level: level,
+ private: Private::Signer,
+ },
+ position: 0,
+ }
}
- /// Creates a signer with intended recipients.
+ /// Sets the hash algorithm to use for the signatures.
+ pub fn hash_algo(mut self, algo: HashAlgorithm) -> Result<Self> {
+ self.hash = algo.context()?;
+ Ok(self)
+ }
+
+ /// Adds an additional signer.
+ pub fn add_signer<S>(mut self, signer: S) -> Self
+ where S: crypto::Signer<key::UnspecifiedRole> + 'a
+ {
+ self.signers.push(Box::new(signer));
+ self
+ }
+
+ /// Adds an intended recipient.
///
/// This signer emits signatures indicating the intended
/// recipients of the encryption container containing the
/// signature. This prevents forwarding a signed message using a
/// different encryption context.
- pub fn with_intended_recipients<H>(inner: writer::Stack<'a, Cookie>,
- signers: Vec<&'a mut dyn crypto::Signer<
- key::UnspecifiedRole>>,
- recipients: &[&'a TPK],
- hash_algo: H)
- -> Result<writer::Stack<'a, Cookie>>
- where H: Into<Option<HashAlgorithm>>
- {
- Self::make(inner, signers,
- Some(recipients.iter().map(|r| r.fingerprint()).collect()),
- false, hash_algo.into().unwrap_or_default())
+ pub fn add_intended_recipient(mut self, recipient: &TPK) -> Self {
+ self.intended_recipients.push(recipient.fingerprint());
+ self
}
/// Creates a signer for a detached signature.
@@ -329,7 +343,7 @@ impl<'a> Signer<'a> {
/// {
/// let message = Message::new(&mut o);
/// let mut signer =
- /// Signer::detached(message, vec![&mut signing_keypair], None)?;
+ /// Signer::new(message, signing_keypair).detached().build()?;
/// signer.write_all(b"Make it so, number one!")?;
/// // In reality, just io::copy() the file to be signed.
/// signer.finalize()?;
@@ -365,56 +379,33 @@ impl<'a> Signer<'a> {
/// # Ok(())
/// # }
/// ```
- pub fn detached<H>(inner: writer::Stack<'a, Cookie>,
- signers: Vec<&'a mut dyn crypto::Signer<key::UnspecifiedRole>>,
- hash_algo: H)
- -> Result<writer::Stack<'a, Cookie>>
- where H: Into<Option<HashAlgorithm>>
- {
- Self::make(inner, signers, None, true,
- hash_algo.into().unwrap_or_default())
+ pub fn detached(mut self) -> Self {
+ self.detached = true;
+ self
}
- fn make(inner: writer::Stack<'a, Cookie>,
- signers: Vec<&'a mut dyn crypto::Signer<key::UnspecifiedRole>>,
- intended_recipients: Option<Vec<Fingerprint>>, detached: bool,
- hash_algo: HashAlgorithm)
- -> Result<writer::Stack<'a, Cookie>>
+ /// Finalizes the signer, returning the writer stack.
+ pub fn build(mut self) -> Result<writer::Stack<'a, Cookie>>
{
- let mut inner = writer::BoxStack::from(inner);
-
- if signers.len() == 0 {
- return Err(Error::InvalidArgument(
- "No signing keys given".into()).into());
- }
+ assert!(self.signers.len() > 0, "The constructor adds a signer.");
+ assert!(self.inner.is_some(), "The constructor adds an inner writer.");
- if ! detached {
+ if ! self.detached {
// For every key we collected, build and emit a one pass
// signature packet.
- for (i, keypair) in signers.iter().enumerate() {
+ for (i, keypair) in self.signers.iter().enumerate() {
let key = keypair.public();
let mut ops = OnePassSig3::new(SignatureType::Binary);
ops.set_pk_algo(key.pk_algo());
- ops.set_hash_algo(hash_algo);
+ ops.set_hash_algo(self.hash.algo());
ops.set_issuer(key.keyid());
- ops.set_last(i == signers.len() - 1);
- Packet::OnePassSig(ops.into()).serialize(&mut inner)?;
+ ops.set_last(i == self.signers.len() - 1);
+ Packet::OnePassSig(ops.into())
+ .serialize(self.inner.as_mut().unwrap())?;
}
}
- let level = inner.cookie_ref().level + 1;
- Ok(writer::Stack::from(Box::new(Signer {
- inner: Some(inner),
- signers: signers,
- intended_recipients: intended_recipients,
- detached: detached,
- hash: hash_algo.context()?,
- cookie: Cookie {
- level: level,
- private: Private::Signer,
- },
- position: 0,
- })))
+ Ok(writer::Stack::from(Box::new(self)))
}
fn emit_signatures(&mut self) -> Result<()> {
@@ -435,12 +426,13 @@ impl<'a> Signer<'a> {
// Issuer subpacket to be present.
.set_issuer(signer.public().keyid())?;
- if let Some(ref ir) = self.intended_recipients {
- sig = sig.set_intended_recipients(ir.clone())?;
+ if ! self.intended_recipients.is_empty() {
+ sig = sig.set_intended_recipients(
+ self.intended_recipients.clone())?;
}
// Compute the signature.
- let sig = sig.sign_hash(*signer, self.hash.algo(), hash)?;
+ let sig = sig.sign_hash(signer.as_mut(), self.hash.algo(), hash)?;
// And emit the packet.
Packet::Signature(sig).serialize(sink)?;
@@ -1405,13 +1397,11 @@ mod test {
}).collect::<Vec<KeyPair<_>>>();
let m = Message::new(&mut o);
- let signer = Signer::new(
- m,
- signers.iter_mut()
- .map(|s| -> &mut dyn crypto::Signer<_> {s})
- .collect(),
- None)
- .unwrap();
+ let mut signer = Signer::new(m, signers.pop().unwrap());
+ for s in signers.into_iter() {
+ signer = signer.add_signer(s);
+ }
+ let signer = signer.build().unwrap();
let mut ls = LiteralWriter::new(signer, None, None, None).unwrap();
ls.write_all(b"Tis, tis, tis. Tis is important.").unwrap();
let signer = ls.finalize_one().unwrap().unwrap();