Struct ValidCert

Source
pub struct ValidCert<'a> { /* private fields */ }
Expand description

A Cert plus a Policy and a reference time.

A ValidCert combines a Cert with a Policy and a reference time. This allows it to implement methods that require a Policy and a reference time without requiring the caller to explicitly pass them in. Embedding them in the ValidCert data structure rather than having the caller pass them in explicitly helps ensure that multipart operations, even those that span multiple functions, use the same Policy and reference time. This avoids a subtle class of bugs in which different views of a certificate are unintentionally used.

A ValidCert is typically obtained by transforming a Cert using Cert::with_policy.

A ValidCert is guaranteed to have a valid and live binding signature at the specified reference time. Note: this only means that the binding signature is live; it says nothing about whether the certificate or any component is live. If you care about those things, then you need to check them separately.

§Examples

use sequoia_openpgp as openpgp;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let vc = cert.with_policy(p, None)?;

Implementations§

Source§

impl<'a> ValidCert<'a>

Source

pub fn cert(&self) -> &'a Cert

Returns the underlying certificate.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let vc = cert.with_policy(p, None)?;
assert!(std::ptr::eq(vc.cert(), &cert));
Source

pub fn time(&self) -> SystemTime

Returns the associated reference time.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let t = UNIX_EPOCH + Duration::from_secs(1307732220);
let vc = cert.with_policy(p, t)?;
assert_eq!(vc.time(), t);
Source

pub fn policy(&self) -> &'a dyn Policy

Returns the associated policy.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let vc = cert.with_policy(p, None)?;
assert!(std::ptr::eq(vc.policy(), p));
Source

pub fn with_policy<T>( self, policy: &'a dyn Policy, time: T, ) -> Result<ValidCert<'a>>
where T: Into<Option<SystemTime>>,

Changes the associated policy and reference time.

If time is None, the current time is used.

Returns an error if the certificate is not valid for the given policy at the specified time.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::policy::{StandardPolicy, NullPolicy};

let sp = &StandardPolicy::new();
let vc = cert.with_policy(sp, None)?;

// ...

// Now with a different policy.
let np = unsafe { &NullPolicy::new() };
let vc = vc.with_policy(np, None)?;
Source

pub fn direct_key_signature(&self) -> Result<&'a Signature>

Returns the certificate’s direct key signature as of the reference time.

Subpackets on direct key signatures apply to all components of the certificate, cf. Section 5.2.3.10 of RFC 9580.

§Examples
use sequoia_openpgp as openpgp;
use sequoia_openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let vc = cert.with_policy(p, None)?;
println!("{:?}", vc.direct_key_signature());
Source

pub fn revocation_status(&self) -> RevocationStatus<'a>

Returns the certificate’s revocation status.

A certificate is considered revoked at time t if:

  • There is a valid and live revocation at time t that is newer than all valid and live self signatures at time t, or

  • There is a valid hard revocation (even if it is not live at time t, and even if there is a newer self signature).

Note: certificates and subkeys have different revocation criteria from User IDs and User Attributes.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::types::RevocationStatus;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let (cert, rev) =
    CertBuilder::general_purpose(Some("alice@example.org"))
    .generate()?;

// Not revoked.
assert_eq!(cert.with_policy(p, None)?.revocation_status(),
           RevocationStatus::NotAsFarAsWeKnow);

// Merge the revocation certificate.  `cert` is now considered
// to be revoked.
let cert = cert.insert_packets(rev.clone())?.0;
assert_eq!(cert.with_policy(p, None)?.revocation_status(),
           RevocationStatus::Revoked(vec![&rev.into()]));
Source

pub fn alive(&self) -> Result<()>

Returns whether the certificate is alive at the reference time.

A certificate is considered to be alive at time t if the primary key is alive at time t.

A valid certificate’s primary key is guaranteed to have a live binding signature, however, that does not mean that the primary key is necessarily alive.

§Examples
use std::time;
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let a_second = time::Duration::from_secs(1);

let creation_time = time::SystemTime::now();
let before_creation = creation_time - a_second;
let validity_period = 60 * a_second;
let expiration_time = creation_time + validity_period;
let before_expiration_time = expiration_time - a_second;
let after_expiration_time = expiration_time + a_second;

let (cert, _) = CertBuilder::new()
    .add_userid("Alice")
    .set_creation_time(creation_time)
    .set_validity_period(validity_period)
    .generate()?;

// There is no binding signature before the certificate was created.
assert!(cert.with_policy(p, before_creation).is_err());
assert!(cert.with_policy(p, creation_time)?.alive().is_ok());
assert!(cert.with_policy(p, before_expiration_time)?.alive().is_ok());
// The binding signature is still alive, but the key has expired.
assert!(cert.with_policy(p, expiration_time)?.alive().is_err());
assert!(cert.with_policy(p, after_expiration_time)?.alive().is_err());
Source

pub fn primary_key(&self) -> ValidPrimaryKeyAmalgamation<'a, PublicParts>

Returns the certificate’s primary key.

A key’s secret key material may be protected with a password. In such cases, it needs to be decrypted before it can be used to decrypt data or generate a signature. Refer to Key::decrypt_secret for details.

§Examples
let primary = vc.primary_key();
// The certificate's fingerprint *is* the primary key's fingerprint.
assert_eq!(vc.cert().fingerprint(), primary.key().fingerprint());
Source

pub fn keys(&self) -> ValidKeyAmalgamationIter<'a, PublicParts, UnspecifiedRole>

Returns an iterator over the certificate’s valid keys.

That is, this returns an iterator over the primary key and any subkeys.

The iterator always returns the primary key first. The order of the subkeys is undefined.

To only iterate over the certificate’s subkeys, call ValidKeyAmalgamationIter::subkeys on the returned iterator instead of skipping the first key: this causes the iterator to return values with a more accurate type.

A key’s secret key material may be protected with a password. In such cases, it needs to be decrypted before it can be used to decrypt data or generate a signature. Refer to Key::decrypt_secret for details.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

// Create a key with two subkeys: one for signing and one for
// encrypting data in transit.
let (cert, _) = CertBuilder::new()
    .add_userid("Alice")
    .add_signing_subkey()
    .add_transport_encryption_subkey()
    .generate()?;
// They should all be valid.
assert_eq!(cert.with_policy(p, None)?.keys().count(), 1 + 2);
Source

pub fn primary_userid(&self) -> Result<ValidUserIDAmalgamation<'a>>

Returns the primary User ID at the reference time, if any.

A certificate may not have a primary User ID if it doesn’t have any valid User IDs. If a certificate has at least one valid User ID at time t, then it has a primary User ID at time t.

The primary User ID is determined as follows:

  • Discard User IDs that are not valid or not alive at time t.

  • Order the remaining User IDs by whether a User ID does not have a valid self-revocation (i.e., non-revoked first, ignoring third-party revocations).

  • Break ties by ordering by whether the User ID is marked as being the primary User ID.

  • Break ties by ordering by the binding signature’s creation time, most recent first.

If there are multiple User IDs that are ordered first, then one is chosen in a deterministic, but undefined manner (currently, we order the value of the User IDs lexographically, but you shouldn’t rely on this).

§Examples
use std::time;
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::packet::prelude::*;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let t1 = time::SystemTime::now();
let t2 = t1 + time::Duration::from_secs(1);

let (cert, _) = CertBuilder::new()
    .set_creation_time(t1)
    .add_userid("Alice")
    .generate()?;
let mut signer = cert
    .primary_key().key().clone().parts_into_secret()?.into_keypair()?;

// There is only one User ID.  It must be the primary User ID.
let vc = cert.with_policy(p, t1)?;
let alice = vc.primary_userid().unwrap();
assert_eq!(alice.userid().value(), b"Alice");
// By default, the primary User ID flag is set.
assert!(alice.binding_signature().primary_userid().is_some());

let template: signature::SignatureBuilder
    = alice.binding_signature().clone().into();

// Add another user id whose creation time is after the
// existing User ID, and doesn't have the User ID set.
let sig = template.clone()
    .set_signature_creation_time(t2)?
    .set_primary_userid(false)?;
let bob: UserID = "Bob".into();
let sig = bob.bind(&mut signer, &cert, sig)?;
let cert = cert.insert_packets(vec![Packet::from(bob), sig.into()])?.0;

// Alice should still be the primary User ID, because it has the
// primary User ID flag set.
let alice = cert.with_policy(p, t2)?.primary_userid().unwrap();
assert_eq!(alice.userid().value(), b"Alice");


// Add another User ID, whose binding signature's creation
// time is after Alice's and also has the primary User ID flag set.
let sig = template.clone()
   .set_signature_creation_time(t2)?;
let carol: UserID = "Carol".into();
let sig = carol.bind(&mut signer, &cert, sig)?;
let cert = cert.insert_packets(vec![Packet::from(carol), sig.into()])?.0;

// It should now be the primary User ID, because it is the
// newest User ID with the primary User ID bit is set.
let carol = cert.with_policy(p, t2)?.primary_userid().unwrap();
assert_eq!(carol.userid().value(), b"Carol");
Source

pub fn userids(&self) -> ValidUserIDAmalgamationIter<'a>

Returns an iterator over the certificate’s valid User IDs.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::packet::prelude::*;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

// `cert` was created at t0.  Add a second User ID at t1.
let userid = UserID::from("alice@example.com");
// Use the primary User ID's current binding signature as the
// basis for the new User ID's binding signature.
let template : signature::SignatureBuilder
    = cert.with_policy(p, None)?
          .primary_userid()?
          .binding_signature()
          .clone()
          .into();
let sig = template.set_signature_creation_time(t1)?;
let mut signer = cert
    .primary_key().key().clone().parts_into_secret()?.into_keypair()?;
let binding = userid.bind(&mut signer, &cert, sig)?;
// Merge it.
let cert = cert.insert_packets(
    vec![Packet::from(userid), binding.into()])?.0;

// At t0, the new User ID is not yet valid (it doesn't have a
// binding signature that is live at t0).  Thus, it is not
// returned.
let vc = cert.with_policy(p, t0)?;
assert_eq!(vc.userids().count(), 1);
// But, at t1, we see both User IDs.
let vc = cert.with_policy(p, t1)?;
assert_eq!(vc.userids().count(), 2);
Source

pub fn primary_user_attribute( &self, ) -> Result<ValidComponentAmalgamation<'a, UserAttribute>>

Returns the primary User Attribute, if any.

If a certificate has any valid User Attributes, then it has a primary User Attribute. In other words, it will not have a primary User Attribute at time t if there are no valid User Attributes at time t.

The primary User Attribute is determined in the same way as the primary User ID. See the documentation of ValidCert::primary_userid for details.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let vc = cert.with_policy(p, None)?;
let ua = vc.primary_user_attribute();
Source

pub fn user_attributes(&self) -> ValidUserAttributeAmalgamationIter<'a>

Returns an iterator over the certificate’s valid UserAttributes.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

// Add a User Attribute without a self-signature to the certificate.
let cert = cert.insert_packets(ua)?.0;
assert_eq!(cert.user_attributes().count(), 1);

// Without a self-signature, it is definitely not valid.
let vc = cert.with_policy(p, None)?;
assert_eq!(vc.user_attributes().count(), 0);
Source

pub fn revocation_keys(&self) -> impl Iterator<Item = &'a RevocationKey> + 'a

Returns a list of any designated revokers for this certificate.

This function returns the designated revokers listed on the primary key’s binding signatures and the certificate’s direct key signatures.

Note: the returned list is deduplicated.

In order to preserve our API during the 1.x series, this function takes an optional policy argument. It should be None, but if it is Some(_), it will be used instead of the ValidCert’s policy. This makes the function signature compatible with Cert::revocation_keys.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::policy::StandardPolicy;
use openpgp::types::RevocationKey;

let p = &StandardPolicy::new();

let (alice, _) =
    CertBuilder::general_purpose(Some("alice@example.org"))
    .generate()?;
// Make Alice a designated revoker for Bob.
let (bob, _) =
    CertBuilder::general_purpose(Some("bob@example.org"))
    .set_revocation_keys(vec![(&alice).into()])
    .generate()?;

// Make sure Alice is listed as a designated revoker for Bob.
assert_eq!(bob.with_policy(p, None)?.revocation_keys()
           .collect::<Vec<&RevocationKey>>(),
           vec![&(&alice).into()]);
Source

pub fn key_handle(&self) -> KeyHandle

Returns the certificate’s fingerprint as a KeyHandle.

§Examples
let p = &StandardPolicy::new();

println!("{}", cert.with_policy(p, None)?.key_handle());

// This always returns a fingerprint.
match cert.with_policy(p, None)?.key_handle() {
    KeyHandle::Fingerprint(_) => (),
    KeyHandle::KeyID(_) => unreachable!(),
}
Source

pub fn fingerprint(&self) -> Fingerprint

Returns the certificate’s fingerprint.

§Examples
let p = &StandardPolicy::new();

println!("{}", cert.with_policy(p, None)?.fingerprint());
Source

pub fn keyid(&self) -> KeyID

Returns the certificate’s Key ID.

As a general rule of thumb, you should prefer the fingerprint as it is possible to create keys with a colliding Key ID using a birthday attack.

§Examples
let p = &StandardPolicy::new();

println!("{}", cert.with_policy(p, None)?.keyid());

Trait Implementations§

Source§

impl<'a> Clone for ValidCert<'a>

Source§

fn clone(&self) -> ValidCert<'a>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Debug for ValidCert<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> Display for ValidCert<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> Preferences<'a> for ValidCert<'a>

Source§

fn preferred_symmetric_algorithms(&self) -> Option<&'a [SymmetricAlgorithm]>

Returns the supported symmetric algorithms ordered by preference. Read more
Source§

fn preferred_hash_algorithms(&self) -> Option<&'a [HashAlgorithm]>

Returns the supported hash algorithms ordered by preference. Read more
Source§

fn preferred_compression_algorithms(&self) -> Option<&'a [CompressionAlgorithm]>

Returns the supported compression algorithms ordered by preference. Read more
Source§

fn preferred_aead_ciphersuites( &self, ) -> Option<&'a [(SymmetricAlgorithm, AEADAlgorithm)]>

Returns the supported AEAD ciphersuites ordered by preference. Read more
Source§

fn key_server_preferences(&self) -> Option<KeyServerPreferences>

Returns the certificate holder’s keyserver preferences.
Source§

fn preferred_key_server(&self) -> Option<&'a [u8]>

Returns the certificate holder’s preferred keyserver for updates.
Source§

fn policy_uri(&self) -> Option<&'a [u8]>

Returns the URI of a document describing the policy the certificate was issued under.
Source§

fn features(&self) -> Option<Features>

Returns the certificate holder’s feature set.

Auto Trait Implementations§

§

impl<'a> Freeze for ValidCert<'a>

§

impl<'a> !RefUnwindSafe for ValidCert<'a>

§

impl<'a> Send for ValidCert<'a>

§

impl<'a> Sync for ValidCert<'a>

§

impl<'a> Unpin for ValidCert<'a>

§

impl<'a> !UnwindSafe for ValidCert<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> MaybeSendSync for T