diff options
Diffstat (limited to 'openpgp/src/serialize/stream.rs')
-rw-r--r-- | openpgp/src/serialize/stream.rs | 64 |
1 files changed, 57 insertions, 7 deletions
diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index 8dddcc4b..0e13e627 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -1245,7 +1245,7 @@ impl<'a> Signer<'a> { assert!(!self.signers.is_empty(), "The constructor adds a signer."); assert!(self.inner.is_some(), "The constructor adds an inner writer."); - for (keypair, signer_hash, _signer_salt) in self.signers.iter_mut() { + for (keypair, signer_hash, signer_salt) in self.signers.iter_mut() { // First, compute a suitable hash algorithm, starting with // the one configured using Self::hash_algo. let mut acceptable_hashes = @@ -1273,7 +1273,7 @@ impl<'a> Signer<'a> { } let algo = acceptable_hashes[0]; *signer_hash = algo; - let hash = algo.context()?; + let mut hash = algo.context()?; match keypair.public().version() { 4 => { @@ -1281,11 +1281,32 @@ impl<'a> Signer<'a> { if self.template.typ() == SignatureType::Text || self.mode == SignatureMode::Cleartext { - HashingMode::Text(hash) + HashingMode::Text(vec![], hash) } else { - HashingMode::Binary(hash) + HashingMode::Binary(vec![], hash) }); }, + 6 => { + // Version 6 signatures are salted, and we + // need to include it in the OPS packet. + // Generate and remember the salt here. + let mut salt = vec![0; algo.salt_size()?]; + crate::crypto::random(&mut salt); + + // Add the salted context. + hash.update(&salt); + self.hashes.push( + if self.template.typ() == SignatureType::Text + || self.mode == SignatureMode::Cleartext + { + HashingMode::Text(salt.clone(), hash) + } else { + HashingMode::Binary(salt.clone(), hash) + }); + + // And remember which signer used which salt. + *signer_salt = salt; + }, v => return Err(Error::InvalidOperation( format!("Unsupported Key version {}", v)).into()), } @@ -1296,7 +1317,7 @@ impl<'a> Signer<'a> { // For every key we collected, build and emit a one pass // signature packet. let signers_count = self.signers.len(); - for (i, (keypair, hash_algo, _salt)) in + for (i, (keypair, hash_algo, salt)) in self.signers.iter().enumerate() { let last = i == signers_count - 1; @@ -1312,6 +1333,18 @@ impl<'a> Signer<'a> { Packet::from(ops) .serialize(self.inner.as_mut().unwrap())?; }, + 6 => { + // Version 6 signatures are salted, and we + // need to include it in the OPS packet. + let mut ops = OnePassSig6::new( + self.template.typ(), key.fingerprint()); + ops.set_pk_algo(key.pk_algo()); + ops.set_hash_algo(*hash_algo); + ops.set_salt(salt.clone()); + ops.set_last(last); + Packet::from(ops) + .serialize(self.inner.as_mut().unwrap())?; + }, v => return Err(Error::InvalidOperation( format!("Unsupported Key version {}", v)).into()), } @@ -1381,14 +1414,15 @@ impl<'a> Signer<'a> { // Emit the signatures in reverse, so that the // one-pass-signature and signature packets "bracket" the // message. - for (signer, algo, _signer_salt) in self.signers.iter_mut().rev() { + for (signer, algo, signer_salt) in self.signers.iter_mut().rev() { let (mut sig, hash) = match signer.public().version() { 4 => { // V4 signature. let hash = self.hashes.iter() .find_map(|hash| { - if hash.as_ref().algo() == *algo + if hash.salt().is_empty() + && hash.as_ref().algo() == *algo { Some(hash.clone()) } else { @@ -1402,6 +1436,22 @@ impl<'a> Signer<'a> { (sig, hash) }, + 6 => { + // V6 signature. + let hash = self.hashes.iter() + .find_map(|hash| if signer_salt == hash.salt() { + Some(hash.clone()) + } else { + None + }) + .expect("we put it in there"); + + // Make and hash a signature packet. + let sig = self.template.clone() + .set_prefix_salt(signer_salt.clone()).0; + + (sig, hash) + }, v => return Err(Error::InvalidOperation( format!("Unsupported Key version {}", v)).into()), }; |