From bbbc6da375d6584c7b2bcc74e838fff943f489d4 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 28 Nov 2019 15:27:33 +0100 Subject: Call TPKs Certificates, update identifiers, documentation. - Fixes #387. --- openpgp/src/tpk/keyiter.rs | 501 --------------------------------------------- 1 file changed, 501 deletions(-) delete mode 100644 openpgp/src/tpk/keyiter.rs (limited to 'openpgp/src/tpk/keyiter.rs') diff --git a/openpgp/src/tpk/keyiter.rs b/openpgp/src/tpk/keyiter.rs deleted file mode 100644 index d7ec9684..00000000 --- a/openpgp/src/tpk/keyiter.rs +++ /dev/null @@ -1,501 +0,0 @@ -use std::fmt; - -use crate::{ - RevocationStatus, - packet::key, - packet::Key, - packet::key::SecretKeyMaterial, - types::KeyFlags, - conversions::Time, - packet::Signature, - TPK, - tpk::KeyBindingIter, -}; - -/// An iterator over all `Key`s (both the primary key and any subkeys) -/// in a TPK. -/// -/// Returned by `TPK::keys_all()` and `TPK::keys_valid()`. -/// -/// `KeyIter` follows the builder pattern. There is no need to -/// explicitly finalize it, however: it already implements the -/// `Iterator` interface. -/// -/// By default, `KeyIter` will only return live, non-revoked keys. It -/// is possible to control how `KeyIter` filters using, for instance, -/// `KeyIter::flags` to only return keys with particular flags set. -pub struct KeyIter<'a, P: key::KeyParts, R: key::KeyRole> { - // This is an option to make it easier to create an empty KeyIter. - tpk: Option<&'a TPK>, - primary: bool, - subkey_iter: KeyBindingIter<'a, - key::PublicParts, - key::SubordinateRole>, - - // If not None, only returns keys with the specified flags. - flags: Option, - - // If not None, only returns keys that are live at the specified - // time. - alive_at: Option, - - // If not None, filters by revocation status. - revoked: Option, - - // If not None, filters by whether a key has a secret. - secret: Option, - - // If not None, filters by whether a key has an unencrypted - // secret. - unencrypted_secret: Option, - - _p: std::marker::PhantomData

, - _r: std::marker::PhantomData, -} - -impl<'a, P: key::KeyParts, R: key::KeyRole> fmt::Debug - for KeyIter<'a, P, R> -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("KeyIter") - .field("flags", &self.flags) - .field("alive_at", &self.alive_at) - .field("revoked", &self.revoked) - .field("secret", &self.secret) - .field("unencrypted_secret", &self.unencrypted_secret) - .finish() - } -} - -// Very carefully implement Iterator for -// Key<{PublicParts,UnspecifiedParts}, _>. We cannot just abstract -// over the parts, because then we cannot specialize the -// implementation for Key below. -macro_rules! impl_iterator { - ($parts:path) => { - impl<'a, R: 'a + key::KeyRole> Iterator for KeyIter<'a, $parts, R> - where &'a Key<$parts, R>: From<&'a Key> - { - type Item = (Option<&'a Signature>, RevocationStatus<'a>, - &'a Key<$parts, R>); - - fn next(&mut self) -> Option { - self.next_common().map(|(s, r, k)| (s, r, k.into())) - } - } - } -} -impl_iterator!(key::PublicParts); -impl_iterator!(key::UnspecifiedParts); - -impl<'a, R: 'a + key::KeyRole> Iterator for KeyIter<'a, key::SecretParts, R> - where &'a Key: From<&'a Key> -{ - type Item = (Option<&'a Signature>, RevocationStatus<'a>, - &'a Key); - - fn next(&mut self) -> Option { - self.next_common() - .map(|(s, r, k)| - (s, r, - k.mark_parts_secret_ref().expect("has secret parts").into())) - } -} - -impl <'a, P: 'a + key::KeyParts, R: 'a + key::KeyRole> KeyIter<'a, P, R> { - fn next_common(&mut self) - -> Option<(Option<&'a Signature>, - RevocationStatus<'a>, - &'a Key)> - { - tracer!(false, "KeyIter::next", 0); - t!("KeyIter: {:?}", self); - - if self.tpk.is_none() { - return None; - } - let tpk = self.tpk.unwrap(); - - if let Some(flags) = self.flags.as_ref() { - if flags.is_empty() { - // Nothing to do. - t!("short circuiting: flags is empty"); - return None; - } - } - - loop { - let (sigo, revoked, key) : (_, _, &key::UnspecifiedPublic) - = if ! self.primary { - self.primary = true; - - (tpk.primary_key_signature(None), - tpk.revoked(None), - tpk.primary().into()) - } else { - self.subkey_iter.next() - .map(|sk_binding| (sk_binding.binding_signature(None), - sk_binding.revoked(None), - sk_binding.key().into(),))? - }; - - t!("Considering key: {:?}", key); - - if let Some(flags) = self.flags.as_ref() { - if let Some(sig) = sigo { - if (&sig.key_flags() & &flags).is_empty() { - t!("Have flags: {:?}, want flags: {:?}... skipping.", - sig.key_flags(), flags); - continue; - } - } else { - // No self-signature, skip it. - t!("No self-signature... skipping."); - continue; - } - } - - if let Some(alive_at) = self.alive_at { - if let Some(sig) = sigo { - if ! sig.key_alive(key, alive_at) { - t!("Key not alive... skipping."); - continue; - } - } else { - // No self-signature, skip it. - t!("No self-signature... skipping."); - continue; - } - } - - if let Some(want_revoked) = self.revoked { - if let RevocationStatus::Revoked(_) = revoked { - // The key is definitely revoked. - if ! want_revoked { - t!("Key revoked... skipping."); - continue; - } - } else { - // The key is probably not revoked. - if want_revoked { - t!("Key not revoked... skipping."); - continue; - } - } - } - - if let Some(want_secret) = self.secret { - if key.secret().is_some() { - // We have a secret. - if ! want_secret { - t!("Have a secret... skipping."); - continue; - } - } else { - if want_secret { - t!("No secret... skipping."); - continue; - } - } - } - - if let Some(want_unencrypted_secret) = self.unencrypted_secret { - if let Some(secret) = key.secret() { - if let SecretKeyMaterial::Unencrypted { .. } = secret { - if ! want_unencrypted_secret { - t!("Unencrypted secret... skipping."); - continue; - } - } else { - if want_unencrypted_secret { - t!("Encrypted secret... skipping."); - continue; - } - } - } else { - // No secret. - t!("No secret... skipping."); - continue; - } - } - - return Some((sigo, revoked, key)); - } - } -} - -impl<'a, P: 'a + key::KeyParts, R: 'a + key::KeyRole> KeyIter<'a, P, R> -{ - /// Returns a new `KeyIter` instance with no filters enabled. - pub(crate) fn new(tpk: &'a TPK) -> Self where Self: 'a { - KeyIter { - tpk: Some(tpk), - primary: false, - subkey_iter: tpk.subkeys(), - - // The filters. - flags: None, - alive_at: None, - revoked: None, - secret: None, - unencrypted_secret: None, - - _p: std::marker::PhantomData, - _r: std::marker::PhantomData, - } - } - - /// Clears all filters. - /// - /// This causes the `KeyIter` to return all keys in the TPK. - pub fn unfiltered(self) -> Self { - KeyIter::new(self.tpk.unwrap()) - } - - /// Returns an empty KeyIter. - pub fn empty() -> Self { - KeyIter { - tpk: None, - primary: false, - subkey_iter: KeyBindingIter { iter: None }, - - // The filters. - flags: None, - alive_at: None, - revoked: None, - secret: None, - unencrypted_secret: None, - - _p: std::marker::PhantomData, - _r: std::marker::PhantomData, - } - } - - /// Returns keys that have the at least one of the flags specified - /// in `flags`. - /// - /// If you call this function (or one of `certification_capable` - /// or `signing_capable` functions) multiple times, the *union* of - /// the values is used. Thus, - /// `tpk.flags().certification_capable().signing_capable()` will - /// return keys that are certification capable or signing capable. - /// - /// If you need more complex filtering, e.g., you want a key that - /// is both certification and signing capable, then just use a - /// normal [`Iterator::filter`]. - /// - /// [`Iterator::filter`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter - pub fn key_flags(mut self, flags: KeyFlags) -> Self { - if let Some(flags_old) = self.flags { - self.flags = Some(&flags | &flags_old); - } else { - self.flags = Some(flags); - } - self - } - - /// Returns keys that are certification capable. - /// - /// See `key_flags` for caveats. - pub fn certification_capable(self) -> Self { - self.key_flags(KeyFlags::default().set_certify(true)) - } - - /// Returns keys that are signing capable. - /// - /// See `key_flags` for caveats. - pub fn signing_capable(self) -> Self { - self.key_flags(KeyFlags::default().set_sign(true)) - } - - /// Returns keys that are authentication capable. - /// - /// See `key_flags` for caveats. - pub fn authentication_capable(self) -> Self { - self.key_flags(KeyFlags::default().set_authenticate(true)) - } - - /// Returns keys that are capable of encrypting data at rest. - /// - /// See `key_flags` for caveats. - pub fn encrypting_capable_at_rest(self) -> Self { - self.key_flags(KeyFlags::default().set_encrypt_at_rest(true)) - } - - /// Returns keys that are capable of encrypting data for transport. - /// - /// See `key_flags` for caveats. - pub fn encrypting_capable_for_transport(self) -> Self { - self.key_flags(KeyFlags::default().set_encrypt_for_transport(true)) - } - - /// Only returns keys that are live as of `now`. - /// - /// If `now` is none, then all keys are returned whether they are - /// live or not. - /// - /// A value of None disables this filter, which is set by default - /// to only return live keys at the current time. - /// - /// If you call this function (or `alive`) multiple times, only - /// the last value is used. - pub fn alive_at(mut self, alive_at: T) -> Self - where T: Into> - { - self.alive_at = alive_at.into(); - self - } - - /// Only returns keys that are live right now. - /// - /// If you call this function (or `alive_at`) multiple times, only - /// the last value is used. - pub fn alive(mut self) -> Self - { - self.alive_at = Some(std::time::SystemTime::now().canonicalize()); - self - } - - /// If not None, filters by whether a key is definitely revoked. - /// - /// That is, whether it's revocation status is - /// `RevocationStatus::Revoked`. - /// - /// A value of None disables this filter, which is set by default - /// to not return revoked keys. - /// - /// If you call this function multiple times, only the last value - /// is used. - pub fn revoked(mut self, revoked: T) -> Self - where T: Into> - { - self.revoked = revoked.into(); - self - } - - /// Changes the filter to only return keys with secret key material. - pub fn secret(self) -> KeyIter<'a, key::SecretParts, R> { - KeyIter { - tpk: self.tpk, - primary: self.primary, - subkey_iter: self.subkey_iter, - - // The filters. - flags: self.flags, - alive_at: self.alive_at, - revoked: self.revoked, - secret: Some(true), - unencrypted_secret: self.unencrypted_secret, - - _p: std::marker::PhantomData, - _r: std::marker::PhantomData, - } - } - - /// Changes the filter to only return keys with unencrypted secret - /// key material. - pub fn unencrypted_secret(self) -> KeyIter<'a, key::SecretParts, R> { - KeyIter { - tpk: self.tpk, - primary: self.primary, - subkey_iter: self.subkey_iter, - - // The filters. - flags: self.flags, - alive_at: self.alive_at, - revoked: self.revoked, - secret: self.secret, - unencrypted_secret: Some(true), - - _p: std::marker::PhantomData, - _r: std::marker::PhantomData, - } - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::{ - parse::Parse, - tpk::builder::TPKBuilder, - }; - - #[test] - fn key_iter_test() { - let key = TPK::from_bytes(crate::tests::key("neal.pgp")).unwrap(); - assert_eq!(1 + key.subkeys().count(), - key.keys_all().count()); - } - - #[test] - fn select_no_keys() { - let (tpk, _) = TPKBuilder::new() - .generate().unwrap(); - let flags = KeyFlags::default().set_encrypt_for_transport(true); - - assert_eq!(tpk.keys_all().key_flags(flags).count(), 0); - } - - #[test] - fn select_valid_and_right_flags() { - let (tpk, _) = TPKBuilder::new() - .add_encryption_subkey() - .generate().unwrap(); - let flags = KeyFlags::default().set_encrypt_for_transport(true); - - assert_eq!(tpk.keys_all().key_flags(flags).count(), 1); - } - - #[test] - fn select_valid_and_wrong_flags() { - let (tpk, _) = TPKBuilder::new() - .add_encryption_subkey() - .add_signing_subkey() - .generate().unwrap(); - let flags = KeyFlags::default().set_encrypt_for_transport(true); - - assert_eq!(tpk.keys_all().key_flags(flags).count(), 1); - } - - #[test] - fn select_invalid_and_right_flags() { - let (tpk, _) = TPKBuilder::new() - .add_encryption_subkey() - .generate().unwrap(); - let flags = KeyFlags::default().set_encrypt_for_transport(true); - - let now = std::time::SystemTime::now().canonicalize() - - std::time::Duration::new(52 * 7 * 24 * 60 * 60, 0); - assert_eq!(tpk.keys_all().key_flags(flags).alive_at(now).count(), 0); - } - - #[test] - fn select_primary() { - let (tpk, _) = TPKBuilder::new() - .add_certification_subkey() - .generate().unwrap(); - let flags = KeyFlags::default().set_certify(true); - - assert_eq!(tpk.keys_all().key_flags(flags).count(), 2); - } - - #[test] - fn selectors() { - let (tpk, _) = TPKBuilder::new() - .add_signing_subkey() - .add_certification_subkey() - .add_encryption_subkey() - .add_authentication_subkey() - .generate().unwrap(); - assert_eq!(tpk.keys_valid().certification_capable().count(), 2); - assert_eq!(tpk.keys_valid().encrypting_capable_for_transport().count(), - 1); - assert_eq!(tpk.keys_valid().encrypting_capable_at_rest().count(), 1); - assert_eq!(tpk.keys_valid().signing_capable().count(), 1); - assert_eq!(tpk.keys_valid().key_flags( - KeyFlags::default().set_authenticate(true)).count(), 1); - } -} -- cgit v1.2.3