summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2019-12-19 21:47:19 +0100
committerNeal H. Walfield <neal@pep.foundation>2019-12-19 21:51:19 +0100
commitb3ba97146f534ac5cf67db7f72d8a633112d0a18 (patch)
tree581c64936f0a857dd1f0fbf75c7a4ddf243d8656
parent2b2b5c8905d0e823d03b5ba2a115298e80e08b74 (diff)
openpgp: Change KeyIter to return a struct instead of a tuple.
- A tuple is just an unnamed, inflexible struct. Use a struct instead. - Fixes #400.
-rw-r--r--guide/src/chapter_01.md16
-rw-r--r--guide/src/chapter_02.md8
-rw-r--r--ipc/examples/gpg-agent-decrypt.rs8
-rw-r--r--ipc/examples/gpg-agent-sign.rs4
-rw-r--r--ipc/tests/gpg-agent.rs6
-rw-r--r--net/src/lib.rs4
-rw-r--r--openpgp-ffi/src/cert.rs7
-rw-r--r--openpgp-ffi/src/serialize.rs2
-rw-r--r--openpgp/examples/decrypt-with.rs11
-rw-r--r--openpgp/examples/encrypt-for.rs2
-rw-r--r--openpgp/examples/generate-encrypt-decrypt.rs2
-rw-r--r--openpgp/examples/generate-sign-verify.rs4
-rw-r--r--openpgp/examples/notarize.rs2
-rw-r--r--openpgp/examples/pad.rs2
-rw-r--r--openpgp/examples/sign-detached.rs2
-rw-r--r--openpgp/examples/sign.rs2
-rw-r--r--openpgp/src/cert/builder.rs8
-rw-r--r--openpgp/src/cert/key_amalgamation.rs183
-rw-r--r--openpgp/src/cert/keyiter.rs53
-rw-r--r--openpgp/src/cert/mod.rs2
-rw-r--r--openpgp/src/crypto/keygrip.rs6
-rw-r--r--openpgp/src/crypto/mpis.rs2
-rw-r--r--openpgp/src/packet/signature/mod.rs2
-rw-r--r--openpgp/src/parse/stream.rs18
-rw-r--r--openpgp/src/serialize/stream.rs13
-rw-r--r--sqv/src/sqv.rs8
-rw-r--r--store/src/backend/mod.rs2
-rw-r--r--tool/src/commands/mod.rs6
-rw-r--r--tool/tests/sq-sign.rs2
29 files changed, 292 insertions, 95 deletions
diff --git a/guide/src/chapter_01.md b/guide/src/chapter_01.md
index b4a4ccab..6368a9eb 100644
--- a/guide/src/chapter_01.md
+++ b/guide/src/chapter_01.md
@@ -51,8 +51,8 @@ fn main() {
# fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::Cert)
# -> openpgp::Result<()> {
# // Get the keypair to do the signing from the Cert.
-# let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().2
-# .clone().mark_parts_secret().unwrap().into_keypair()?;
+# let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().
+# key().clone().mark_parts_secret().unwrap().into_keypair()?;
#
# // Start streaming an OpenPGP message.
# let message = Message::new(sink);
@@ -196,8 +196,8 @@ fn generate() -> openpgp::Result<openpgp::Cert> {
# fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::Cert)
# -> openpgp::Result<()> {
# // Get the keypair to do the signing from the Cert.
-# let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().2
-# .clone().mark_parts_secret().unwrap().into_keypair()?;
+# let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().
+# key().clone().mark_parts_secret().unwrap().into_keypair()?;
#
# // Start streaming an OpenPGP message.
# let message = Message::new(sink);
@@ -341,8 +341,8 @@ implements [`io::Write`], and we simply write the plaintext to it.
fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::Cert)
-> openpgp::Result<()> {
// Get the keypair to do the signing from the Cert.
- let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().2
- .clone().mark_parts_secret().unwrap().into_keypair()?;
+ let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().
+ key().clone().mark_parts_secret().unwrap().into_keypair()?;
// Start streaming an OpenPGP message.
let message = Message::new(sink);
@@ -497,8 +497,8 @@ Verified data can be read from this using [`io::Read`].
# fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::Cert)
# -> openpgp::Result<()> {
# // Get the keypair to do the signing from the Cert.
-# let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().2
-# .clone().mark_parts_secret().unwrap().into_keypair()?;
+# let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().
+# key().clone().mark_parts_secret().unwrap().into_keypair()?;
#
# // Start streaming an OpenPGP message.
# let message = Message::new(sink);
diff --git a/guide/src/chapter_02.md b/guide/src/chapter_02.md
index cc024348..e1687803 100644
--- a/guide/src/chapter_02.md
+++ b/guide/src/chapter_02.md
@@ -53,7 +53,7 @@ fn main() {
# let mut recipients =
# recipient.keys_valid()
# .for_transport_encryption()
-# .map(|(_, _, key)| key.into())
+# .map(|ka| ka.key().into())
# .collect::<Vec<_>>();
#
# // Start streaming an OpenPGP message.
@@ -194,7 +194,7 @@ fn generate() -> openpgp::Result<openpgp::Cert> {
# let mut recipients =
# recipient.keys_valid()
# .for_transport_encryption()
-# .map(|(_, _, key)| key.into())
+# .map(|ka| ka.key().into())
# .collect::<Vec<_>>();
#
# // Start streaming an OpenPGP message.
@@ -335,7 +335,7 @@ fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::Cert)
let mut recipients =
recipient.keys_valid()
.for_transport_encryption()
- .map(|(_, _, key)| key.into())
+ .map(|ka| ka.key().into())
.collect::<Vec<_>>();
// Start streaming an OpenPGP message.
@@ -490,7 +490,7 @@ Decrypted data can be read from this using [`io::Read`].
# let mut recipients =
# recipient.keys_valid()
# .for_transport_encryption()
-# .map(|(_, _, key)| key.into())
+# .map(|ka| ka.key().into())
# .collect::<Vec<_>>();
#
# // Start streaming an OpenPGP message.
diff --git a/ipc/examples/gpg-agent-decrypt.rs b/ipc/examples/gpg-agent-decrypt.rs
index f59912a5..381bab6d 100644
--- a/ipc/examples/gpg-agent-decrypt.rs
+++ b/ipc/examples/gpg-agent-decrypt.rs
@@ -74,11 +74,13 @@ impl<'a> Helper<'a> {
// Map (sub)KeyIDs to secrets.
let mut keys = HashMap::new();
for cert in certs {
- for (sig, _, key) in cert.keys_all() {
- if sig.map(|s| (s.key_flags().for_storage_encryption()
- || s.key_flags().for_transport_encryption()))
+ for ka in cert.keys_all() {
+ if ka.binding_signature(None)
+ .map(|s| (s.key_flags().for_storage_encryption()
+ || s.key_flags().for_transport_encryption()))
.unwrap_or(false)
{
+ let key = ka.key();
keys.insert(key.keyid(), key.clone().into());
}
}
diff --git a/ipc/examples/gpg-agent-sign.rs b/ipc/examples/gpg-agent-sign.rs
index e0cfeb98..dfc3f304 100644
--- a/ipc/examples/gpg-agent-sign.rs
+++ b/ipc/examples/gpg-agent-sign.rs
@@ -39,8 +39,8 @@ fn main() {
// Construct a KeyPair for every signing-capable (sub)key.
let mut signers = certs.iter().flat_map(|cert| {
- cert.keys_valid().for_signing().filter_map(|(_, _, key)| {
- KeyPair::new(&ctx, key).ok()
+ cert.keys_valid().for_signing().filter_map(|ka| {
+ KeyPair::new(&ctx, ka.key()).ok()
})
}).collect::<Vec<KeyPair>>();
diff --git a/ipc/tests/gpg-agent.rs b/ipc/tests/gpg-agent.rs
index c284117f..6a74ffa3 100644
--- a/ipc/tests/gpg-agent.rs
+++ b/ipc/tests/gpg-agent.rs
@@ -95,7 +95,7 @@ fn sign() {
gpg_import(&ctx, &buf);
let keypair = KeyPair::new(
- &ctx, cert.keys_valid().for_signing().take(1).next().unwrap().2)
+ &ctx, cert.keys_valid().for_signing().take(1).next().unwrap().key())
.unwrap();
let mut message = Vec::new();
@@ -210,7 +210,7 @@ fn decrypt() {
let recipient =
cert.keys_valid().key_flags(
KeyFlags::default().set_transport_encryption(true))
- .map(|(_, _, key)| key.into())
+ .map(|ka| ka.key().into())
.nth(0).unwrap();
// Start streaming an OpenPGP message.
@@ -277,7 +277,7 @@ fn decrypt() {
self.ctx,
self.cert.keys_valid().key_flags(
KeyFlags::default().set_transport_encryption(true))
- .take(1).next().unwrap().2)
+ .take(1).next().unwrap().key())
.unwrap();
pkesks[0].decrypt(&mut keypair)
diff --git a/net/src/lib.rs b/net/src/lib.rs
index e0b94434..a7746727 100644
--- a/net/src/lib.rs
+++ b/net/src/lib.rs
@@ -183,8 +183,8 @@ impl KeyServer {
Some(armor::Kind::PublicKey)));
match Cert::from_reader(r) {
Ok(cert) => {
- if cert.keys_all().any(|(_, _, key)| {
- KeyID::from(key.fingerprint())
+ if cert.keys_all().any(|ka| {
+ KeyID::from(ka.key().fingerprint())
== keyid_want
}) {
future::done(Ok(cert))
diff --git a/openpgp-ffi/src/cert.rs b/openpgp-ffi/src/cert.rs
index b81150fa..2791ad1c 100644
--- a/openpgp-ffi/src/cert.rs
+++ b/openpgp-ffi/src/cert.rs
@@ -695,7 +695,12 @@ pub extern "C" fn pgp_cert_key_iter_next<'a>(
let iter_wrapper = ffi_param_ref_mut!(iter_wrapper);
iter_wrapper.next_called = true;
- if let Some((sig, rs, key)) = iter_wrapper.iter.next() {
+ if let Some(ka) = iter_wrapper.iter.next() {
+ // XXX: Shouldn't assume the current time.
+ let sig = ka.binding_signature(None);
+ let rs = ka.revoked(None);
+ let key = ka.key();
+
if let Some(ptr) = sigo {
*ptr = sig.move_into_raw();
}
diff --git a/openpgp-ffi/src/serialize.rs b/openpgp-ffi/src/serialize.rs
index 6f24a5aa..0a6435a0 100644
--- a/openpgp-ffi/src/serialize.rs
+++ b/openpgp-ffi/src/serialize.rs
@@ -282,7 +282,7 @@ fn pgp_recipients_from_key_iter<'a>(
let result_len = ffi_param_ref_mut!(result_len);
let recipients =
iter_wrapper.iter
- .map(|(_, _, key)| key.into())
+ .map(|ka| ka.key().into())
.collect::<Vec<openpgp::serialize::stream::Recipient>>();
let result = unsafe {
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs
index 224a8726..7c924cc9 100644
--- a/openpgp/examples/decrypt-with.rs
+++ b/openpgp/examples/decrypt-with.rs
@@ -58,16 +58,17 @@ impl Helper {
// Map (sub)KeyIDs to secrets.
let mut keys = HashMap::new();
for cert in certs {
- for (sig, _, key) in cert.keys_all() {
- if sig.map(|s| (s.key_flags().for_storage_encryption()
- || s.key_flags().for_transport_encryption()))
+ for ka in cert.keys_all() {
+ if ka.binding_signature(None)
+ .map(|s| (s.key_flags().for_storage_encryption()
+ || s.key_flags().for_transport_encryption()))
.unwrap_or(false)
{
// This only works for unencrypted secret keys.
if let Ok(keypair) =
- key.clone().mark_parts_secret().unwrap().into_keypair()
+ ka.key().clone().mark_parts_secret().unwrap().into_keypair()
{
- keys.insert(key.keyid(), keypair);
+ keys.insert(ka.key().keyid(), keypair);
}
}
}
diff --git a/openpgp/examples/encrypt-for.rs b/openpgp/examples/encrypt-for.rs
index f3004532..eceec5b3 100644
--- a/openpgp/examples/encrypt-for.rs
+++ b/openpgp/examples/encrypt-for.rs
@@ -38,7 +38,7 @@ fn main() {
let mut recipients =
certs.iter()
.flat_map(|cert| cert.keys_valid().key_flags(mode.clone()))
- .map(|(_, _, key)| key.into())
+ .map(|ka| ka.key().into())
.collect::<Vec<_>>();
// Compose a writer stack corresponding to the output format and
diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs
index 55ea89d6..01782b47 100644
--- a/openpgp/examples/generate-encrypt-decrypt.rs
+++ b/openpgp/examples/generate-encrypt-decrypt.rs
@@ -44,7 +44,7 @@ fn encrypt(sink: &mut dyn Write, plaintext: &str, recipient: &openpgp::Cert)
let mut recipients =
recipient.keys_valid()
.for_transport_encryption()
- .map(|(_, _, key)| key.into())
+ .map(|ka| ka.key().into())
.collect::<Vec<_>>();
// Start streaming an OpenPGP message.
diff --git a/openpgp/examples/generate-sign-verify.rs b/openpgp/examples/generate-sign-verify.rs
index 6e3d8084..1cccac44 100644
--- a/openpgp/examples/generate-sign-verify.rs
+++ b/openpgp/examples/generate-sign-verify.rs
@@ -40,8 +40,8 @@ fn generate() -> openpgp::Result<openpgp::Cert> {
fn sign(sink: &mut dyn Write, plaintext: &str, tsk: &openpgp::Cert)
-> openpgp::Result<()> {
// Get the keypair to do the signing from the Cert.
- let keypair = tsk.keys_valid().for_signing().nth(0).unwrap().2
- .clone().mark_parts_secret().unwrap().into_keypair()?;
+ let keypair = tsk.keys_valid().for_signing().nth(0).unwrap()
+ .key().clone().mark_parts_secret().unwrap().into_keypair()?;
// Start streaming an OpenPGP message.
let message = Message::new(sink);
diff --git a/openpgp/examples/notarize.rs b/openpgp/examples/notarize.rs
index ce007968..f52466f4 100644
--- a/openpgp/examples/notarize.rs
+++ b/openpgp/examples/notarize.rs
@@ -28,7 +28,7 @@ fn main() {
.expect("Failed to read key");
let mut n = 0;
- for (_, _, key) in tsk.keys_valid().for_signing().secret() {
+ for key in tsk.keys_valid().for_signing().secret().map(|ka| ka.key()) {
keys.push({
let mut key = key.clone();
if key.secret().expect("filtered").is_encrypted() {
diff --git a/openpgp/examples/pad.rs b/openpgp/examples/pad.rs
index a13e53d5..32583a42 100644
--- a/openpgp/examples/pad.rs
+++ b/openpgp/examples/pad.rs
@@ -40,7 +40,7 @@ fn main() {
let mut recipients =
certs.iter()
.flat_map(|cert| cert.keys_valid().key_flags(mode.clone()))
- .map(|(_, _, key)| Recipient::new(KeyID::wildcard(), key))
+ .map(|ka| Recipient::new(KeyID::wildcard(), ka.key()))
.collect::<Vec<_>>();
// Compose a writer stack corresponding to the output format and
diff --git a/openpgp/examples/sign-detached.rs b/openpgp/examples/sign-detached.rs
index 0fee0e36..20d4150b 100644
--- a/openpgp/examples/sign-detached.rs
+++ b/openpgp/examples/sign-detached.rs
@@ -24,7 +24,7 @@ fn main() {
.expect("Failed to read key");
let mut n = 0;
- for (_, _, key) in tsk.keys_valid().for_signing().secret() {
+ for key in tsk.keys_valid().for_signing().secret().map(|ka| ka.key()) {
keys.push({
let mut key = key.clone();
if key.secret().expect("filtered").is_encrypted() {
diff --git a/openpgp/examples/sign.rs b/openpgp/examples/sign.rs
index 195ac508..7fae29ef 100644
--- a/openpgp/examples/sign.rs
+++ b/openpgp/examples/sign.rs
@@ -23,7 +23,7 @@ fn main() {
.expect("Failed to read key");
let mut n = 0;
- for (_, _, key) in tsk.keys_valid().for_signing().secret() {
+ for key in tsk.keys_valid().for_signing().secret().map(|ka| ka.key()) {
keys.push({
let mut key = key.clone();
if key.secret().expect("filtered").is_encrypted() {
diff --git a/openpgp/src/cert/builder.rs b/openpgp/src/cert/builder.rs
index ce1a0a6c..24bc5fe7 100644
--- a/openpgp/src/cert/builder.rs
+++ b/openpgp/src/cert/builder.rs
@@ -656,13 +656,17 @@ mod tests {
assert!(! sig.key_alive(key, now + 610 * s).is_ok());
let (sig, key) = cert.keys_valid().for_signing()
- .nth(0).map(|(s, _, k)| (s.unwrap(), k)).unwrap();
+ .nth(0).map(|ka| {
+ (ka.binding_signature(None).unwrap(), ka.key())
+ }).unwrap();
assert!(sig.key_alive(key, now).is_ok());
assert!(sig.key_alive(key, now + 290 * s).is_ok());
assert!(! sig.key_alive(key, now + 310 * s).is_ok());
let (sig, key) = cert.keys_valid().for_authentication()
- .nth(0).map(|(s, _, k)| (s.unwrap(), k)).unwrap();
+ .nth(0).map(|ka| {
+ (ka.binding_signature(None).unwrap(), ka.key())
+ }).unwrap();
assert!(sig.key_alive(key, now).is_ok());
assert!(sig.key_alive(key, now + 590 * s).is_ok());
assert!(! sig.key_alive(key, now + 610 * s).is_ok());
diff --git a/openpgp/src/cert/key_amalgamation.rs b/openpgp/src/cert/key_amalgamation.rs
new file mode 100644
index 00000000..af7f7a7e
--- /dev/null
+++ b/openpgp/src/cert/key_amalgamation.rs
@@ -0,0 +1,183 @@
+use std::time;
+use std::convert::TryInto;
+use std::convert::TryFrom;
+
+use crate::{
+ Cert,
+ cert::KeyBinding,
+ packet::key,
+ packet::Key,
+ packet::Signature,
+ Result,
+ RevocationStatus,
+};
+
+/// A variant of `KeyAmalgamation` for primary keys.
+#[derive(Debug)]
+struct PrimaryKeyAmalgamation<'a, P: key::KeyParts> {
+ cert: &'a Cert,
+ binding: &'a KeyBinding<P, key::PrimaryRole>,
+}
+
+/// A variant of `KeyAmalgamation` for subkeys.
+#[derive(Debug)]
+struct SubordinateKeyAmalgamation<'a, P: key::KeyParts> {
+ cert: &'a Cert,
+ binding: &'a KeyBinding<P, key::SubordinateRole>,
+}
+
+/// The underlying `KeyAmalgamation` type.
+///
+/// We don't make this type public, because an enum's variant types
+/// must also all be public, and we don't want that here. Wrapping
+/// this in a struct means that we can hide that.
+#[derive(Debug)]
+enum KeyAmalgamation0<'a, P: key::KeyParts> {
+ Primary(PrimaryKeyAmalgamation<'a, P>),
+ Subordinate(SubordinateKeyAmalgamation<'a, P>),
+}
+
+/// A `Key` and its associated data.
+#[derive(Debug)]
+pub struct KeyAmalgamation<'a, P: key::KeyParts>(KeyAmalgamation0<'a, P>);
+
+impl<'a, P> From<(&'a Cert, &'a KeyBinding<P, key::PrimaryRole>)>
+ for KeyAmalgamation<'a, P>
+ where P: key::KeyParts
+{
+ fn from(x: (&'a Cert, &'a KeyBinding<P, key::PrimaryRole>)) -> Self {
+ KeyAmalgamation(KeyAmalgamation0::Primary(PrimaryKeyAmalgamation {
+ cert: x.0,
+ binding: x.1,
+ }))
+ }
+}
+
+impl<'a, P> From<(&'a Cert, &'a KeyBinding<P, key::SubordinateRole>)>
+ for KeyAmalgamation<'a, P>
+ where P: key::KeyParts
+{
+ fn from(x: (&'a Cert, &'a KeyBinding<P, key::SubordinateRole>)) -> Self {
+ KeyAmalgamation(KeyAmalgamation0::Subordinate(SubordinateKeyAmalgamation {
+ cert: x.0,
+ binding: x.1,
+ }))
+ }
+}
+
+// We can't make the key parts generic, because then the impl would
+// conflict with 'impl<T> std::convert::From<T> for T'.
+impl<'a> From<KeyAmalgamation<'a, key::PublicParts>>
+ for KeyAmalgamation<'a, key::UnspecifiedParts>
+{
+ fn from(ka: KeyAmalgamation<'a, key::PublicParts>) -> Self {
+ match ka {
+ KeyAmalgamation(KeyAmalgamation0::Primary(ka)) => {
+ KeyAmalgamation(KeyAmalgamation0::Primary(
+ PrimaryKeyAmalgamation {
+ cert: ka.cert,
+ binding: ka.binding.into(),
+ })
+ )
+ }
+ KeyAmalgamation(KeyAmalgamation0::Subordinate(ka)) => {
+ KeyAmalgamation(KeyAmalgamation0::Subordinate(
+ SubordinateKeyAmalgamation {
+ ce