diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-05-28 22:21:47 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-05-30 12:09:47 +0200 |
commit | be8bf91c14485a844a2c6143893105a21fd6f26e (patch) | |
tree | b2e632196964ebe6e94fb709b77d24d031c0ea2f | |
parent | a0378343f6f0d311021437435c14670a6d7dc3e2 (diff) |
openpgp: Make PKESK::decrypt use crypto::Decryptor.
-rw-r--r-- | guide/src/chapter_02.md | 28 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/pkesk.rs | 20 | ||||
-rw-r--r-- | openpgp/examples/decrypt-with.rs | 4 | ||||
-rw-r--r-- | openpgp/examples/generate-encrypt-decrypt.rs | 4 | ||||
-rw-r--r-- | openpgp/src/packet/key.rs | 24 | ||||
-rw-r--r-- | openpgp/src/packet/pkesk.rs | 143 | ||||
-rw-r--r-- | tool/src/commands/decrypt.rs | 15 |
7 files changed, 93 insertions, 145 deletions
diff --git a/guide/src/chapter_02.md b/guide/src/chapter_02.md index f66e15b3..06d38342 100644 --- a/guide/src/chapter_02.md +++ b/guide/src/chapter_02.md @@ -121,11 +121,11 @@ fn main() { # let key = self.secret.subkeys().nth(0) # .map(|binding| binding.subkey().clone()) # .unwrap(); -# +# # // The secret key is not encrypted. -# let pair = key.into_keypair().unwrap(); -# -# pkesks[0].decrypt(pair.public(), pair.secret()) +# let mut pair = key.into_keypair().unwrap(); +# +# pkesks[0].decrypt(&mut pair) # .and_then(|(algo, session_key)| decrypt(algo, &session_key)) # .map(|_| None) # // XXX: In production code, return the Fingerprint of the @@ -255,11 +255,11 @@ fn generate() -> openpgp::Result<openpgp::TPK> { # let key = self.secret.subkeys().nth(0) # .map(|binding| binding.subkey().clone()) # .unwrap(); -# +# # // The secret key is not encrypted. -# let pair = key.into_keypair().unwrap(); -# -# pkesks[0].decrypt(pair.public(), pair.secret()) +# let mut pair = key.into_keypair().unwrap(); +# +# pkesks[0].decrypt(&mut pair) # .and_then(|(algo, session_key)| decrypt(algo, &session_key)) # .map(|_| None) # // XXX: In production code, return the Fingerprint of the @@ -389,11 +389,11 @@ fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK) # let key = self.secret.subkeys().nth(0) # .map(|binding| binding.subkey().clone()) # .unwrap(); -# +# # // The secret key is not encrypted. -# let pair = key.into_keypair().unwrap(); -# -# pkesks[0].decrypt(pair.public(), pair.secret()) +# let mut pair = key.into_keypair().unwrap(); +# +# pkesks[0].decrypt(&mut pair) # .and_then(|(algo, session_key)| decrypt(algo, &session_key)) # .map(|_| None) # // XXX: In production code, return the Fingerprint of the @@ -539,9 +539,9 @@ impl<'a> DecryptionHelper for Helper<'a> { .unwrap(); // The secret key is not encrypted. - let pair = key.into_keypair().unwrap(); + let mut pair = key.into_keypair().unwrap(); - pkesks[0].decrypt(pair.public(), pair.secret()) + pkesks[0].decrypt(&mut pair) .and_then(|(algo, session_key)| decrypt(algo, &session_key)) .map(|_| None) // XXX: In production code, return the Fingerprint of the diff --git a/openpgp-ffi/src/packet/pkesk.rs b/openpgp-ffi/src/packet/pkesk.rs index af87be5f..e50f0cc9 100644 --- a/openpgp-ffi/src/packet/pkesk.rs +++ b/openpgp-ffi/src/packet/pkesk.rs @@ -4,7 +4,7 @@ use failure; use libc::{uint8_t, size_t}; extern crate sequoia_openpgp as openpgp; -use self::openpgp::packet::{PKESK, key::SecretKey}; +use self::openpgp::packet::PKESK; use super::super::keyid::KeyID; use super::super::packet::key::Key; @@ -44,9 +44,9 @@ pub extern "C" fn pgp_pkesk_decrypt(errp: Option<&mut *mut ::error::Error>, let algo = ffi_param_ref_mut!(algo); let key_len = ffi_param_ref_mut!(key_len); - match secret_key.secret() { - Some(SecretKey::Unencrypted{ mpis: secret_parts }) => { - match pkesk.decrypt(secret_key, secret_parts) { + match secret_key.clone().into_keypair() { + Ok(mut keypair) => { + match pkesk.decrypt(&mut keypair) { Ok((a, k)) => { *algo = a.into(); if !key.is_null() && *key_len >= k.len() { @@ -61,14 +61,10 @@ pub extern "C" fn pgp_pkesk_decrypt(errp: Option<&mut *mut ::error::Error>, }, Err(e) => ffi_try_status!(Err::<(), failure::Error>(e)), } - } - Some(thing @ SecretKey::Encrypted{ .. }) => { + }, + Err(e) => { // XXX: Better message, don't panic. - panic!("Secret parts not unencrypted: {:?}", thing); - } - None => { - // XXX: Better message, don't panic. - panic!("No secret parts: {:?}", secret_key.secret()); - } + panic!("Secret parts not unencrypted in {:?}: {}", secret_key, e); + }, } } diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index 63582299..a13dc98b 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -87,8 +87,8 @@ impl DecryptionHelper for Helper { { // Try each PKESK until we succeed. for pkesk in pkesks { - if let Some(pair) = self.keys.get(pkesk.recipient()) { - if let Ok(_) = pkesks[0].decrypt(pair.public(), pair.secret()) + if let Some(pair) = self.keys.get_mut(pkesk.recipient()) { + if let Ok(_) = pkesks[0].decrypt(pair) .and_then(|(algo, session_key)| decrypt(algo, &session_key)) { break; diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs index 4645cb0c..8a450d24 100644 --- a/openpgp/examples/generate-encrypt-decrypt.rs +++ b/openpgp/examples/generate-encrypt-decrypt.rs @@ -114,9 +114,9 @@ impl<'a> DecryptionHelper for Helper<'a> { .unwrap(); // The secret key is not encrypted. - let pair = key.into_keypair().unwrap(); + let mut pair = key.into_keypair().unwrap(); - pkesks[0].decrypt(pair.public(), pair.secret()) + pkesks[0].decrypt(&mut pair) .and_then(|(algo, session_key)| decrypt(algo, &session_key)) .map(|_| None) // XXX: In production code, return the Fingerprint of the diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs index 42339644..56416de3 100644 --- a/openpgp/src/packet/key.rs +++ b/openpgp/src/packet/key.rs @@ -798,7 +798,6 @@ mod tests { #[test] fn encryption_roundtrip() { - use packet::key::SecretKey; use crypto::SessionKey; use constants::Curve::*; @@ -810,21 +809,13 @@ mod tests { for key in keys.into_iter() { let key = Key::from(key); - let secret = - if let Some(SecretKey::Unencrypted { - ref mpis, - }) = key.secret() { - mpis.clone() - } else { - unreachable!() - }; - + let mut keypair = key.clone().into_keypair().unwrap(); let cipher = SymmetricAlgorithm::AES256; let sk = SessionKey::new(&mut Default::default(), cipher.key_size().unwrap()); let pkesk = PKESK3::for_recipient(cipher, &sk, &key).unwrap(); - let (cipher_, sk_) = pkesk.decrypt(&key, &secret).unwrap(); + let (cipher_, sk_) = pkesk.decrypt(&mut keypair).unwrap(); assert_eq!(cipher, cipher_); assert_eq!(sk, sk_); @@ -956,14 +947,11 @@ mod tests { let dek = b"\xA5\x58\x3A\x04\x35\x8B\xC7\x3F\x4A\xEF\x0C\x5A\xEB\xED\x59\xCA\xFD\x96\xB5\x32\x23\x26\x0C\x91\x78\xD1\x31\x12\xF0\x41\x42\x9D"; let sk = SessionKey::from(Vec::from(&dek[..])); - // Expected - let sec = match key.secret() { - Some(&SecretKey::Unencrypted{ ref mpis }) => mpis, - _ => unreachable!(), - }; - let got_sk = pkesk.decrypt(&key, sec).unwrap(); + // Expected + let mut decryptor = key.into_keypair().unwrap(); + let got_sk = pkesk.decrypt(&mut decryptor).unwrap(); - assert_eq!(got_sk.1, sk); + assert_eq!(got_sk.1, sk); } #[test] diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs index ad56d03a..1f638da6 100644 --- a/openpgp/src/packet/pkesk.rs +++ b/openpgp/src/packet/pkesk.rs @@ -10,6 +10,7 @@ use quickcheck::{Arbitrary, Gen}; use Error; use packet::Key; use KeyID; +use crypto::Decryptor; use crypto::mpis::{self, MPI, Ciphertext}; use Packet; use PublicKeyAlgorithm; @@ -144,46 +145,10 @@ impl PKESK3 { /// Decrypts the ESK and returns the session key and symmetric algorithm /// used to encrypt the following payload. - pub fn decrypt(&self, recipient: &Key, recipient_sec: &mpis::SecretKey) + pub fn decrypt(&self, decryptor: &mut Decryptor) -> Result<(SymmetricAlgorithm, SessionKey)> { - use PublicKeyAlgorithm::*; - use crypto::mpis::PublicKey; - use nettle::rsa; - - let plain: SessionKey = match - (self.pk_algo, recipient.mpis(), recipient_sec, &self.esk) - { - (RSAEncryptSign, - &PublicKey::RSA{ ref e, ref n }, - &mpis::SecretKey::RSA{ ref p, ref q, ref d, .. }, - &mpis::Ciphertext::RSA{ ref c }) => { - let public = rsa::PublicKey::new(&n.value, &e.value)?; - let secret = rsa::PrivateKey::new(&d.value, &p.value, - &q.value, Option::None)?; - let mut rand = Yarrow::default(); - rsa::decrypt_pkcs1(&public, &secret, &mut rand, &c.value)? - } - - (ElgamalEncrypt, - &PublicKey::Elgamal{ .. }, - &mpis::SecretKey::Elgamal{ .. }, - &mpis::Ciphertext::Elgamal{ .. }) => - return Err( - Error::UnsupportedPublicKeyAlgorithm(self.pk_algo).into()), - - (ECDH, - PublicKey::ECDH{ .. }, - mpis::SecretKey::ECDH { .. }, - mpis::Ciphertext::ECDH { .. }) => - ecdh::unwrap_session_key(recipient, recipient_sec, &self.esk)?, - - (algo, public, secret, cipher) => - return Err(Error::MalformedPacket(format!( - "unsupported combination of algorithm {:?}, key pair {:?}/{:?} and ciphertext {:?}", - algo, public, secret, cipher)).into()), - }.into(); - + let plain = decryptor.decrypt(&self.esk)?; let key_rgn = 1..(plain.len() - 2); let sym_algo: SymmetricAlgorithm = plain[0].into(); let mut key: SessionKey = vec![0u8; sym_algo.key_size()?].into(); @@ -258,20 +223,18 @@ mod tests { ::tests::key("testy-private.pgp")).unwrap(); let pile = PacketPile::from_bytes( ::tests::message("encrypted-to-testy.gpg")).unwrap(); - let pair = tpk.subkeys().next().unwrap().subkey(); + let mut keypair = + tpk.subkeys().next().unwrap() + .subkey().clone().into_keypair().unwrap(); - if let Some(SecretKey::Unencrypted{ mpis: ref sec }) = pair.secret() { - let pkg = pile.descendants().skip(0).next().clone(); + let pkg = pile.descendants().skip(0).next().clone(); - if let Some(Packet::PKESK(ref pkesk)) = pkg { - let plain = pkesk.decrypt(&pair, sec).unwrap(); + if let Some(Packet::PKESK(ref pkesk)) = pkg { + let plain = pkesk.decrypt(&mut keypair).unwrap(); - eprintln!("plain: {:?}", plain); - } else { - panic!("message is not a PKESK packet"); - } + eprintln!("plain: {:?}", plain); } else { - panic!("secret key is encrypted/missing"); + panic!("message is not a PKESK packet"); } } @@ -281,20 +244,18 @@ mod tests { ::tests::key("testy-new-private.pgp")).unwrap(); let pile = PacketPile::from_bytes( ::tests::message("encrypted-to-testy-new.pgp")).unwrap(); - let pair = tpk.subkeys().next().unwrap().subkey(); + let mut keypair = + tpk.subkeys().next().unwrap() + .subkey().clone().into_keypair().unwrap(); - if let Some(SecretKey::Unencrypted{ mpis: ref sec }) = pair.secret() { - let pkg = pile.descendants().skip(0).next().clone(); + let pkg = pile.descendants().skip(0).next().clone(); - if let Some(Packet::PKESK(ref pkesk)) = pkg { - let plain = pkesk.decrypt(&pair, sec).unwrap(); + if let Some(Packet::PKESK(ref pkesk)) = pkg { + let plain = pkesk.decrypt(&mut keypair).unwrap(); - eprintln!("plain: {:?}", plain); - } else { - panic!("message is not a PKESK packet"); - } + eprintln!("plain: {:?}", plain); } else { - panic!("secret key is encrypted/missing"); + panic!("message is not a PKESK packet"); } } @@ -304,20 +265,18 @@ mod tests { ::tests::key("testy-nistp256-private.pgp")).unwrap(); let pile = PacketPile::from_bytes( ::tests::message("encrypted-to-testy-nistp256.pgp")).unwrap(); - let pair = tpk.subkeys().next().unwrap().subkey(); + let mut keypair = + tpk.subkeys().next().unwrap() + .subkey().clone().into_keypair().unwrap(); - if let Some(SecretKey::Unencrypted{ mpis: ref sec }) = pair.secret() { - let pkg = pile.descendants().skip(0).next().clone(); + let pkg = pile.descendants().skip(0).next().clone(); - if let Some(Packet::PKESK(ref pkesk)) = pkg { - let plain = pkesk.decrypt(&pair, sec).unwrap(); + if let Some(Packet::PKESK(ref pkesk)) = pkg { + let plain = pkesk.decrypt(&mut keypair).unwrap(); - eprintln!("plain: {:?}", plain); - } else { - panic!("message is not a PKESK packet"); - } + eprintln!("plain: {:?}", plain); } else { - panic!("secret key is encrypted/missing"); + panic!("message is not a PKESK packet"); } } @@ -327,20 +286,18 @@ mod tests { ::tests::key("testy-nistp384-private.pgp")).unwrap(); let pile = PacketPile::from_bytes( ::tests::message("encrypted-to-testy-nistp384.pgp")).unwrap(); - let pair = tpk.subkeys().next().unwrap().subkey(); + let mut keypair = + tpk.subkeys().next().unwrap() + .subkey().clone().into_keypair().unwrap(); - if let Some(SecretKey::Unencrypted{ mpis: ref sec }) = pair.secret() { - let pkg = pile.descendants().skip(0).next().clone(); + let pkg = pile.descendants().skip(0).next().clone(); - if let Some(Packet::PKESK(ref pkesk)) = pkg { - let plain = pkesk.decrypt(&pair, sec).unwrap(); + if let Some(Packet::PKESK(ref pkesk)) = pkg { + let plain = pkesk.decrypt(&mut keypair).unwrap(); - eprintln!("plain: {:?}", plain); - } else { - panic!("message is not a PKESK packet"); - } + eprintln!("plain: {:?}", plain); } else { - panic!("secret key is encrypted/missing"); + panic!("message is not a PKESK packet"); } } @@ -350,20 +307,18 @@ mod tests { ::tests::key("testy-nistp521-private.pgp")).unwrap(); let pile = PacketPile::from_bytes( ::tests::message("encrypted-to-testy-nistp521.pgp")).unwrap(); - let pair = tpk.subkeys().next().unwrap().subkey(); + let mut keypair = + tpk.subkeys().next().unwrap() + .subkey().clone().into_keypair().unwrap(); - if let Some(SecretKey::Unencrypted{ mpis: ref sec }) = pair.secret() { - let pkg = pile.descendants().skip(0).next().clone(); + let pkg = pile.descendants().skip(0).next().clone(); - if let Some(Packet::PKESK(ref pkesk)) = pkg { - let plain = pkesk.decrypt(&pair, sec).unwrap(); + if let Some(Packet::PKESK(ref pkesk)) = pkg { + let plain = pkesk.decrypt(&mut keypair).unwrap(); - eprintln!("plain: {:?}", plain); - } else { - panic!("message is not a PKESK packet"); - } + eprintln!("plain: {:?}", plain); } else { - panic!("secret key is encrypted/missing"); + panic!("message is not a PKESK packet"); } } @@ -403,14 +358,18 @@ mod tests { let private_mpis = mpis::SecretKey::ECDH { scalar: MPI::new(&sec[..]), }; - let key: Key = Key4::new(time::now().canonicalize(), - PublicKeyAlgorithm::ECDH, public_mpis, None) + let mut key: Key = Key4::new(time::now().canonicalize(), + PublicKeyAlgorithm::ECDH, + public_mpis, None) .unwrap().into(); + key.set_secret(Some(SecretKey::Unencrypted { + mpis: private_mpis, + })); let mut rng = Yarrow::default(); let sess_key = SessionKey::new(&mut rng, 32); let pkesk = PKESK3::for_recipient(SymmetricAlgorithm::AES256, &sess_key, &key).unwrap(); - - pkesk.decrypt(&key, &private_mpis).unwrap(); + let mut keypair = key.into_keypair().unwrap(); + pkesk.decrypt(&mut keypair).unwrap(); } } diff --git a/tool/src/commands/decrypt.rs b/tool/src/commands/decrypt.rs index c762c454..a8c72f96 100644 --- a/tool/src/commands/decrypt.rs +++ b/tool/src/commands/decrypt.rs @@ -122,8 +122,9 @@ impl<'a> DecryptionHelper for Helper<'a> { for pkesk in pkesks { let keyid = pkesk.recipient(); if let Some(key) = self.secret_keys.get(&keyid) { - if let Some(SecretKey::Unencrypted { mpis }) = key.secret() { - if let Ok(sk) = pkesks[0].decrypt(key, mpis) + if let Some(SecretKey::Unencrypted { .. }) = key.secret() { + if let Ok(sk) = key.clone().into_keypair() + .and_then(|mut keypair| pkesks[0].decrypt(&mut keypair)) .and_then(|(algo, sk)| { decrypt(algo, &sk)?; Ok(sk) }) { if self.dump_session_key { @@ -159,10 +160,14 @@ impl<'a> DecryptionHelper for Helper<'a> { self.key_hints.get(&keyid).unwrap()))) ?.into(); - if let Ok(mpis) = - key.secret().unwrap().decrypt(key.pk_algo(), &p) + let mut key = key.clone(); + let algo = key.pk_algo(); + if let Some(()) = + key.secret_mut() + .and_then(|s| s.decrypt_in_place(algo, &p).ok()) { - match pkesk.decrypt(key, &mpis) + let mut keypair = key.into_keypair().unwrap(); + match pkesk.decrypt(&mut keypair) .and_then(|(algo, sk)| { decrypt(algo, &sk)?; Ok(sk) }) |