use std::ops::Deref;
use std::time;
use crate::{
HashAlgorithm,
Result,
SignatureType,
};
use crate::types::{
ReasonForRevocation,
};
use crate::crypto::hash::Hash;
use crate::crypto::Signer;
use crate::packet::{
Key,
key,
signature,
Signature,
UserAttribute,
UserID,
};
use crate::cert::prelude::*;
/// A builder for revocation certificates for OpenPGP certificates.
///
/// A revocation certificate for an OpenPGP certificate (as opposed
/// to, say, a subkey) has two degrees of freedom: the certificate,
/// and the key used to sign the revocation certificate.
///
/// Normally, the key used to sign the revocation certificate is the
/// certificate's primary key. However, this is not required. For
/// instance, if Alice has marked Robert's certificate (`R`) as a
/// [designated revoker] for her certificate (`A`), then `R` can
/// revoke `A` or parts of `A`. In this case, the certificate is `A`,
/// and the key used to sign the revocation certificate comes from
/// `R`.
///
/// [designated revoker]: https://tools.ietf.org/html/rfc4880#section-5.2.3.15
///
/// # Examples
///
/// Revoke `cert`, which was compromised yesterday:
///
/// ```rust
/// use sequoia_openpgp as openpgp;
/// # use openpgp::Result;
/// use openpgp::cert::prelude::*;
/// use openpgp::policy::StandardPolicy;
/// use openpgp::types::ReasonForRevocation;
/// use openpgp::types::RevocationStatus;
/// use openpgp::types::SignatureType;
///
/// # fn main() -> Result<()> {
/// let p = &StandardPolicy::new();
///
/// # let (cert, _) = CertBuilder::new()
/// # .generate()?;
/// # assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
/// # cert.revocation_status(p, None));
/// #
/// // Create and sign a revocation certificate.
/// let mut signer = cert.primary_key().key().clone()
/// .parts_into_secret()?.into_keypair()?;
/// # let yesterday = std::time::SystemTime::now();
/// let sig = CertRevocationBuilder::new()
/// // Don't use the current time, since the certificate was
/// // actually compromised yesterday.
/// .set_signature_creation_time(yesterday)?
/// .set_reason_for_revocation(ReasonForRevocation::KeyCompromised,
/// b"It was the maid :/")?
/// .build(&mut signer, &cert, None)?;
///
/// // Merge it into the certificate.
/// let cert = cert.insert_packets(sig.clone())?;
///
/// // Now it's revoked.
/// assert_eq!(RevocationStatus::Revoked(vec![&sig]),
/// cert.revocation_status(p, None));
/// # Ok(())
/// # }
pub struct CertRevocationBuilder {
builder: signature::SignatureBuilder,
}
assert_send_and_sync!{CertRevocationBuilder}
impl CertRevocationBuilder {
/// Returns a new `CertRevocationBuilder`.
///
/// # Examples
///
/// ```rust
/// use sequoia_openpgp as openpgp;
/// # use openpgp::Result;
/// use openpgp::cert::prelude::*;
///
/// # fn main() -> Result<()> {
/// let builder = CertRevocationBuilder::new();
/// # Ok(())
/// # }
pub fn new() -> Self {
Self {
builder:
signature::SignatureBuilder::new(SignatureType::KeyRevocation)
}
}
/// Sets the reason for revocation.
///
/// # Examples
///
/// ```rust
/// use sequoia_openpgp as openpgp;
/// # use openpgp::Result;
/// use openpgp::cert::prelude::*;
/// use openpgp::types::ReasonForRevocation;
///
/// # fn main() -> Result<()> {
/// let builder = CertRevocationBuilder::new()
/// .set_reason_for_revocation(ReasonForRevocation::KeyRetired,
/// b"I'm retiring this key. \
/// Please use my new OpenPGP certificate (FPR)");
/// # Ok(())
/// # }
pub fn set_reason_for_revocation(self, code: ReasonForRevocation,
reason: &[u8])
-> Result<Self>
{
Ok(Self {
builder: self.builder.set_reason_for_revocation(code, reason)?
})
}
/// Sets the revocation certificate's creation time.
///
/// The creation time is interpreted as the time at which the
/// certificate should be considered revoked. For a soft
/// revocation, artifacts created prior to the revocation are
/// still considered valid.
///
/// You'll usually want to set this explicitly and not use the
/// current time.
///
/// First, the creation time should reflect the time of the event
/// that triggered the revocation. As such, if it is discovered
/// that a certificate was compromised a week ago, then the
/// revocation certificate should be backdated appropriately.
///
/// Second,