diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-12-05 16:13:54 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-12-05 16:21:52 +0100 |
commit | 41fd3f08adff856ec558f8b06214e0f392893a26 (patch) | |
tree | e7894d4e77074109692503fab3b3b46d343f70b6 /openpgp | |
parent | 71a3a540bda400f52a841c04b8d33a51959fa8f0 (diff) |
openpgp: Make crypto::{Signer,Decryptor} non-polymorphic.
- These are low-level cryptographic traits that are not concerned
with the role of a key.
- Fixes #382.
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/examples/decrypt-with.rs | 3 | ||||
-rw-r--r-- | openpgp/src/cert/bindings.rs | 47 | ||||
-rw-r--r-- | openpgp/src/cert/mod.rs | 17 | ||||
-rw-r--r-- | openpgp/src/cert/revoke.rs | 32 | ||||
-rw-r--r-- | openpgp/src/crypto/asymmetric.rs | 48 | ||||
-rw-r--r-- | openpgp/src/packet/mod.rs | 9 | ||||
-rw-r--r-- | openpgp/src/packet/pkesk.rs | 3 | ||||
-rw-r--r-- | openpgp/src/packet/signature/mod.rs | 47 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 12 |
9 files changed, 91 insertions, 127 deletions
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index 537e8f8b..224a8726 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -10,7 +10,6 @@ extern crate sequoia_openpgp as openpgp; use crate::openpgp::crypto::{KeyPair, SessionKey}; use crate::openpgp::types::SymmetricAlgorithm; -use crate::openpgp::packet::key; use crate::openpgp::parse::{ Parse, stream::{ @@ -50,7 +49,7 @@ pub fn main() { /// keys for the signature verification and implements the /// verification policy. struct Helper { - keys: HashMap<openpgp::KeyID, KeyPair<key::UnspecifiedRole>>, + keys: HashMap<openpgp::KeyID, KeyPair>, } impl Helper { diff --git a/openpgp/src/cert/bindings.rs b/openpgp/src/cert/bindings.rs index 70ade707..c6d9e6c6 100644 --- a/openpgp/src/cert/bindings.rs +++ b/openpgp/src/cert/bindings.rs @@ -52,12 +52,11 @@ impl<P: key::KeyParts> Key<P, key::SubordinateRole> { /// // Check that we have an encryption subkey. /// assert_eq!(cert.keys_valid().key_flags(flags).count(), 1); /// # Ok(()) } - pub fn bind<T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature: signature::Builder, - creation_time: T) + pub fn bind<T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature: signature::Builder, + creation_time: T) -> Result<Signature> - where T: Into<Option<time::SystemTime>>, - R: key::KeyRole + where T: Into<Option<time::SystemTime>> { signature .set_signature_creation_time( @@ -110,12 +109,11 @@ impl UserID { /// // Check that we have a userid. /// assert_eq!(cert.userids().len(), 1); /// # Ok(()) } - pub fn bind<T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature: signature::Builder, - creation_time: T) - -> Result<Signature> - where T: Into<Option<time::SystemTime>>, - R: key::KeyRole + pub fn bind<T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature: signature::Builder, + creation_time: T) + -> Result<Signature> + where T: Into<Option<time::SystemTime>> { signature .set_signature_creation_time( @@ -180,14 +178,13 @@ impl UserID { /// // Check that we have a certification on the userid. /// assert_eq!(bob.userids().nth(0).unwrap().certifications().len(), 1); /// # Ok(()) } - pub fn certify<S, H, T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature_type: S, - hash_algo: H, creation_time: T) + pub fn certify<S, H, T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature_type: S, + hash_algo: H, creation_time: T) -> Result<Signature> where S: Into<Option<SignatureType>>, H: Into<Option<HashAlgorithm>>, - T: Into<Option<time::SystemTime>>, - R: key::KeyRole + T: Into<Option<time::SystemTime>> { let typ = signature_type.into(); let typ = match typ { @@ -257,12 +254,11 @@ impl UserAttribute { /// // Check that we have a user attribute. /// assert_eq!(cert.user_attributes().len(), 1); /// # Ok(()) } - pub fn bind<T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature: signature::Builder, - creation_time: T) + pub fn bind<T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature: signature::Builder, + creation_time: T) -> Result<Signature> - where T: Into<Option<time::SystemTime>>, - R: key::KeyRole + where T: Into<Option<time::SystemTime>> { signature .set_signature_creation_time( @@ -331,14 +327,13 @@ impl UserAttribute { /// assert_eq!(bob.user_attributes().nth(0).unwrap().certifications().len(), /// 1); /// # Ok(()) } - pub fn certify<S, H, T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature_type: S, - hash_algo: H, creation_time: T) + pub fn certify<S, H, T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature_type: S, + hash_algo: H, creation_time: T) -> Result<Signature> where S: Into<Option<SignatureType>>, H: Into<Option<HashAlgorithm>>, - T: Into<Option<time::SystemTime>>, - R: key::KeyRole + T: Into<Option<time::SystemTime>> { let typ = signature_type.into(); let typ = match typ { diff --git a/openpgp/src/cert/mod.rs b/openpgp/src/cert/mod.rs index 23db1bc8..d0999a95 100644 --- a/openpgp/src/cert/mod.rs +++ b/openpgp/src/cert/mod.rs @@ -1095,10 +1095,9 @@ impl Cert { /// # Ok(()) /// # } /// ``` - pub fn revoke_in_place<R>(self, primary_signer: &mut dyn Signer<R>, - code: ReasonForRevocation, reason: &[u8]) + pub fn revoke_in_place(self, primary_signer: &mut dyn Signer, + code: ReasonForRevocation, reason: &[u8]) -> Result<Cert> - where R: key::KeyRole { let sig = CertRevocationBuilder::new() .set_reason_for_revocation(code, reason)? @@ -1137,11 +1136,10 @@ impl Cert { /// /// This function exists to facilitate testing, which is why it is /// not exported. - fn set_expiry_as_of<R>(self, primary_signer: &mut dyn Signer<R>, - expiration: Option<time::Duration>, - now: time::SystemTime) + fn set_expiry_as_of(self, primary_signer: &mut dyn Signer, + expiration: Option<time::Duration>, + now: time::SystemTime) -> Result<Cert> - where R: key::KeyRole { let sig = { let (template, userid) = self @@ -1173,10 +1171,9 @@ impl Cert { /// /// Note: the time is relative to the key's creation time, not the /// current time! - pub fn set_expiry<R>(self, primary_signer: &mut dyn Signer<R>, - expiration: Option<time::Duration>) + pub fn set_expiry(self, primary_signer: &mut dyn Signer, + expiration: Option<time::Duration>) -> Result<Cert> - where R: key::KeyRole { self.set_expiry_as_of(primary_signer, expiration, time::SystemTime::now()) diff --git a/openpgp/src/cert/revoke.rs b/openpgp/src/cert/revoke.rs index f4f6e31c..a4876e0f 100644 --- a/openpgp/src/cert/revoke.rs +++ b/openpgp/src/cert/revoke.rs @@ -100,10 +100,9 @@ impl CertRevocationBuilder { /// Returns a revocation certificate for the cert `Cert` signed by /// `signer`. - pub fn build<H, R>(self, signer: &mut dyn Signer<R>, cert: &Cert, hash_algo: H) + pub fn build<H>(self, signer: &mut dyn Signer, cert: &Cert, hash_algo: H) -> Result<Signature> - where H: Into<Option<HashAlgorithm>>, - R: key::KeyRole + where H: Into<Option<HashAlgorithm>> { let hash_algo = hash_algo.into().unwrap_or(HashAlgorithm::SHA512); let mut hash = hash_algo.context()?; @@ -221,12 +220,11 @@ impl SubkeyRevocationBuilder { /// Returns a revocation certificate for the cert `Cert` signed by /// `signer`. - pub fn build<H, R>(mut self, signer: &mut dyn Signer<R>, - cert: &Cert, key: &key::PublicSubkey, - hash_algo: H) + pub fn build<H>(mut self, signer: &mut dyn Signer, + cert: &Cert, key: &key::PublicSubkey, + hash_algo: H) -> Result<Signature> - where H: Into<Option<HashAlgorithm>>, - R: key::KeyRole + where H: Into<Option<HashAlgorithm>> { let hash_algo = hash_algo.into().unwrap_or(HashAlgorithm::SHA512); let creation_time @@ -337,12 +335,11 @@ impl UserIDRevocationBuilder { /// Returns a revocation certificate for the cert `Cert` signed by /// `signer`. - pub fn build<H, R>(mut self, signer: &mut dyn Signer<R>, - cert: &Cert, userid: &UserID, - hash_algo: H) + pub fn build<H>(mut self, signer: &mut dyn Signer, + cert: &Cert, userid: &UserID, + hash_algo: H) -> Result<Signature> - where H: Into<Option<HashAlgorithm>>, - R: key::KeyRole + where H: Into<Option<HashAlgorithm>> { let hash_algo = hash_algo.into().unwrap_or(HashAlgorithm::SHA512); let creation_time @@ -456,12 +453,11 @@ impl UserAttributeRevocationBuilder { /// Returns a revocation certificate for the cert `Cert` signed by /// `signer`. - pub fn build<H, R>(mut self, signer: &mut dyn Signer<R>, - cert: &Cert, ua: &UserAttribute, - hash_algo: H) + pub fn build<H>(mut self, signer: &mut dyn Signer, + cert: &Cert, ua: &UserAttribute, + hash_algo: H) -> Result<Signature> - where H: Into<Option<HashAlgorithm>>, - R: key::KeyRole + where H: Into<Option<HashAlgorithm>> { let hash_algo = hash_algo.into().unwrap_or(HashAlgorithm::SHA512); let creation_time diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs index e67461ce..7185a471 100644 --- a/openpgp/src/crypto/asymmetric.rs +++ b/openpgp/src/crypto/asymmetric.rs @@ -16,19 +16,17 @@ use crate::Result; /// signature. Using this trait allows Sequoia to perform all /// operations involving signing to use a variety of secret key /// storage mechanisms (e.g. smart cards). -pub trait Signer<R> - where R: key::KeyRole -{ +pub trait Signer { /// Returns a reference to the public key. - fn public(&self) -> &Key<key::PublicParts, R>; + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole>; /// Creates a signature over the `digest` produced by `hash_algo`. fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8]) -> Result<mpis::Signature>; } -impl<R: key::KeyRole> Signer<R> for Box<dyn Signer<R>> { - fn public(&self) -> &Key<key::PublicParts, R> { +impl Signer for Box<dyn Signer> { + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { self.as_ref().public() } @@ -44,11 +42,9 @@ impl<R: key::KeyRole> Signer<R> for Box<dyn Signer<R>> { /// ciphertext. Using this trait allows Sequoia to perform all /// operations involving decryption to use a variety of secret key /// storage mechanisms (e.g. smart cards). -pub trait Decryptor<R> - where R: key::KeyRole -{ +pub trait Decryptor { /// Returns a reference to the public key. - fn public(&self) -> &Key<key::PublicParts, R>; + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole>; /// Decrypts `ciphertext`, returning the plain session key. fn decrypt(&mut self, ciphertext: &mpis::Ciphertext) @@ -64,18 +60,14 @@ pub trait Decryptor<R> /// [`Signer`]: trait.Signer.html /// [`Decryptor`]: trait.Decryptor.html #[derive(Clone)] -pub struct KeyPair<R> - where R: key::KeyRole -{ - public: Key<key::PublicParts, R>, +pub struct KeyPair { + public: Key<key::PublicParts, key::UnspecifiedRole>, secret: packet::key::Unencrypted, } -impl<R> KeyPair<R> - where R: key::KeyRole -{ +impl KeyPair { /// Creates a new key pair. - pub fn new(public: Key<key::PublicParts, R>, + pub fn new(public: Key<key::PublicParts, key::UnspecifiedRole>, secret: packet::key::Unencrypted) -> Result<Self> { @@ -86,7 +78,7 @@ impl<R> KeyPair<R> } /// Returns a reference to the public key. - pub fn public(&self) -> &Key<key::PublicParts, R> { + pub fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { &self.public } @@ -96,10 +88,8 @@ impl<R> KeyPair<R> } } -impl<R> Signer<R> for KeyPair<R> - where R: key::KeyRole -{ - fn public(&self) -> &Key<key::PublicParts, R> { +impl Signer for KeyPair { + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { &self.public } @@ -226,10 +216,8 @@ impl<R> Signer<R> for KeyPair<R> } } -impl<R> Decryptor<R> for KeyPair<R> - where R: key::KeyRole -{ - fn public(&self) -> &Key<key::PublicParts, R> { +impl Decryptor for KeyPair { + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { &self.public } @@ -274,10 +262,8 @@ impl<R> Decryptor<R> for KeyPair<R> } } -impl<R> From<KeyPair<R>> for Key<key::SecretParts, R> - where R: key::KeyRole -{ - fn from(p: KeyPair<R>) -> Self { +impl From<KeyPair> for Key<key::SecretParts, key::UnspecifiedRole> { + fn from(p: KeyPair) -> Self { let (mut key, secret) = (p.public, p.secret); key.set_secret(Some(secret.into())); key.mark_parts_secret().expect("XXX") diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs index fe756298..ca9a39de 100644 --- a/openpgp/src/packet/mod.rs +++ b/openpgp/src/packet/mod.rs @@ -744,7 +744,7 @@ impl<R: key::KeyRole> Key<key::SecretParts, R> { /// # Errors /// /// Fails if the secret key is missing, or encrypted. - pub fn into_keypair(mut self) -> Result<KeyPair<R>> { + pub fn into_keypair(mut self) -> Result<KeyPair> { use crate::packet::key::SecretKeyMaterial; let secret = match self.set_secret(None) { Some(SecretKeyMaterial::Unencrypted(secret)) => secret, @@ -756,7 +756,7 @@ impl<R: key::KeyRole> Key<key::SecretParts, R> { "no secret key".into()).into()), }; - KeyPair::new(self.into(), secret) + KeyPair::new(self.mark_role_unspecified().into(), secret) } } @@ -767,7 +767,7 @@ impl<R: key::KeyRole> key::Key4<key::SecretParts, R> { /// # Errors /// /// Fails if the secret key is missing, or encrypted. - pub fn into_keypair(mut self) -> Result<KeyPair<R>> { + pub fn into_keypair(mut self) -> Result<KeyPair> { use crate::packet::key::SecretKeyMaterial; let secret = match self.set_secret(None) { Some(SecretKeyMaterial::Unencrypted(secret)) => secret, @@ -779,7 +779,8 @@ impl<R: key::KeyRole> key::Key4<key::SecretParts, R> { "no secret key".into()).into()), }; - KeyPair::new(self.mark_parts_public().into(), secret) + KeyPair::new(self.mark_role_unspecified().mark_parts_public().into(), + secret) } } diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs index f307dd9c..db88c215 100644 --- a/openpgp/src/packet/pkesk.rs +++ b/openpgp/src/packet/pkesk.rs @@ -149,9 +149,8 @@ impl PKESK3 { /// Decrypts the ESK and returns the session key and symmetric algorithm /// used to encrypt the following payload. - pub fn decrypt<R>(&self, decryptor: &mut dyn Decryptor<R>) + pub fn decrypt(&self, decryptor: &mut dyn Decryptor) -> Result<(SymmetricAlgorithm, SessionKey)> - where R: key::KeyRole { let plain = decryptor.decrypt(&self.esk)?; let key_rgn = 1..(plain.len() - 2); diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs index 199f7a88..1740e727 100644 --- a/openpgp/src/packet/signature/mod.rs +++ b/openpgp/src/packet/signature/mod.rs @@ -138,9 +138,8 @@ impl Builder { /// /// The Signature's public-key algorithm field is set to the /// algorithm used by `signer`. - pub fn sign_standalone<R>(mut self, signer: &mut dyn Signer<R>) - -> Result<Signature> - where R: key::KeyRole + pub fn sign_standalone(mut self, signer: &mut dyn Signer) + -> Result<Signature> { self.pk_algo = signer.public().pk_algo(); let digest = Signature::standalone_hash(&self)?; @@ -151,9 +150,8 @@ impl Builder { /// /// The Signature's public-key algorithm field is set to the /// algorithm used by `signer`. - pub fn sign_timestamp<R>(mut self, signer: &mut dyn Signer<R>) - -> Result<Signature> - where R: key::KeyRole + pub fn sign_timestamp(mut self, signer: &mut dyn Signer) + -> Result<Signature> { self.pk_algo = signer.public().pk_algo(); let digest = Signature::timestamp_hash(&self)?; @@ -164,9 +162,8 @@ impl Builder { /// /// The Signature's public-key algorithm field is set to the /// algorithm used by `signer`. - pub fn sign_primary_key_binding<R>(mut self, signer: &mut dyn Signer<R>) + pub fn sign_primary_key_binding(mut self, signer: &mut dyn Signer) -> Result<Signature> - where R: key::KeyRole { self.pk_algo = signer.public().pk_algo(); let digest = @@ -181,11 +178,10 @@ impl Builder { /// /// The Signature's public-key algorithm field is set to the /// algorithm used by `signer`. - pub fn sign_userid_binding<R>(mut self, signer: &mut dyn Signer<R>, - key: &key::PublicKey, - userid: &UserID) + pub fn sign_userid_binding(mut self, signer: &mut dyn Signer, + key: &key::PublicKey, + userid: &UserID) -> Result<Signature> - where R: key::KeyRole { self.pk_algo = signer.public().pk_algo(); let digest = Signature::userid_binding_hash(&self, key, userid)?; @@ -197,12 +193,11 @@ impl Builder { /// /// The Signature's public-key algorithm field is set to the /// algorithm used by `signer`. - pub fn sign_subkey_binding<P, R>(mut self, signer: &mut dyn Signer<R>, - primary: &key::PublicKey, - subkey: &Key<P, key::SubordinateRole>) + pub fn sign_subkey_binding<P>(mut self, signer: &mut dyn Signer, + primary: &key::PublicKey, + subkey: &Key<P, key::SubordinateRole>) -> Result<Signature> - where P: key:: KeyParts, - R: key::KeyRole + where P: key:: KeyParts { self.pk_algo = signer.public().pk_algo(); let digest = Signature::subkey_binding_hash(&self, primary, subkey)?; @@ -214,11 +209,10 @@ impl Builder { /// /// The Signature's public-key algorithm field is set to the /// algorithm used by `signer`. - pub fn sign_user_attribute_binding<R>(mut self, signer: &mut dyn Signer<R>, - key: &key::PublicKey, - ua: &UserAttribute) + pub fn sign_user_attribute_binding(mut self, signer: &mut dyn Signer, + key: &key::PublicKey, + ua: &UserAttribute) -> Result<Signature> - where R: key::KeyRole { self.pk_algo = signer.public().pk_algo(); let digest = @@ -231,10 +225,9 @@ impl Builder { /// /// The Signature's public-key algorithm field is set to the /// algorithm used by `signer`. - pub fn sign_hash<R>(mut self, signer: &mut dyn Signer<R>, - mut hash: hash::Context) + pub fn sign_hash(mut self, signer: &mut dyn Signer, + mut hash: hash::Context) -> Result<Signature> - where R: key::KeyRole { // Fill out some fields, then hash the packet. self.pk_algo = signer.public().pk_algo(); @@ -252,9 +245,8 @@ impl Builder { /// /// The Signature's public-key algorithm field is set to the /// algorithm used by `signer`. - pub fn sign_message<R>(mut self, signer: &mut dyn Signer<R>, msg: &[u8]) + pub fn sign_message(mut self, signer: &mut dyn Signer, msg: &[u8]) -> Result<Signature> - where R: key::KeyRole { // Hash the message let mut hash = self.hash_algo.context()?; @@ -271,9 +263,8 @@ impl Builder { self.sign(signer, digest) } - fn sign<R>(self, signer: &mut dyn Signer<R>, digest: Vec<u8>) + fn sign(self, signer: &mut dyn Signer, digest: Vec<u8>) -> Result<Signature> - where R: key::KeyRole { let algo = self.hash_algo; let mpis = signer.sign(algo, &digest)?; diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index 0ee18a18..35b08b1a 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -203,7 +203,7 @@ pub struct Signer<'a> { // take our inner reader. If that happens, we only update the // digests. inner: Option<writer::BoxStack<'a, Cookie>>, - signers: Vec<Box<dyn crypto::Signer<key::UnspecifiedRole> + 'a>>, + signers: Vec<Box<dyn crypto::Signer + 'a>>, intended_recipients: Vec<Fingerprint>, detached: bool, hash: crypto::hash::Context, @@ -231,7 +231,7 @@ impl<'a> Signer<'a> { /// # let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().2 /// # .clone().mark_parts_secret().unwrap().into_keypair().unwrap(); /// # f(tsk, keypair).unwrap(); - /// # fn f(cert: Cert, mut signing_keypair: KeyPair<key::UnspecifiedRole>) + /// # fn f(cert: Cert, mut signing_keypair: KeyPair) /// # -> Result<()> { /// /// let mut o = vec![]; @@ -272,7 +272,7 @@ impl<'a> Signer<'a> { /// # } /// ``` pub fn new<S>(inner: writer::Stack<'a, Cookie>, signer: S) -> Self - where S: crypto::Signer<key::UnspecifiedRole> + 'a + where S: crypto::Signer + 'a { let inner = writer::BoxStack::from(inner); let level = inner.cookie_ref().level + 1; @@ -298,7 +298,7 @@ impl<'a> Signer<'a> { /// Adds an additional signer. pub fn add_signer<S>(mut self, signer: S) -> Self - where S: crypto::Signer<key::UnspecifiedRole> + 'a + where S: crypto::Signer + 'a { self.signers.push(Box::new(signer)); self @@ -334,7 +334,7 @@ impl<'a> Signer<'a> { /// # let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().2 /// # .clone().mark_parts_secret().unwrap().into_keypair().unwrap(); /// # f(tsk, keypair).unwrap(); - /// # fn f(cert: Cert, mut signing_keypair: KeyPair<key::UnspecifiedRole>) + /// # fn f(cert: Cert, mut signing_keypair: KeyPair) /// # -> Result<()> { /// /// let mut o = vec![]; @@ -1479,7 +1479,7 @@ mod test { let mut signers = keys.iter().map(|(_, key)| { key.clone().mark_parts_secret().unwrap().into_keypair() .expect("expected unencrypted secret key") - }).collect::<Vec<KeyPair<_>>>(); + }).collect::<Vec<KeyPair>>(); let m = Message::new(&mut o); let mut signer = Signer::new(m, signers.pop().unwrap()); |