use std::time;
use std::time::SystemTime;
use std::convert::TryInto;
use std::convert::TryFrom;
use std::borrow::Borrow;
use std::ops::Deref;
use crate::{
Cert,
cert::components::{
Amalgamation,
KeyBinding,
},
Error,
packet::key,
packet::key::SecretKeyMaterial,
packet::Key,
packet::Signature,
Result,
RevocationStatus,
types::KeyFlags,
};
/// 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, Clone)]
enum KeyAmalgamationBinding<'a, P: key::KeyParts> {
Primary(),
Subordinate(&'a KeyBinding<P, key::SubordinateRole>),
}
/// A `Key` and its associated data.
#[derive(Debug, Clone)]
pub struct KeyAmalgamation<'a, P: key::KeyParts> {
cert: &'a Cert,
binding: KeyAmalgamationBinding<'a, P>,
}
impl<'a, P: key::KeyParts> Deref for KeyAmalgamation<'a, P>
where &'a Key<P, key::UnspecifiedRole>: From<&'a key::PublicKey>
{
type Target = Key<P, key::UnspecifiedRole>;
fn deref(&self) -> &Self::Target {
self.key()
}
}
// 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 {
cert,
binding: KeyAmalgamationBinding::Primary(),
} =>
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Primary(),
},
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Subordinate(binding),
} =>
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Subordinate(binding.into()),
},
}
}
}
impl<'a> From<KeyAmalgamation<'a, key::SecretParts>>
for KeyAmalgamation<'a, key::PublicParts>
{
fn from(ka: KeyAmalgamation<'a, key::SecretParts>) -> Self {
match ka {
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Primary(),
} =>
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Primary(),
},
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Subordinate(binding),
} =>
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Subordinate(binding.into()),
},
}
}
}
impl<'a> TryFrom<KeyAmalgamation<'a, key::PublicParts>>
for KeyAmalgamation<'a, key::SecretParts>
{
type Error = failure::Error;
fn try_from(ka: KeyAmalgamation<'a, key::PublicParts>) -> Result<Self> {
Ok(match ka {
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Primary(),
} => {
// Error out if the primary key does not have secret
// key material.
let _ : &KeyBinding<key::SecretParts, key::PrimaryRole>
= (&cert.primary).try_into()?;
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Primary(),
}
}
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Subordinate(binding),
} =>
KeyAmalgamation {
cert,
binding: KeyAmalgamationBinding::Subordinate(binding.try_into()?),
},
})
}
}
impl<'a, P: 'a + key::KeyParts> KeyAmalgamation<'a, P> {
pub(crate) fn new_primary(cert: &'a Cert) -> Self {
Key