use std::fmt;
use std::convert::{TryFrom, TryInto};
use std::time::SystemTime;
use std::borrow::Borrow;
use crate::{
KeyHandle,
RevocationStatus,
packet::key,
packet::key::SecretKeyMaterial,
types::KeyFlags,
cert::{
Cert,
components::{
Amalgamation,
KeyBundle,
UnfilteredKeyBundleIter,
},
KeyAmalgamation,
ValidKeyAmalgamation,
},
policy::Policy,
};
pub struct KeyIter<'a, P: key::KeyParts> {
cert: Option<&'a Cert>,
primary: bool,
subkey_iter: UnfilteredKeyBundleIter<'a,
key::PublicParts,
key::SubordinateRole>,
secret: Option<bool>,
unencrypted_secret: Option<bool>,
key_handles: Vec<KeyHandle>,
_p: std::marker::PhantomData<P>,
}
impl<'a, P: key::KeyParts> fmt::Debug for KeyIter<'a, P>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("KeyIter")
.field("secret", &self.secret)
.field("unencrypted_secret", &self.unencrypted_secret)
.field("key_handles", &self.key_handles)
.finish()
}
}
macro_rules! impl_iterator {
($parts:path) => {
impl<'a> Iterator for KeyIter<'a, $parts>
{
type Item = KeyAmalgamation<'a, $parts>;
fn next(&mut self) -> Option<Self::Item> {
self.next_common().map(|k| k.into())
}
}
}
}
impl_iterator!(key::PublicParts);
impl_iterator!(key::UnspecifiedParts);
impl<'a> Iterator for KeyIter<'a, key::SecretParts> {
type Item = KeyAmalgamation<'a, key::SecretParts>;
fn next(&mut self) -> Option<Self::Item> {
self.next_common().map(|k| k.try_into().expect("has secret parts"))
}
}
impl<'a, P: 'a + key::KeyParts> KeyIter<'a, P> {
fn next_common(&mut self) -> Option<KeyAmalgamation<'a, key::PublicParts>>
{
tracer!(false, "KeyIter::next", 0);
t!("KeyIter: {:?}", self);
if self.cert.is_none() {
return None;
}
let cert = self.cert.unwrap();
loop {
let ka : KeyAmalgamation<key::PublicParts>
= if ! self.primary {
self.primary = true;
KeyAmalgamation::new_primary(cert)
} else {
KeyAmalgamation::new_subordinate(
cert, self.subkey_iter.next()?)
};
t!("Considering key: {:?}", ka.key());
if self.key_handles.len() > 0 {
if !self.key_handles
.iter()
.any(|h| h.aliases(ka.key().key_handle()))
{
t!("{} is not one of the keys that we are looking for ({:?})",
ka.key().fingerprint(), self.key_handles);
continue;
}
}
if let Some(want_secret) = self.secret {
if ka.key().secret().is_some() {
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) = ka.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 {
t!("No secret... skipping.");
continue;
}
}
return Some(ka);
}
}
}
impl<'a, P: 'a + key::KeyParts> KeyIter<'a, P>
{
pub(crate) fn new(cert: &'a Cert) -> Self where Self: 'a {
KeyIter {
cert: Some(cert),
primary: false,
subkey_iter: cert.subkeys(),
secret: None,
unencrypted_secret: None,
key_handles: Vec::with_capacity(0),
_p: std::marker::PhantomData,
}
}
pub fn secret(self) -> KeyIter<'a, key::SecretParts> {
KeyIter {
cert: self.cert,
primary: self.primary,
subkey_iter: self.subkey_iter,
secret: Some(true),
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
_p: std::marker::PhantomData,
}
}
pub fn unencrypted_secret(self) -> KeyIter<'a, key::SecretParts> {
KeyIter {
cert: self.cert,
primary: self.primary,
subkey_iter: self.subkey_iter,
secret: self.secret,
unencrypted_secret: Some(true),
key_handles: self.key_handles,
_p: std::marker::PhantomData,
}
}
pub fn key_handle<H>(mut self, h: H) -> Self
where H: Into<KeyHandle>
{
self.key_handles.push(h.into());
self
}
pub fn key_handles<'b>(mut self, h: impl Iterator<Item=&'b KeyHandle>)
-> Self
where 'a: 'b
{
self.key_handles.extend(h.map(|h| h.clone()));
self
}
pub fn skip_primary(mut self) -> Self {
self.primary = true;
self
}
pub fn with_policy<T>(self, policy: &'a dyn Policy, time: T)
-> ValidKeyIter<'a, P>
where T: Into<Option<SystemTime>>
{
ValidKeyIter {
cert: self.cert,
primary: self.primary,
subkey_iter: self.subkey_iter,
policy: policy,
time: time.into().unwrap_or_else(SystemTime::now),
secret: self.secret,
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
flags: None,
alive: None,
revoked: None,
_p: self._p,
}
}
pub fn bundles(self) -> KeyBundleIter<'a, P, key::UnspecifiedRole> {
KeyBundleIter {
cert: self.cert,
primary: self.primary,
subkey_iter: self.subkey_iter,
secret: self.secret,
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
_p: std::marker::PhantomData,
_r: std::marker::PhantomData,
}
}
pub fn subkeys(self) -> KeyBundleIter<'a, P, key::SubordinateRole> {
KeyBundleIter {
cert: self.cert,
primary: true,
subkey_iter: self.subkey_iter,
secret: self.secret,
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
_p: std::marker::PhantomData,
_r: std::marker::PhantomData,
}
}
}
pub struct ValidKeyIter<'a, P: key::KeyParts> {
cert: Option<&'a Cert>,
primary: bool,
subkey_iter: UnfilteredKeyBundleIter<'a,
key::PublicParts,
key::SubordinateRole>,
policy: &'a dyn Policy,
time: SystemTime,
secret: Option<bool>,
unencrypted_secret: Option<bool>,
key_handles: Vec<KeyHandle>,
flags: Option<KeyFlags>,
alive: Option<()>,
revoked: Option<bool>,
_p: std::marker::PhantomData<P>,
}
impl<'a, P: key::KeyParts> fmt::Debug for ValidKeyIter<'a, P>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ValidKeyIter")
.field("policy", &self.policy)
.field("time", &self.time)
.field("secret", &self.secret)
.field("unencrypted_secret", &self.unencrypted_secret)
.field("key_handles", &self.key_handles)
.field("flags", &self.flags)
.field("alive", &self.alive)
.field("revoked", &self.revoked)
.finish()
}
}
macro_rules! impl_valid_key_iterator {
($parts:path) => {
impl<'a> Iterator for ValidKeyIter<'a, $parts>
{
type Item = ValidKeyAmalgamation<'a, $parts>;
fn next(&mut self) -> Option<Self::Item> {
self.next_common().map(|ka| ka.into())
}
}
}
}
impl_valid_key_iterator!(key::PublicParts);
impl_valid_key_iterator!(key::UnspecifiedParts);
impl<'a> Iterator for ValidKeyIter<'a, key::SecretParts>
{
type Item = ValidKeyAmalgamation<'a, key::SecretParts>;
fn next(&mut self) -> Option<Self::Item> {
self.next_common().map(|ka| ka.try_into().expect("has secret parts"))
}
}
impl<'a, P: 'a + key::KeyParts> ValidKeyIter<'a, P> {
fn next_common(&mut self) -> Option<ValidKeyAmalgamation<'a, key::PublicParts>>
{
tracer!(false, "ValidKeyIter::next", 0);
t!("ValidKeyIter: {:?}", self);
if self.cert.is_none() {
return None;
}
let cert = self.cert.unwrap();
if let Some(flags) = self.flags.as_ref() {
if flags.is_empty() {
t!("short circuiting: flags is empty");
return None;
}
}
loop {
let ka : ValidKeyAmalgamation<'a, key::PublicParts>
= if ! self.primary {
self.primary = true;
let ka = KeyAmalgamation::new_primary(cert);
match ka.with_policy(self.policy, self.time) {
Ok(ka) => ka,
Err(err) => {
t!("Getting primary key: {:?}", err);
return None;
}
}
} else {
let ka = KeyAmalgamation::new_subordinate(
cert.into(), self.subkey_iter.next()?);
match ka.with_policy(self.policy, self.time) {
Ok(ka) => ka,
Err(err) => {
t!("Getting subkey: {:?}", err);
continue;
}
}
};
let key = ka.key();
t!("Considering key: {:?}", key);
if self.key_handles.len() > 0 {
if !self.key_handles
.iter()
.any(|h| h.aliases(key.key_handle()))
{
t!("{} is not one of the keys that we are looking for ({:?})",
key.key_handle(), self.key_handles);
continue;
}
}
if let Some(flags) = self.flags.as_ref() {
if !ka.has_any_key_flag(flags) {
t!("Have flags: {:?}, want flags: {:?}... skipping.",
flags, flags);
continue;
}
}
if let Some(()) = self.alive {
if let Err(err) = ka.alive() {
t!("Key not alive: {:?}", err);
continue;
}
}
if let Some(want_revoked) = self.revoked {
if let RevocationStatus::Revoked(_) = ka.revoked() {
if ! want_revoked {
t!("Key revoked... skipping.");
continue;
}
} else {
if want_revoked {
t!("Key not revoked... skipping.");
continue;
}
}
}
if let Some(want_secret) = self.secret {
if key.secret().is_some() {
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 {
t!("No secret... skipping.");
continue;
}
}
return Some(ka.into());
}
}
}
impl<'a, P: 'a + key::KeyParts> ValidKeyIter<'a, P>
{
pub fn key_flags<F>(mut self, flags: F) -> Self
where F: Borrow<KeyFlags>
{
let flags = flags.borrow();
if let Some(flags_old) = self.flags {
self.flags = Some(flags | &flags_old);
} else {
self.flags = Some(flags.clone());
}
self
}
pub fn for_certification(self) -> Self {
self.key_flags(KeyFlags::default().set_certification(true))
}
pub fn for_signing(self) -> Self {
self.key_flags(KeyFlags::default().set_signing(true))
}
pub fn for_authentication(self) -> Self {
self.key_flags(KeyFlags::default().set_authentication(true))
}
pub fn for_storage_encryption(self) -> Self {
self.key_flags(KeyFlags::default().set_storage_encryption(true))
}
pub fn for_transport_encryption(self) -> Self {
self.key_flags(KeyFlags::default().set_transport_encryption(true))
}
pub fn alive(mut self) -> Self
{
self.alive = Some(());
self
}
pub fn revoked<T>(mut self, revoked: T) -> Self
where T: Into<Option<bool>>
{
self.revoked = revoked.into();
self
}
pub fn secret(self) -> ValidKeyIter<'a, key::SecretParts> {
ValidKeyIter {
cert: self.cert,
primary: self.primary,
subkey_iter: self.subkey_iter,
time: self.time,
policy: self.policy,
secret: Some(true),
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
flags: self.flags,
alive: self.alive,
revoked: self.revoked,
_p: std::marker::PhantomData,
}
}
pub fn unencrypted_secret(self) -> ValidKeyIter<'a, key::SecretParts> {
ValidKeyIter {
cert: self.cert,
primary: self.primary,
subkey_iter: self.subkey_iter,
time: self.time,
policy: self.policy,
secret: self.secret,
unencrypted_secret: Some(true),
key_handles: self.key_handles,
flags: self.flags,
alive: self.alive,
revoked: self.revoked,
_p: std::marker::PhantomData,
}
}
pub fn key_handle<H>(mut self, h: H) -> Self
where H: Into<KeyHandle>
{
self.key_handles.push(h.into());
self
}
pub fn key_handles<'b>(mut self, h: impl Iterator<Item=&'b KeyHandle>)
-> Self
where 'a: 'b
{
self.key_handles.extend(h.map(|h| h.clone()));
self
}
}
pub struct KeyBundleIter<'a, P: key::KeyParts, R: key::KeyRole> {
cert: Option<&'a Cert>,
primary: bool,
subkey_iter: UnfilteredKeyBundleIter<'a,
key::PublicParts,
key::SubordinateRole>,
secret: Option<bool>,
unencrypted_secret: Option<bool>,
key_handles: Vec<KeyHandle>,
_p: std::marker::PhantomData<P>,
_r: std::marker::PhantomData<R>,
}
impl<'a, P: key::KeyParts, R: key::KeyRole> fmt::Debug
for KeyBundleIter<'a, P, R>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("KeyBundleIter")
.field("primary", &self.primary)
.field("secret", &self.secret)
.field("unencrypted_secret", &self.unencrypted_secret)
.field("key_handles", &self.key_handles)
.finish()
}
}
macro_rules! impl_key_component_iterator {
($parts:path) => {
impl<'a, R: 'a + key::KeyRole> Iterator for KeyBundleIter<'a, $parts, R>
where &'a KeyBundle<$parts, R>:
From<&'a KeyBundle<key::PublicParts, key::UnspecifiedRole>>
{
type Item = &'a KeyBundle<$parts, R>;
fn next(&mut self) -> Option<Self::Item> {
self.next_common().map(|b| b.into())
}
}
}
}
impl_key_component_iterator!(key::PublicParts);
impl_key_component_iterator!(key::UnspecifiedParts);
impl<'a, R: 'a + key::KeyRole, E> Iterator for KeyBundleIter<'a, key::SecretParts, R>
where &'a KeyBundle<key::SecretParts, R>:
TryFrom<&'a KeyBundle<key::PublicParts, key::UnspecifiedRole>,
Error = E>,
E: std::fmt::Debug,
{
type Item = &'a KeyBundle<key::SecretParts, R>;
fn next(&mut self) -> Option<Self::Item> {
self.next_common().map(|ka| ka.try_into().expect("has secret parts"))
}
}
impl<'a, P: 'a + key::KeyParts, R: 'a + key::KeyRole> KeyBundleIter<'a, P, R>
{
fn next_common(&mut self) -> Option<&'a KeyBundle<key::PublicParts, key::UnspecifiedRole>>
{
tracer!(false, "KeyBundleIter::next", 0);
t!("KeyBundleIter: {:?}", self);
if self.cert.is_none() {
return None;
}
let cert = self.cert.unwrap();
loop {
let binding =
if ! self.primary {
self.primary = true;
cert.primary.mark_role_unspecified_ref()
} else {
self.subkey_iter.next()?.mark_role_unspecified_ref()
};
let key = binding.key();
t!("Considering key: {:?}", key);
if self.key_handles.len() > 0 {
if !self.key_handles
.iter()
.any(|h| h.aliases(key.key_handle()))
{
t!("{} is not one of the keys that we are looking for ({:?})",
key.key_handle(), self.key_handles);
continue;
}
}
if let Some(want_secret) = self.secret {
if key.secret().is_some() {
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 {
t!("No secret... skipping.");
continue;
}
}
return Some(binding);
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{
parse::Parse,
cert::builder::CertBuilder,
};
use crate::policy::StandardPolicy as P;
#[test]
fn key_iter_test() {
let key = Cert::from_bytes(crate::tests::key("neal.pgp")).unwrap();
assert_eq!(1 + key.subkeys().count(),
key.keys().count());
}
#[test]
fn select_no_keys() {
let p = &P::new();
let (cert, _) = CertBuilder::new()
.generate().unwrap();
let flags = KeyFlags::default().set_transport_encryption(true);
assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 0);
}
#[test]
fn select_valid_and_right_flags() {
let p = &P::new();
let (cert, _) = CertBuilder::new()
.add_transport_encryption_subkey()
.generate().unwrap();
let flags = KeyFlags::default().set_transport_encryption(true);
assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 1);
}
#[test]
fn select_valid_and_wrong_flags() {
let p = &P::new();
let (cert, _) = CertBuilder::new()
.add_transport_encryption_subkey()
.add_signing_subkey()
.generate().unwrap();
let flags = KeyFlags::default().set_transport_encryption(true);
assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 1);
}
#[test]
fn select_invalid_and_right_flags() {
let p = &P::new();
let (cert, _) = CertBuilder::new()
.add_transport_encryption_subkey()
.generate().unwrap();
let flags = KeyFlags::default().set_transport_encryption(true);
let now = SystemTime::now()
- std::time::Duration::new(52 * 7 * 24 * 60 * 60, 0);
assert_eq!(cert.keys().with_policy(p, now).key_flags(flags).alive().count(),
0);
}
#[test]
fn select_primary() {
let p = &P::new();
let (cert, _) = CertBuilder::new()
.add_certification_subkey()
.generate().unwrap();
let flags = KeyFlags::default().set_certification(true);
assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(),
2);
}
#[test]
fn selectors() {
let p = &P::new();
let (cert, _) = CertBuilder::new()
.add_signing_subkey()
.add_certification_subkey()
.add_transport_encryption_subkey()
.add_storage_encryption_subkey()
.add_authentication_subkey()
.generate().unwrap();
assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
.for_certification().count(),
2);
assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
.for_transport_encryption().count(),
1);
assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
.for_storage_encryption().count(),
1);
assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
.for_signing().count(),
1);
assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
.key_flags(KeyFlags::default().set_authentication(true))
.count(),
1);
}
#[test]
fn select_key_handle() {
let p = &P::new();
let (cert, _) = CertBuilder::new()
.add_signing_subkey()
.add_certification_subkey()
.add_transport_encryption_subkey()
.add_storage_encryption_subkey()
.add_authentication_subkey()
.generate().unwrap();
let keys = cert.keys().count();
assert_eq!(keys, 6);
let keyids = cert.keys().map(|ka| ka.key().keyid()).collect::<Vec<_>>();
fn check(got: &[KeyHandle], expected: &[KeyHandle]) {
if expected.len() != got.len() {
panic!("Got {}, expected {} handles",
got.len(), expected.len());
}
for (g, e) in got.iter().zip(expected.iter()) {
if !e.aliases(g) {
panic!(" Got: {:?}\nExpected: {:?}",
got, expected);
}
}
}
for i in 1..keys {
for keyids in keyids[..].windows(i) {
let keyids : Vec<KeyHandle>
= keyids.iter().map(Into::into).collect();
assert_eq!(keyids.len(), i);
check(
&cert.keys().key_handles(keyids.iter())
.map(|ka| ka.key().key_handle())
.collect::<Vec<KeyHandle>>(),
&keyids);
check(
&cert.keys().with_policy(p, None).key_handles(keyids.iter())
.map(|ka| ka.key().key_handle())
.collect::<Vec<KeyHandle>>(),
&keyids);
check(
&cert.keys().key_handles(keyids.iter()).with_policy(p, None)
.map(|ka| ka.key().key_handle())
.collect::<Vec<KeyHandle>>(),
&keyids);
}
}
}
}