summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--guide/src/chapter_02.md142
-rw-r--r--openpgp-ffi/examples/decrypt-with.c31
-rw-r--r--openpgp-ffi/include/sequoia/openpgp.h8
-rw-r--r--openpgp-ffi/include/sequoia/openpgp/types.h13
-rw-r--r--openpgp-ffi/src/parse/stream.rs150
-rw-r--r--openpgp/examples/decrypt-with.rs53
-rw-r--r--openpgp/examples/generate-encrypt-decrypt.rs34
-rw-r--r--openpgp/src/crypto/asymmetric.rs10
-rw-r--r--openpgp/src/parse/stream.rs154
-rw-r--r--tool/src/commands/decrypt.rs156
10 files changed, 325 insertions, 426 deletions
diff --git a/guide/src/chapter_02.md b/guide/src/chapter_02.md
index 0afcf3f3..2a23b65b 100644
--- a/guide/src/chapter_02.md
+++ b/guide/src/chapter_02.md
@@ -12,9 +12,10 @@ fragments yields the [`openpgp/examples/generate-encrypt-decrypt.rs`].
use std::io::{self, Write};
extern crate sequoia_openpgp as openpgp;
+use openpgp::crypto::SessionKey;
+use openpgp::constants::SymmetricAlgorithm;
use openpgp::serialize::stream::*;
use openpgp::parse::stream::*;
-use openpgp::packet::key::SecretKey;
const MESSAGE: &'static str = "дружба";
@@ -109,31 +110,26 @@ fn main() {
# }
#
# impl<'a> DecryptionHelper for Helper<'a> {
-# fn get_secret(&mut self,
-# _pkesks: &[&openpgp::packet::PKESK],
-# _skesks: &[&openpgp::packet::SKESK])
-# -> openpgp::Result<Option<Secret>>
+# fn decrypt<D>(&mut self,
+# pkesks: &[openpgp::packet::PKESK],
+# _skesks: &[openpgp::packet::SKESK],
+# mut decrypt: D)
+# -> openpgp::Result<Option<openpgp::Fingerprint>>
+# where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()>
# {
# // The encryption key is the first and only subkey.
# let key = self.secret.subkeys().nth(0)
# .map(|binding| binding.subkey().clone())
# .unwrap();
-#
+#
# // The secret key is not encrypted.
-# let secret =
-# if let Some(SecretKey::Unencrypted {
-# ref mpis,
-# }) = key.secret() {
-# mpis.clone()
-# } else {
-# unreachable!()
-# };
-#
-# Ok(Some(Secret::Asymmetric {
-# identity: self.secret.fingerprint(),
-# key: key,
-# secret: secret,
-# }))
+# let pair = key.into_keypair().unwrap();
+#
+# pkesks[0].decrypt(pair.public(), pair.secret())
+# .and_then(|(algo, session_key)| decrypt(algo, &session_key))
+# .map(|_| None)
+# // XXX: In production code, return the Fingerprint of the
+# // recipient's TPK here
# }
# }
```
@@ -150,9 +146,10 @@ create it:
# use std::io::{self, Write};
#
# extern crate sequoia_openpgp as openpgp;
+# use openpgp::crypto::SessionKey;
+# use openpgp::constants::SymmetricAlgorithm;
# use openpgp::serialize::stream::*;
# use openpgp::parse::stream::*;
-# use openpgp::packet::key::SecretKey;
#
# const MESSAGE: &'static str = "дружба";
#
@@ -247,31 +244,26 @@ fn generate() -> openpgp::Result<openpgp::TPK> {
# }
#
# impl<'a> DecryptionHelper for Helper<'a> {
-# fn get_secret(&mut self,
-# _pkesks: &[&openpgp::packet::PKESK],
-# _skesks: &[&openpgp::packet::SKESK])
-# -> openpgp::Result<Option<Secret>>
+# fn decrypt<D>(&mut self,
+# pkesks: &[openpgp::packet::PKESK],
+# _skesks: &[openpgp::packet::SKESK],
+# mut decrypt: D)
+# -> openpgp::Result<Option<openpgp::Fingerprint>>
+# where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()>
# {
# // The encryption key is the first and only subkey.
# let key = self.secret.subkeys().nth(0)
# .map(|binding| binding.subkey().clone())
# .unwrap();
-#
+#
# // The secret key is not encrypted.
-# let secret =
-# if let Some(SecretKey::Unencrypted {
-# ref mpis,
-# }) = key.secret() {
-# mpis.clone()
-# } else {
-# unreachable!()
-# };
-#
-# Ok(Some(Secret::Asymmetric {
-# identity: self.secret.fingerprint(),
-# key: key,
-# secret: secret,
-# }))
+# let pair = key.into_keypair().unwrap();
+#
+# pkesks[0].decrypt(pair.public(), pair.secret())
+# .and_then(|(algo, session_key)| decrypt(algo, &session_key))
+# .map(|_| None)
+# // XXX: In production code, return the Fingerprint of the
+# // recipient's TPK here
# }
# }
```
@@ -288,9 +280,10 @@ implements [`io::Write`], and we simply write the plaintext to it.
# use std::io::{self, Write};
#
# extern crate sequoia_openpgp as openpgp;
+# use openpgp::crypto::SessionKey;
+# use openpgp::constants::SymmetricAlgorithm;
# use openpgp::serialize::stream::*;
# use openpgp::parse::stream::*;
-# use openpgp::packet::key::SecretKey;
#
# const MESSAGE: &'static str = "дружба";
#
@@ -385,31 +378,26 @@ fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK)
# }
#
# impl<'a> DecryptionHelper for Helper<'a> {
-# fn get_secret(&mut self,
-# _pkesks: &[&openpgp::packet::PKESK],
-# _skesks: &[&openpgp::packet::SKESK])
-# -> openpgp::Result<Option<Secret>>
+# fn decrypt<D>(&mut self,
+# pkesks: &[openpgp::packet::PKESK],
+# _skesks: &[openpgp::packet::SKESK],
+# mut decrypt: D)
+# -> openpgp::Result<Option<openpgp::Fingerprint>>
+# where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()>
# {
# // The encryption key is the first and only subkey.
# let key = self.secret.subkeys().nth(0)
# .map(|binding| binding.subkey().clone())
# .unwrap();
-#
+#
# // The secret key is not encrypted.
-# let secret =
-# if let Some(SecretKey::Unencrypted {
-# ref mpis,
-# }) = key.secret() {
-# mpis.clone()
-# } else {
-# unreachable!()
-# };
-#
-# Ok(Some(Secret::Asymmetric {
-# identity: self.secret.fingerprint(),
-# key: key,
-# secret: secret,
-# }))
+# let pair = key.into_keypair().unwrap();
+#
+# pkesks[0].decrypt(pair.public(), pair.secret())
+# .and_then(|(algo, session_key)| decrypt(algo, &session_key))
+# .map(|_| None)
+# // XXX: In production code, return the Fingerprint of the
+# // recipient's TPK here
# }
# }
```
@@ -440,9 +428,10 @@ Decrypted data can be read from this using [`io::Read`].
# use std::io::{self, Write};
#
# extern crate sequoia_openpgp as openpgp;
+# use openpgp::crypto::SessionKey;
+# use openpgp::constants::SymmetricAlgorithm;
# use openpgp::serialize::stream::*;
# use openpgp::parse::stream::*;
-# use openpgp::packet::key::SecretKey;
#
# const MESSAGE: &'static str = "дружба";
#
@@ -537,10 +526,12 @@ impl<'a> VerificationHelper for Helper<'a> {
}
impl<'a> DecryptionHelper for Helper<'a> {
- fn get_secret(&mut self,
- _pkesks: &[&openpgp::packet::PKESK],
- _skesks: &[&openpgp::packet::SKESK])
- -> openpgp::Result<Option<Secret>>
+ fn decrypt<D>(&mut self,
+ pkesks: &[openpgp::packet::PKESK],
+ _skesks: &[openpgp::packet::SKESK],
+ mut decrypt: D)
+ -> openpgp::Result<Option<openpgp::Fingerprint>>
+ where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()>
{
// The encryption key is the first and only subkey.
let key = self.secret.subkeys().nth(0)
@@ -548,20 +539,13 @@ impl<'a> DecryptionHelper for Helper<'a> {
.unwrap();
// The secret key is not encrypted.
- let secret =
- if let Some(SecretKey::Unencrypted {
- ref mpis,
- }) = key.secret() {
- mpis.clone()
- } else {
- unreachable!()
- };
-
- Ok(Some(Secret::Asymmetric {
- identity: self.secret.fingerprint(),
- key: key,
- secret: secret,
- }))
+ let pair = key.into_keypair().unwrap();
+
+ pkesks[0].decrypt(pair.public(), pair.secret())
+ .and_then(|(algo, session_key)| decrypt(algo, &session_key))
+ .map(|_| None)
+ // XXX: In production code, return the Fingerprint of the
+ // recipient's TPK here
}
}
```
diff --git a/openpgp-ffi/examples/decrypt-with.c b/openpgp-ffi/examples/decrypt-with.c
index d30b2d52..d68e0902 100644
--- a/openpgp-ffi/examples/decrypt-with.c
+++ b/openpgp-ffi/examples/decrypt-with.c
@@ -21,7 +21,7 @@
struct decrypt_cookie {
pgp_tpk_t key;
- int get_secret_keys_called;
+ int decrypt_called;
};
static pgp_status_t
@@ -46,18 +46,20 @@ check_signatures_cb(void *cookie_opaque,
}
static pgp_status_t
-get_secret_keys_cb (void *cookie_opaque,
- pgp_pkesk_t *pkesks, size_t pkesk_count,
- pgp_skesk_t *skesks, size_t skesk_count,
- pgp_secret_t *secret)
+decrypt_cb (void *cookie_opaque,
+ pgp_pkesk_t *pkesks, size_t pkesk_count,
+ pgp_skesk_t *skesks, size_t skesk_count,
+ pgp_decryptor_do_decrypt_cb_t *decrypt,
+ void *decrypt_cookie,
+ pgp_fingerprint_t *identity_out)
{
+ pgp_status_t rc;
pgp_error_t err;
struct decrypt_cookie *cookie = cookie_opaque;
/* Prevent iterations, we only have one key to offer. */
- if (cookie->get_secret_keys_called)
- return PGP_STATUS_UNKNOWN_ERROR;
- cookie->get_secret_keys_called = 1;
+ assert (!cookie->decrypt_called);
+ cookie->decrypt_called = 1;
for (int i = 0; i < pkesk_count; i++) {
pgp_pkesk_t pkesk = pkesks[i];
@@ -88,8 +90,13 @@ get_secret_keys_cb (void *cookie_opaque,
}
pgp_key_free (key);
- *secret = pgp_secret_cached (algo, session_key, session_key_len);
- return PGP_STATUS_SUCCESS;
+ pgp_session_key_t sk = pgp_session_key_from_bytes (session_key,
+ session_key_len);
+ rc = decrypt (decrypt_cookie, algo, sk);
+ pgp_session_key_free (sk);
+
+ *identity_out = pgp_tpk_fingerprint (cookie->key);
+ return rc;
}
return PGP_STATUS_UNKNOWN_ERROR;
@@ -117,10 +124,10 @@ main (int argc, char **argv)
struct decrypt_cookie cookie = {
.key = tpk,
- .get_secret_keys_called = 0,
+ .decrypt_called = 0,
};
plaintext = pgp_decryptor_new (&err, source,
- get_public_keys_cb, get_secret_keys_cb,
+ get_public_keys_cb, decrypt_cb,
check_signatures_cb, &cookie);
if (! plaintext)
error (1, 0, "pgp_decryptor_new: %s", pgp_error_to_string (err));
diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h
index 8473e632..aad66926 100644
--- a/openpgp-ffi/include/sequoia/openpgp.h
+++ b/openpgp-ffi/include/sequoia/openpgp.h
@@ -1388,12 +1388,6 @@ pgp_writer_stack_t pgp_encryptor_new (pgp_error_t *errp,
pgp_encryption_mode_t mode,
uint8_t cipher_algo);
-/*/
-/// Creates an pgp_secret_t from a decrypted session key.
-/*/
-pgp_secret_t pgp_secret_cached(uint8_t algo,
- uint8_t *session_key, size_t session_key_len);
-
void pgp_verification_results_at_level(pgp_verification_results_t results,
size_t level,
pgp_verification_result_t **r,
@@ -1438,7 +1432,7 @@ int pgp_verification_result_level(pgp_verification_result_t r);
/*/
pgp_reader_t pgp_decryptor_new (pgp_error_t *errp, pgp_reader_t input,
pgp_decryptor_get_public_keys_cb_t get_public_keys,
- pgp_decryptor_get_secret_keys_cb_t get_secret_keys,
+ pgp_decryptor_decrypt_cb_t decrypt,
pgp_decryptor_check_signatures_cb_t check_signatures,
void *cookie);
diff --git a/openpgp-ffi/include/sequoia/openpgp/types.h b/openpgp-ffi/include/sequoia/openpgp/types.h
index 2ba7fcdc..140554f5 100644
--- a/openpgp-ffi/include/sequoia/openpgp/types.h
+++ b/openpgp-ffi/include/sequoia/openpgp/types.h
@@ -455,8 +455,6 @@ typedef enum pgp_encryption_mode {
PGP_ENCRYPTION_MODE_FOR_TRANSPORT = 1,
} pgp_encryption_mode_t;
-typedef struct pgp_secret *pgp_secret_t;
-
typedef struct pgp_verification_results *pgp_verification_results_t;
typedef struct pgp_verification_result *pgp_verification_result_t;
@@ -475,10 +473,17 @@ typedef pgp_status_t (*pgp_decryptor_get_public_keys_cb_t) (void *,
pgp_tpk_t **, size_t *,
void (**free)(void *));
-typedef pgp_status_t (*pgp_decryptor_get_secret_keys_cb_t) (void *,
+typedef pgp_status_t (pgp_decryptor_do_decrypt_cb_t) (
+ void *,
+ uint8_t,
+ pgp_session_key_t);
+
+typedef pgp_status_t (*pgp_decryptor_decrypt_cb_t) (void *,
pgp_pkesk_t *, size_t,
pgp_skesk_t *, size_t,
- pgp_secret_t *);
+ pgp_decryptor_do_decrypt_cb_t *,
+ void *,
+ pgp_fingerprint_t *);
typedef pgp_status_t (*pgp_decryptor_check_signatures_cb_t) (void *,
pgp_verification_results_t,
diff --git a/openpgp-ffi/src/parse/stream.rs b/openpgp-ffi/src/parse/stream.rs
index d26bbbc8..63db33a6 100644
--- a/openpgp-ffi/src/parse/stream.rs
+++ b/openpgp-ffi/src/parse/stream.rs
@@ -11,14 +11,15 @@
//! [`sequoia-openpgp::parse::stream`]: ../../../sequoia_openpgp/parse/stream/index.html
use std::ptr;
-use std::slice;
-use libc::{c_int, size_t, c_void};
+use libc::{c_int, size_t, c_void, uint8_t};
extern crate sequoia_openpgp as openpgp;
extern crate time;
use self::openpgp::{
RevocationStatus,
+ crypto::SessionKey,
+ constants::SymmetricAlgorithm,
packet::{
PKESK,
SKESK,
@@ -27,7 +28,6 @@ use self::openpgp::{
use self::openpgp::parse::stream::{
DecryptionHelper,
Decryptor,
- Secret,
VerificationHelper,
VerificationResult,
Verifier,
@@ -38,10 +38,12 @@ use Maybe;
use MoveFromRaw;
use MoveIntoRaw;
use MoveResultIntoRaw;
+use RefRaw;
use RefMutRaw;
use super::super::{
error::Status,
+ crypto,
io,
keyid,
packet,
@@ -76,30 +78,6 @@ pub extern "system" fn pgp_revocation_status_free(
ffi_free!(rs)
}
-// Secret.
-
-/// Creates an pgp_secret_t from a decrypted session key.
-#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "system"
-fn pgp_secret_cached<'a>(algo: u8,
- session_key: *const u8,
- session_key_len: size_t)
- -> *mut Secret
-{
- let session_key = if session_key_len > 0 {
- unsafe {
- slice::from_raw_parts(session_key, session_key_len)
- }
- } else {
- &[]
- };
-
- box_raw!(Secret::Cached {
- algo: algo.into(),
- session_key: session_key.to_vec().into()
- })
-}
-
-
// Decryptor.
/// A message's verification results.
@@ -201,11 +179,25 @@ type GetPublicKeysCallback = fn(*mut HelperCookie,
&mut *mut *mut TPK, *mut usize,
*mut FreeCallback) -> Status;
-/// Returns a session key.
-type GetSecretKeysCallback = fn(*mut HelperCookie,
- *const &PKESK, usize,
- *const &SKESK, usize,
- &mut *mut Secret) -> Status;
+/// Decrypts the message.
+///
+/// This function is called with every `PKESK` and `SKESK` found in
+/// the message. The implementation must decrypt the symmetric
+/// algorithm and session key from one of the PKESK packets, the
+/// SKESKs, or retrieve it from a cache, and then call the given
+/// function with the symmetric algorithm and the session key.
+///
+/// XXX: This needlessly flattens the complex errors returned by the
+/// `decrypt` function into a status.
+type DecryptCallback = fn(*mut HelperCookie,
+ *const *const PKESK, usize,
+ *const *const SKESK, usize,
+ extern "system" fn (*mut c_void, uint8_t,
+ *const crypto::SessionKey)
+ -> Status,
+ *mut c_void,
+ *mut Maybe<super::super::fingerprint::Fingerprint>)
+ -> Status;
/// Process the signatures.
///
@@ -522,19 +514,19 @@ fn pgp_detached_verifier_new<'a>(errp: Option<&mut *mut ::error::Error>,
struct DHelper {
vhelper: VHelper,
- get_secret_keys_cb: GetSecretKeysCallback,
+ decrypt_cb: DecryptCallback,
}
impl DHelper {
fn new(get_public_keys: GetPublicKeysCallback,
- get_secret_keys: GetSecretKeysCallback,
+ decrypt: DecryptCallback,
check_signatures: CheckSignaturesCallback,
cookie: *mut HelperCookie)
-> Self
{
DHelper {
vhelper: VHelper::new(get_public_keys, check_signatures, cookie),
- get_secret_keys_cb: get_secret_keys,
+ decrypt_cb: decrypt,
}
}
}
@@ -554,15 +546,46 @@ impl VerificationHelper for DHelper {
}
impl DecryptionHelper for DHelper {
- fn get_secret(&mut self, pkesks: &[&PKESK], skesks: &[&SKESK])
- -> Result<Option<Secret>, failure::Error>
+ fn decrypt<D>(&mut self, pkesks: &[PKESK], skesks: &[SKESK],
+ mut decrypt: D)
+ -> openpgp::Result<Option<openpgp::Fingerprint>>
+ where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()>
{
- let mut secret : *mut Secret = ptr::null_mut();
+ let mut identity: Maybe<super::super::fingerprint::Fingerprint> = None;
+
+ // The size of PKESK is not known in C. Convert from an array
+ // of PKESKs to an array of PKESK refs. Likewise for SKESKs.
+ //
+ // XXX: .move_into_raw() once PKESK and SKESK are wrapped.
+ let pkesks : Vec<*const PKESK> =
+ pkesks.iter().map(|k| k as *const _).collect();
+ let skesks : Vec<*const SKESK> =
+ skesks.iter().map(|k| k as *const _).collect();
+
+ // XXX: Free the wrappers once PKESK and SKESK are wrapped.
+ //
+ // // Free the wrappers.
+ // pkesks.into_iter().for_each(|o| {
+ // super::super::packet::pkesk::pgp_pkesk_free(o) });
+ // skesks.into_iter().for_each(|o| {
+ // super::super::packet::skesk::pgp_skesk_free(o) });
+
+ extern "system" fn trampoline<D>(data: *mut c_void, algo: uint8_t,
+ sk: *const crypto::SessionKey)
+ -> Status
+ where D: FnMut(SymmetricAlgorithm, &SessionKey)
+ -> openpgp::Result<()>
+ {
+ let closure: &mut D = unsafe { &mut *(data as *mut D) };
+ (*closure)(algo.into(), sk.ref_raw()).into()
+ }
- let result = (self.get_secret_keys_cb)(
+ let result = (self.decrypt_cb)(
self.vhelper.cookie,
pkesks.as_ptr(), pkesks.len(), skesks.as_ptr(), skesks.len(),
- &mut secret);
+ trampoline::<D>,
+ &mut decrypt as *mut _ as *mut c_void,
+ &mut identity);
if result != Status::Success {
// XXX: We need to convert the status to an error. A
// status contains less information, but we should do the
@@ -572,14 +595,7 @@ impl DecryptionHelper for DHelper {
format!("{:?}", result)).into());
}
- if secret.is_null() {
- return Err(openpgp::Error::MissingSessionKey(
- "Callback did not return a session key".into()).into());
- }
-
- let secret = ffi_param_move!(secret);
-
- Ok(Some(*secret))
+ Ok(identity.move_from_raw())
}
}
@@ -611,7 +627,7 @@ impl DecryptionHelper for DHelper {
///
/// struct decrypt_cookie {
/// pgp_tpk_t key;
-/// int get_secret_keys_called;
+/// int decrypt_called;
/// };
///
/// static pgp_status_t
@@ -636,18 +652,19 @@ impl DecryptionHelper for DHelper {
/// }
///
/// static pgp_status_t
-/// get_secret_keys_cb (void *cookie_opaque,
-/// pgp_pkesk_t *pkesks, size_t pkesk_count,
-/// pgp_skesk_t *skesks, size_t skesk_count,
-/// pgp_secret_t *secret)
+/// decrypt_cb (void *cookie_opaque,
+/// pgp_pkesk_t *pkesks, size_t pkesk_count,
+/// pgp_skesk_t *skesks, size_t skesk_count,
+/// pgp_decryptor_do_decrypt_cb_t *decrypt,
+/// void *decrypt_cookie,
+/// pgp_fingerprint_t *identity_out)
/// {
+/// pgp_status_t rc;
/// pgp_error_t err;
/// struct decrypt_cookie *cookie = cookie_opaque;
///
-/// /* Prevent iterations, we only have one key to offer. */
-/// if (cookie->get_secret_keys_called)
-/// return PGP_STATUS_UNKNOWN_ERROR;
-/// cookie->get_secret_keys_called = 1;
+/// assert (! cookie->decrypt_called);
+/// cookie->decrypt_called = 1;
///
/// for (int i = 0; i < pkesk_count; i++) {
/// pgp_pkesk_t pkesk = pkesks[i];
@@ -678,8 +695,13 @@ impl DecryptionHelper for DHelper {
/// }
/// pgp_key_free (key);
///
-/// *secret = pgp_secret_cached (algo, session_key, session_key_len);
-/// return PGP_STATUS_SUCCESS;
+/// pgp_session_key_t sk = pgp_session_key_from_bytes (session_key,
+/// session_key_len);
+/// rc = decrypt (decrypt_cookie, algo, sk);
+/// pgp_session_key_free (sk);
+///
+/// *identity_out = pgp_tpk_fingerprint (cookie->key);
+/// return rc;
/// }
///
/// return PGP_STATUS_UNKNOWN_ERROR;
@@ -704,17 +726,17 @@ impl DecryptionHelper for DHelper {
///
/// struct decrypt_cookie cookie = {
/// .key = tpk,
-/// .get_secret_keys_called = 0,
+/// .decrypt_called = 0,
/// };
/// plaintext = pgp_decryptor_new (NULL, source,
-/// get_public_keys_cb, get_secret_keys_cb,
+/// get_public_keys_cb, decrypt_cb,
/// check_signatures_cb, &cookie);
/// assert (plaintext);
///
/// nread = pgp_reader_read (NULL, plaintext, buf, sizeof buf);
/// assert (nread == 13);
/// assert (memcmp (buf, "Test, 1-2-3.\n", nread) == 0);
-/// assert (cookie.get_secret_keys_called);
+/// assert (cookie.decrypt_called);
///
/// pgp_reader_free (plaintext);
/// pgp_reader_free (source);
@@ -726,13 +748,13 @@ impl DecryptionHelper for DHelper {
fn pgp_decryptor_new<'a>(errp: Option<&mut *mut ::error::Error>,
input: *mut io::Reader,
get_public_keys: GetPublicKeysCallback,
- get_secret_keys: GetSecretKeysCallback,
+ decrypt: DecryptCallback,
check_signatures: CheckSignaturesCallback,
cookie: *mut HelperCookie)
-> Maybe<io::Reader>
{
let helper = DHelper::new(
- get_public_keys, get_secret_keys, check_signatures, cookie);
+ get_public_keys, decrypt, check_signatures, cookie);
Decryptor::from_reader(input.ref_mut_raw(), helper)
.map(|r| io::ReaderKind::Generic(Box::new(r)))
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs
index a5b26baa..3d6118f0 100644
--- a/openpgp/examples/decrypt-with.rs
+++ b/openpgp/examples/decrypt-with.rs
@@ -8,13 +8,13 @@ use std::io;
extern crate failure;
extern crate sequoia_openpgp as openpgp;
-use openpgp::packet::key::SecretKey;
+use openpgp::crypto::{KeyPair, SessionKey};
+use openpgp::constants::SymmetricAlgorithm;
use openpgp::parse::{
Parse,
stream::{
DecryptionHelper,
Decryptor,
- Secret,
VerificationHelper,
VerificationResult,
},
@@ -47,8 +47,7 @@ pub fn main() {
/// keys for the signature verification and implements the
/// verification policy.
struct Helper {
- keys: HashMap<openpgp::KeyID, Secret>,
- i: usize,
+ keys: HashMap<openpgp::KeyID, KeyPair>,
}
impl Helper {
@@ -62,16 +61,10 @@ impl Helper {
|| s.key_flags().can_encrypt_for_transport()))
.unwrap_or(false)
{
- // Only handle unencrypted secret keys.
- if let Some(SecretKey::Unencrypted { ref mpis }) =
- key.secret()
- {
+ // This only works for unencrypted secret keys.
+ if let Ok(keypair) = key.clone().into_keypair() {
keys.insert(key.fingerprint().to_keyid(),
- Secret::Asymmetric {
- identity: tpk.fingerprint(),
- key: key.clone(),
- secret: mpis.clone(),
- });
+ keypair);
}
}
}
@@ -79,25 +72,31 @@ impl Helper {
Helper {
keys: keys,
- i: 0,
}
}
}
impl DecryptionHelper for Helper {
- fn get_secret(&mut self,
- pkesks: &[&openpgp::packet::PKESK],
- _: &[&openpgp::packet::SKESK])
- -> failure::Fallible<Option<Secret>> {
- let r = pkesks
- .iter()
- .nth(self.i)
- .and_then(|pkesk| {
- self.keys.get(pkesk.recipient())
- .map(|s| (*s).clone())
- });
- self.i += 1;
- Ok(r)
+ fn decrypt<D>(&mut self,
+ pkesks: &[openpgp::packet::PKESK],
+ _skesks: &[openpgp::packet::SKESK],
+ mut decrypt: D)
+ -> openpgp::Result<Option<openpgp::Fingerprint>>
+ where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()>
+ {
+ // 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())
+ .and_then(|(algo, session_key)| decrypt(algo, &session_key))
+ {
+ break;