Struct sequoia_openpgp::cert::Cert

source ·
pub struct Cert { /* private fields */ }
Expand description

A collection of components and their associated signatures.

The Cert data structure mirrors the TPK and TSK data structures defined in RFC 4880. Specifically, it contains components (Keys, UserIDs, and UserAttributes), their associated self signatures, self revocations, third-party signatures, and third-party revocations, as well as useful methods.

Certs are canonicalized in the sense that their Components are deduplicated, and their signatures and revocations are deduplicated and checked for validity. The canonicalization routine does not throw away components that have no self signatures. These are returned as usual by, e.g., Cert::userids.

Keys are deduplicated by comparing their public bits using Key::public_cmp. If two keys are considered equal, and only one of them has secret key material, the key with the secret key material is preferred. If both keys have secret material, then one of them is chosen in a deterministic, but undefined manner, which is subject to change. Note: the secret key material is not integrity checked. Hence when updating a certificate with secret key material, it is essential to first strip the secret key material from copies that came from an untrusted source.

Signatures are deduplicated using their Eq implementation, which compares the data that is hashed and the MPIs. That is, it does not compare the unhashed data, the digest prefix and the unhashed subpacket area. If two signatures are considered equal, but have different unhashed data, the unhashed data are merged in a deterministic, but undefined manner, which is subject to change. This policy prevents an attacker from flooding a certificate with valid signatures that only differ in their unhashed data.

Self signatures and self revocations are checked for validity by making sure that the signature is mathematically correct. At this point, the signature is not checked against a Policy.

Third-party signatures and revocations are checked for validity by making sure the computed digest matches the digest prefix stored in the signature packet. This is not an integrity check and is easily spoofed. Unfortunately, at the time of canonicalization, the actual signatures cannot be checked, because the public keys are not available. If you rely on these signatures, it is up to you to check their validity by using an appropriate signature verification method, e.g., Signature::verify_userid_binding or Signature::verify_userid_revocation.

If a signature or a revocation is not valid, we check to see whether it is simply out of place (i.e., belongs to a different component) and, if so, we reorder it. If not, it is added to a list of bad signatures. These can be retrieved using Cert::bad_signatures.

Signatures and revocations are sorted so that the newest signature comes first. Components are sorted, but in an undefined manner (i.e., when parsing the same certificate multiple times, the components will be in the same order, but we reserve the right to change the sort function between versions).

§Secret Keys

Any key in a certificate may include secret key material. To protect secret key material from being leaked, secret keys are not written out when a Cert is serialized. To also serialize secret key material, you need to serialize the object returned by Cert::as_tsk().

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.

§Filtering Certificates

Component-wise filtering of userids, user attributes, and subkeys can be done with Cert::retain_userids, Cert::retain_user_attributes, and Cert::retain_subkeys.

If you need even more control, iterate over all components, clone what you want to keep, and then reassemble the certificate. The following example simply copies all the packets, and can be adapted to suit your policy:

use std::convert::TryFrom;
use openpgp::cert::prelude::*;

fn identity_filter(cert: &Cert) -> Result<Cert> {
    // Iterate over all of the Cert components, pushing packets we
    // want to keep into the accumulator.
    let mut acc = Vec::new();

    // Primary key and related signatures.
    let c = cert.primary_key();
    acc.push(c.key().clone().into());
    for s in c.self_signatures()   { acc.push(s.clone().into()) }
    for s in c.certifications()    { acc.push(s.clone().into()) }
    for s in c.self_revocations()  { acc.push(s.clone().into()) }
    for s in c.other_revocations() { acc.push(s.clone().into()) }

    // UserIDs and related signatures.
    for c in cert.userids() {
        acc.push(c.userid().clone().into());
        for s in c.self_signatures()   { acc.push(s.clone().into()) }
        for s in c.attestations()      { acc.push(s.clone().into()) }
        for s in c.certifications()    { acc.push(s.clone().into()) }
        for s in c.self_revocations()  { acc.push(s.clone().into()) }
        for s in c.other_revocations() { acc.push(s.clone().into()) }
    }

    // UserAttributes and related signatures.
    for c in cert.user_attributes() {
        acc.push(c.user_attribute().clone().into());
        for s in c.self_signatures()   { acc.push(s.clone().into()) }
        for s in c.attestations()      { acc.push(s.clone().into()) }
        for s in c.certifications()    { acc.push(s.clone().into()) }
        for s in c.self_revocations()  { acc.push(s.clone().into()) }
        for s in c.other_revocations() { acc.push(s.clone().into()) }
    }

    // Subkeys and related signatures.
    for c in cert.keys().subkeys() {
        acc.push(c.key().clone().into());
        for s in c.self_signatures()   { acc.push(s.clone().into()) }
        for s in c.certifications()    { acc.push(s.clone().into()) }
        for s in c.self_revocations()  { acc.push(s.clone().into()) }
        for s in c.other_revocations() { acc.push(s.clone().into()) }
    }

    // Unknown components and related signatures.
    for c in cert.unknowns() {
        acc.push(c.unknown().clone().into());
        for s in c.self_signatures()   { acc.push(s.clone().into()) }
        for s in c.certifications()    { acc.push(s.clone().into()) }
        for s in c.self_revocations()  { acc.push(s.clone().into()) }
        for s in c.other_revocations() { acc.push(s.clone().into()) }
    }

    // Any signatures that we could not associate with a component.
    for s in cert.bad_signatures()     { acc.push(s.clone().into()) }

    // Finally, parse into Cert.
    Cert::try_from(acc)
}

let (cert, _) =
    CertBuilder::general_purpose(None, Some("alice@example.org"))
    .generate()?;
assert_eq!(cert, identity_filter(&cert)?);

§A note on equality

We define equality on Cert as the equality of the serialized form as defined by RFC 4880. That is, two certs are considered equal if and only if their serialized forms are equal, modulo the OpenPGP packet framing (see Packet#a-note-on-equality).

Because secret key material is not emitted when a Cert is serialized, two certs are considered equal even if only one of them has secret key material. To take secret key material into account, compare the TSKs instead:

use openpgp::cert::prelude::*;

// Generate a cert with secrets.
let (cert_with_secrets, _) =
    CertBuilder::general_purpose(None, Some("alice@example.org"))
    .generate()?;

// Derive a cert without secrets.
let cert_without_secrets =
    cert_with_secrets.clone().strip_secret_key_material();

// Both are considered equal.
assert!(cert_with_secrets == cert_without_secrets);

// But not if we compare their TSKs:
assert!(cert_with_secrets.as_tsk() != cert_without_secrets.as_tsk());

§Examples

Parse a certificate:

use std::convert::TryFrom;
use sequoia_openpgp as openpgp;
use openpgp::Cert;

match Cert::try_from(ppr) {
    Ok(cert) => {
        println!("Key: {}", cert.fingerprint());
        for uid in cert.userids() {
            println!("User ID: {}", uid.userid());
        }
    }
    Err(err) => {
        eprintln!("Error parsing Cert: {}", err);
    }
}

Implementations§

source§

impl Cert

source

pub fn primary_key(&self) -> PrimaryKeyAmalgamation<'_, PublicParts>

Returns the primary key.

Unlike getting the certificate’s primary key using the Cert::keys method, this method does not erase the key’s role.

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

The first key returned by Cert::keys is the primary key, but its role has been erased:

assert_eq!(cert.primary_key().key().role_as_unspecified(),
           cert.keys().nth(0).unwrap().key());
source

pub fn revocation_status<T>( &self, policy: &dyn Policy, t: T, ) -> RevocationStatus<'_>
where T: Into<Option<SystemTime>>,

Returns the certificate’s revocation status.

Normally, methods that take a policy and a reference time are only provided by ValidCert. This method is provided here because there are two revocation criteria, and one of them is independent of the reference time. That is, even if it is not possible to turn a Cert into a ValidCert at time t, it may still be considered revoked at time t.

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(None, Some("alice@example.org"))
    .generate()?;

assert_eq!(cert.revocation_status(p, None), RevocationStatus::NotAsFarAsWeKnow);

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

pub fn revoke( &self, primary_signer: &mut dyn Signer, code: ReasonForRevocation, reason: &[u8], ) -> Result<Signature>

Generates a revocation certificate.

This is a convenience function around CertRevocationBuilder to generate a revocation certificate. To use the revocation certificate, merge it into the certificate using Cert::insert_packets.

If you want to revoke an individual component, use SubkeyRevocationBuilder, UserIDRevocationBuilder, or UserAttributeRevocationBuilder, as appropriate.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::types::{ReasonForRevocation, RevocationStatus, SignatureType};
use openpgp::cert::prelude::*;
use openpgp::crypto::KeyPair;
use openpgp::parse::Parse;
use openpgp::policy::StandardPolicy;

let p = &StandardPolicy::new();

let (cert, rev) = CertBuilder::new()
    .set_cipher_suite(CipherSuite::Cv25519)
    .generate()?;

// A new certificate is not revoked.
assert_eq!(cert.revocation_status(p, None),
           RevocationStatus::NotAsFarAsWeKnow);

// The default revocation certificate is a generic
// revocation.
assert_eq!(rev.reason_for_revocation().unwrap().0,
           ReasonForRevocation::Unspecified);

// Create a revocation to explain what *really* happened.
let mut keypair = cert.primary_key()
    .key().clone().parts_into_secret()?.into_keypair()?;
let rev = cert.revoke(&mut keypair,
                      ReasonForRevocation::KeyCompromised,
                      b"It was the maid :/")?;
let cert = cert.insert_packets(rev)?;
if let RevocationStatus::Revoked(revs) = cert.revocation_status(p, None) {
    assert_eq!(revs.len(), 1);
    let rev = revs[0];

    assert_eq!(rev.typ(), SignatureType::KeyRevocation);
    assert_eq!(rev.reason_for_revocation(),
               Some((ReasonForRevocation::KeyCompromised,
                     "It was the maid :/".as_bytes())));
} else {
    unreachable!()
}
source

pub fn set_expiration_time<T>( &self, policy: &dyn Policy, t: T, primary_signer: &mut dyn Signer, expiration: Option<SystemTime>, ) -> Result<Vec<Signature>>
where T: Into<Option<SystemTime>>,

Sets the certificate to expire at the specified time.

If no time (None) is specified, then the certificate is set to not expire.

This function creates new binding signatures that cause the certificate to expire at the specified time. Specifically, it updates the current binding signature on each of the valid, non-revoked User IDs, and the direct key signature, if any. This is necessary, because the primary User ID is first consulted when determining the certificate’s expiration time, and certificates can be distributed with a possibly empty subset of User IDs.

A policy is needed, because the expiration is updated by updating the current binding signatures.

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

let p = &StandardPolicy::new();

// The certificate is alive (not expired).
assert!(cert.with_policy(p, None)?.alive().is_ok());

// Make cert expire now.
let mut keypair = cert.primary_key()
    .key().clone().parts_into_secret()?.into_keypair()?;
let sigs = cert.set_expiration_time(p, None, &mut keypair,
                                    Some(time::SystemTime::now()))?;

let cert = cert.insert_packets(sigs)?;
assert!(cert.with_policy(p, None)?.alive().is_err());
source

pub fn userids(&self) -> UserIDAmalgamationIter<'_>

Returns an iterator over the certificate’s User IDs.

Note: This returns all User IDs, even those without a binding signature. This is not what you want, unless you are doing a low-level inspection of the certificate. Use ValidCert::userids instead. (You turn a Cert into a ValidCert by using Cert::with_policy.)

§Examples
println!("{}'s User IDs:", cert.fingerprint());
for ua in cert.userids() {
    println!("  {}", String::from_utf8_lossy(ua.value()));
}
source

pub fn user_attributes(&self) -> UserAttributeAmalgamationIter<'_>

Returns an iterator over the certificate’s User Attributes.

Note: This returns all User Attributes, even those without a binding signature. This is not what you want, unless you are doing a low-level inspection of the certificate. Use ValidCert::user_attributes instead. (You turn a Cert into a ValidCert by using Cert::with_policy.)

§Examples
println!("{}'s has {} User Attributes.",
         cert.fingerprint(),
         cert.user_attributes().count());
source

pub fn keys(&self) -> KeyAmalgamationIter<'_, PublicParts, UnspecifiedRole>

Returns an iterator over the certificate’s keys.

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

Note: This returns all keys, even those without a binding signature. This is not what you want, unless you are doing a low-level inspection of the certificate. Use ValidCert::keys instead. (You turn a Cert into a ValidCert by using Cert::with_policy.)

By necessity, this function erases the returned keys’ roles. If you are only interested in the primary key, use Cert::primary_key. If you are only interested in the subkeys, use KeyAmalgamationIter::subkeys. These functions preserve the keys’ role in the type system.

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
println!("{}'s has {} keys.",
         cert.fingerprint(),
         cert.keys().count());
source

pub fn unknowns(&self) -> UnknownComponentAmalgamationIter<'_>

Returns an iterator over the certificate’s unknown components.

This function returns all unknown components even those without a binding signature.

§Examples
println!("{}'s has {} unknown components.",
         cert.fingerprint(),
         cert.unknowns().count());
for ua in cert.unknowns() {
    println!("  Unknown component with tag {} ({}), error: {}",
             ua.tag(), u8::from(ua.tag()), ua.error());
}
source

pub fn bad_signatures(&self) -> impl Iterator<Item = &Signature> + Send + Sync

Returns the bad signatures.

Bad signatures are signatures and revocations that we could not associate with one of the certificate’s components.

For self signatures and self revocations, we check that the signature is correct. For third-party signatures and third-party revocations, we only check that the digest prefix is correct, because third-party keys are not available. Checking the digest prefix is not an integrity check; third party-signatures and third-party revocations may be invalid and must still be checked for validity before use.

§Examples
println!("{}'s has {} bad signatures.",
         cert.fingerprint(),
         cert.bad_signatures().count());
source

pub fn revocation_keys<'a>( &'a self, policy: &dyn Policy, ) -> Box<dyn 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.

§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(None, Some("alice@example.org"))
    .generate()?;
// Make Alice a designated revoker for Bob.
let (bob, _) =
    CertBuilder::general_purpose(None, 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.revocation_keys(p).collect::<Vec<&RevocationKey>>(),
           vec![&(&alice).into()]);
source

pub fn into_packets(self) -> impl Iterator<Item = Packet> + Send + Sync

👎Deprecated since 1.18.0: Use Cert::into_packets2() to strip secret key material or cert.into_tsk().into_packets() to serialize any secret key material

Converts the certificate into an iterator over a sequence of packets.

WARNING: When serializing a Cert, any secret key material is dropped. In order to serialize the secret key material, it is first necessary to convert the Cert into a TSK and serialize that. This behavior makes it harder to accidentally leak secret key material. This function is different. If a key contains secret key material, it is exported as a SecretKey or SecretSubkey, as appropriate. This means that if you serialize the resulting packets, the secret key material will be serialized too.

§Examples
println!("Cert contains {} packets",
         cert.into_packets().count());
source

pub fn into_packets2(self) -> impl Iterator<Item = Packet> + Send + Sync

Converts the certificate into an iterator over a sequence of packets.

This function strips secrets from the keys, similar to how serializing a Cert would not serialize secret keys. This behavior makes it harder to accidentally leak secret key material.

If you do want to preserve secret key material, use Cert::into_tsk to opt-in to getting the secret key material, then use TSK::into_packets to convert to a packet stream.

§Examples
assert!(cert.is_tsk());
// But:
assert!(! Cert::from_packets(cert.into_packets2())?.is_tsk());
source

pub fn from_packets( p: impl Iterator<Item = Packet> + Send + Sync, ) -> Result<Self>

Returns the first certificate found in the sequence of packets.

If the sequence of packets does not start with a certificate (specifically, if it does not start with a primary key packet), then this fails.

If the sequence contains multiple certificates (i.e., it is a keyring), or the certificate is followed by an invalid packet this function will fail. To parse keyrings, use CertParser instead of this function.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::packet::prelude::*;
use openpgp::PacketPile;

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

// We should be able to turn a certificate into a PacketPile
// and back.
assert!(Cert::from_packets(cert.into_packets2()).is_ok());

// But a revocation certificate is not a certificate, so this
// will fail.
let p : Vec<Packet> = vec![rev.into()];
assert!(Cert::from_packets(p.into_iter()).is_err());
source

pub fn into_packet_pile(self) -> PacketPile

Converts the certificate into a PacketPile.

§Examples
let pp = cert.into_packet_pile();
source

pub fn key_handle(&self) -> KeyHandle

Returns the certificate’s fingerprint as a KeyHandle.

§Examples
println!("{}", cert.key_handle());

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

pub fn fingerprint(&self) -> Fingerprint

Returns the certificate’s fingerprint.

§Examples
println!("{}", cert.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
println!("{}", cert.keyid());
source

pub fn merge_public(self, other: Cert) -> Result<Self>

Merges other into self, ignoring secret key material in other.

If other is a different certificate, then an error is returned.

Merging two versions of a certificate is complicated, because there may be multiple variants of the same key or signature packet. It is possible to have multiple variants of a key packet if one contains secret key material, and the other does not, or if both contain secret key material that is protected in different ways, e.g., a different algorithm, or a different password. Multiple variants of a signature packet are possible when the unhashed subpacket areas differ.

This routine is different from Cert::insert_packets in the following ways:

  • Cert::merge_public strictly prefers keys in self to those in other. That is, if a primary key or subkey appears in both self and other, the version in self is kept. In contrast, Cert::insert_packets prefers the new variant.

  • If other contains a new subkey, Cert::merge_public merges it into the certificate, but strips any secret key material. In contrast, Cert::insert_packets preserves the secret key material.

  • If both self and other contain two variants of a signature (that is, a signature packet that is identical expect for the contents of the unhashed subpacket area), Cert::merge_public merges the two variants using Signature::merge, which combines the unhashed subpacket areas. Cert::insert_packets just takes the new signature packet.

This function is appropriate to merge certificate material from untrusted sources like keyservers, because it only adds data to the existing certificate, it never overwrites existing data, and it doesn’t import secret key material, which may have been manipulated by an attacker.

Cert::merge_public_and_secret is similar to this function, but merges in secret key material from other.

§Examples

Merge a certificate from an untrusted source:

// Merge the local version with the version from the keyserver.
let cert = local.merge_public(keyserver)?;

Secret key material in other is stripped, even if the variant of the packet in self doesn’t have secret key material:

use sequoia_openpgp as openpgp;
use openpgp::cert::CertBuilder;

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert!(cert.is_tsk());

let stripped = cert.clone().strip_secret_key_material();
assert!(! stripped.is_tsk());

// Merge `cert` into `stripped`.
let merged = stripped.merge_public(cert).expect("same certificate");
assert!(! merged.is_tsk());

Secret key material from self is preferred to secret key material from other:

use sequoia_openpgp as openpgp;
use openpgp::crypto::Password;
use openpgp::cert::prelude::*;
use openpgp::Packet;

let p0 = Password::from("old password");
let p1 = Password::from("new password");

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .set_password(Some(p0.clone()))
      .generate()?;
assert!(cert.is_tsk());

// Change the password for the primary key.
let pk = cert.primary_key().key().clone().parts_into_secret()?
    .decrypt_secret(&p0)?
    .encrypt_secret(&p1)?;
let other = Cert::try_from(vec![ Packet::from(pk) ])
    .expect("a primary key is a certificate");

// Merge `other` into `cert`.
let merged = cert.merge_public(other).expect("same certificate");

// `merged` has the secret key material from `cert`, which is
// password protected with `p0`, not `other`, which is password
// protected with `p1`.
assert!(merged.primary_key().key().clone().parts_into_secret()?
        .decrypt_secret(&p0).is_ok());

The unhashed subpacket areas of two variants of a signature are merged:

use sequoia_openpgp as openpgp;
use openpgp::Packet;
use openpgp::cert::prelude::*;
use openpgp::packet::signature::subpacket::Subpacket;
use openpgp::packet::signature::subpacket::SubpacketTag;
use openpgp::packet::signature::subpacket::SubpacketValue;

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert!(cert.is_tsk());

// Add a subpacket to the unhashed subpacket area.
let subpacket_a = Subpacket::new(
    SubpacketValue::Unknown {
        tag: SubpacketTag::Private(100),
        body: Vec::new(),
    },
    false).expect("valid");
let subpacket_b = Subpacket::new(
    SubpacketValue::Unknown {
        tag: SubpacketTag::Private(101),
        body: Vec::new(),
    },
    false).expect("valid");

let mut cert_a = cert.clone().into_packets2().collect::<Vec<Packet>>();
match cert_a[1] {
    Packet::Signature(ref mut sig) => {
        let unhashed_area = sig.unhashed_area_mut();
        assert!(unhashed_area.subpacket(subpacket_a.tag()).is_none());
        assert!(unhashed_area.subpacket(subpacket_b.tag()).is_none());
        unhashed_area.add(subpacket_a.clone());
    }
    _ => panic!("Second packet is the direct signature packet."),
};
let cert_a = Cert::try_from(cert_a).expect("valid");

let mut cert_b = cert.clone().into_packets2().collect::<Vec<Packet>>();
match cert_b[1] {
    Packet::Signature(ref mut sig) => {
        let unhashed_area = sig.unhashed_area_mut();
        assert!(unhashed_area.subpacket(subpacket_a.tag()).is_none());
        assert!(unhashed_area.subpacket(subpacket_b.tag()).is_none());
        unhashed_area.add(subpacket_b.clone());
    }
    _ => panic!("Second packet is the direct signature packet."),
};
let cert_b = Cert::try_from(cert_b).expect("valid");

// When we merge `cert_b` into `cert_a`, the signature packets
// are merged:
let merged = cert_a.clone().merge_public(cert_b.clone())
    .expect("same certificate")
    .into_packets2()
    .collect::<Vec<Packet>>();
match merged[1] {
    Packet::Signature(ref sig) => {
        let unhashed_area = sig.unhashed_area();
        assert!(unhashed_area.subpacket(subpacket_a.tag()).is_some());
        assert!(unhashed_area.subpacket(subpacket_b.tag()).is_some());
    }
    _ => panic!("Second packet is the direct signature packet."),
};

// Likewise, when we merge `cert_a` into `cert_b`, the signature
// packets are merged:
let merged = cert_b.clone().merge_public(cert_a.clone())
    .expect("same certificate")
    .into_packets2()
    .collect::<Vec<Packet>>();
match merged[1] {
    Packet::Signature(ref sig) => {
        let unhashed_area = sig.unhashed_area();
        assert!(unhashed_area.subpacket(subpacket_a.tag()).is_some());
        assert!(unhashed_area.subpacket(subpacket_b.tag()).is_some());
    }
    _ => panic!("Second packet is the direct signature packet."),
};
source

pub fn merge_public_and_secret(self, other: Cert) -> Result<Self>

Merges other into self, including secret key material.

If other is a different certificate, then an error is returned.

This function is like Cert::merge_public except:

  • if two variants of the same key have secret key material, then the version in other is preferred,

  • if there are two variants of the same key, and one has secret key material, that variant is preferred.

This is different from Cert::insert_packets, which unconditionally prefers keys in the packets that are being merged into the certificate.

It is important to only merge key material from trusted sources using this function, because it may be used to import secret key material. Secret key material is not authenticated by OpenPGP, and there are plausible attack scenarios where a malicious actor injects secret key material.

To merge only public key material, which is always safe, use Cert::merge_public.

§Examples

Merge a certificate from a trusted source:

// Merge the local version with the version from your other device.
let cert = local.merge_public_and_secret(other_device)?;

Secret key material is preferred to no secret key material:

use sequoia_openpgp as openpgp;
use openpgp::cert::CertBuilder;

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert!(cert.is_tsk());

let stripped = cert.clone().strip_secret_key_material();
assert!(! stripped.is_tsk());

// If we merge `cert` into `stripped`, the secret key material is
// preserved:
let merged = stripped.clone().merge_public_and_secret(cert.clone())
    .expect("same certificate");
assert!(merged.is_tsk());

// Likewise if we merge `stripped` into `cert`:
let merged = cert.merge_public_and_secret(stripped)
    .expect("same certificate");
assert!(merged.is_tsk());

Secret key material in other is preferred:

use sequoia_openpgp as openpgp;
use openpgp::crypto::Password;
use openpgp::cert::prelude::*;
use openpgp::Packet;

let p0 = Password::from("old password");
let p1 = Password::from("new password");

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .set_password(Some(p0.clone()))
      .generate()?;
assert!(cert.is_tsk());

// Change the password for the primary key.
let pk = cert.primary_key().key().clone().parts_into_secret()?
    .decrypt_secret(&p0)?
    .encrypt_secret(&p1)?;
let other = Cert::try_from(vec![ Packet::from(pk) ])
    .expect("a primary key is a certificate");

// Merge `other` into `cert`.
let merged = cert.merge_public_and_secret(other).expect("same certificate");

// `merged` has the secret key material from `other`, which is
// password protected with `p1`, not `self`, which is password
// protected with `p0`.
assert!(merged.primary_key().key().clone().parts_into_secret()?
        .decrypt_secret(&p1).is_ok());

The unhashed subpacket areas of two variants of a signature are merged:

use sequoia_openpgp as openpgp;
use openpgp::Packet;
use openpgp::cert::prelude::*;
use openpgp::packet::signature::subpacket::Subpacket;
use openpgp::packet::signature::subpacket::SubpacketTag;
use openpgp::packet::signature::subpacket::SubpacketValue;

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert!(cert.is_tsk());

// Add a subpacket to the unhashed subpacket area.
let subpacket_a = Subpacket::new(
    SubpacketValue::Unknown {
        tag: SubpacketTag::Private(100),
        body: Vec::new(),
    },
    false).expect("valid");
let subpacket_b = Subpacket::new(
    SubpacketValue::Unknown {
        tag: SubpacketTag::Private(101),
        body: Vec::new(),
    },
    false).expect("valid");

let mut cert_a = cert.clone().into_packets2().collect::<Vec<Packet>>();
match cert_a[1] {
    Packet::Signature(ref mut sig) => {
        let unhashed_area = sig.unhashed_area_mut();
        assert!(unhashed_area.subpacket(subpacket_a.tag()).is_none());
        assert!(unhashed_area.subpacket(subpacket_b.tag()).is_none());
        unhashed_area.add(subpacket_a.clone());
    }
    _ => panic!("Second packet is the direct signature packet."),
};
let cert_a = Cert::try_from(cert_a).expect("valid");

let mut cert_b = cert.clone().into_packets2().collect::<Vec<Packet>>();
match cert_b[1] {
    Packet::Signature(ref mut sig) => {
        let unhashed_area = sig.unhashed_area_mut();
        assert!(unhashed_area.subpacket(subpacket_a.tag()).is_none());
        assert!(unhashed_area.subpacket(subpacket_b.tag()).is_none());
        unhashed_area.add(subpacket_b.clone());
    }
    _ => panic!("Second packet is the direct signature packet."),
};
let cert_b = Cert::try_from(cert_b).expect("valid");

// When we merge `cert_b` into `cert_a`, the signature packets
// are merged:
let merged = cert_a.clone().merge_public_and_secret(cert_b.clone())
    .expect("same certificate")
    .into_packets2()
    .collect::<Vec<Packet>>();
match merged[1] {
    Packet::Signature(ref sig) => {
        let unhashed_area = sig.unhashed_area();
        assert!(unhashed_area.subpacket(subpacket_a.tag()).is_some());
        assert!(unhashed_area.subpacket(subpacket_b.tag()).is_some());
    }
    _ => panic!("Second packet is the direct signature packet."),
};

// Likewise, when we merge `cert_a` into `cert_b`, the signature
// packets are merged:
let merged = cert_b.clone().merge_public_and_secret(cert_a.clone())
    .expect("same certificate")
    .into_packets2()
    .collect::<Vec<Packet>>();
match merged[1] {
    Packet::Signature(ref sig) => {
        let unhashed_area = sig.unhashed_area();
        assert!(unhashed_area.subpacket(subpacket_a.tag()).is_some());
        assert!(unhashed_area.subpacket(subpacket_b.tag()).is_some());
    }
    _ => panic!("Second packet is the direct signature packet."),
};
source

pub fn insert_packets2<I>(self, packets: I) -> Result<(Self, bool)>
where I: IntoIterator, I::Item: Into<Packet>,

Adds packets to the certificate.

This function turns the certificate into a sequence of packets, appends the packets to the end of it, and canonicalizes the result. Known packets that don’t belong in a TPK or TSK cause this function to return an error. Unknown packets are retained and added to the list of unknown components. The goal is to provide some future compatibility.

If a key is merged that already exists in the certificate, it replaces the existing key. This way, secret key material can be added, removed, encrypted, or decrypted.

Similarly, if a signature is merged that already exists in the certificate, it replaces the existing signature. This way, the unhashed subpacket area can be updated.

On success, this function returns the certificate with the packets merged in, and a boolean indicating whether the certificate actually changed. Changed here means that at least one new packet was added, or an existing packet was updated. Alternatively, changed means that the serialized form has changed.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::packet::prelude::*;
use openpgp::serialize::Serialize;
use openpgp::parse::Parse;
use openpgp::types::DataFormat;

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert!(cert.is_tsk());


// Merging in the certificate doesn't change it.
let identical_cert = cert.clone();
let (cert, changed) =
    cert.insert_packets2(identical_cert.into_tsk().into_packets())?;
assert!(! changed);


// Merge in the revocation certificate.
assert_eq!(cert.primary_key().self_revocations().count(), 0);
let (cert, changed) = cert.insert_packets2(rev)?;
assert!(changed);
assert_eq!(cert.primary_key().self_revocations().count(), 1);


// Add an unknown packet.
let tag = Tag::Private(61.into());
let unknown = Unknown::new(tag,
    openpgp::Error::UnsupportedPacketType(tag).into());

// It shows up as an unknown component.
let (cert, changed) = cert.insert_packets2(unknown)?;
assert!(changed);
assert_eq!(cert.unknowns().count(), 1);
for p in cert.unknowns() {
    assert_eq!(p.tag(), tag);
}


// Try and merge a literal data packet.
let mut lit = Literal::new(DataFormat::Text);
lit.set_body(b"test".to_vec());

// Merging packets that are known to not belong to a
// certificate result in an error.
assert!(cert.insert_packets(lit).is_err());

Remove secret key material:

use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::packet::prelude::*;

// Create a new key.
let (cert, _) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert!(cert.is_tsk());

// We just created the key, so all of the keys have secret key
// material.
let mut pk = cert.primary_key().key().clone();

// Split off the secret key material.
let (pk, sk) = pk.take_secret();
assert!(sk.is_some());
assert!(! pk.has_secret());

// Merge in the public key.  Recall: the packets that are
// being merged into the certificate take precedence.
let (cert, changed) = cert.insert_packets2(pk)?;
assert!(changed);

// The secret key material is stripped.
assert!(! cert.primary_key().has_secret());

Update a binding signature’s unhashed subpacket area:

use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::packet::prelude::*;
use openpgp::packet::signature::subpacket::*;

// Create a new key.
let (cert, _) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert_eq!(cert.userids().nth(0).unwrap().self_signatures().count(), 1);

// Grab the binding signature so that we can modify it.
let mut sig =
    cert.userids().nth(0).unwrap().self_signatures().nth(0)
    .unwrap().clone();

// Add a notation subpacket.  Note that the information is not
// authenticated, therefore it may only be trusted if the
// certificate with the signature is placed in a trusted store.
let notation = NotationData::new("retrieved-from@example.org",
                                 "generated-locally",
                                 NotationDataFlags::empty()
                                     .set_human_readable());
sig.unhashed_area_mut().add(
    Subpacket::new(SubpacketValue::NotationData(notation), false)?)?;

// Merge in the signature.  Recall: the packets that are
// being merged into the certificate take precedence.
let (cert, changed) = cert.insert_packets2(sig)?;
assert!(changed);

// The old binding signature is replaced.
assert_eq!(cert.userids().nth(0).unwrap().self_signatures().count(), 1);
assert_eq!(cert.userids().nth(0).unwrap().self_signatures().nth(0)
               .unwrap()
               .unhashed_area()
               .subpackets(SubpacketTag::NotationData).count(), 1);
source

pub fn insert_packets_merge<P, I>( self, packets: P, merge: I, ) -> Result<(Self, bool)>

Adds packets to the certificate with an explicit merge policy.

Like Cert::insert_packets2, but also takes a function that will be called on inserts and replacements that can be used to log changes to the certificate, and to influence how packets are merged. The merge function takes two parameters, an optional existing packet, and the packet to be merged in.

If a new packet is inserted, there is no packet currently in the certificate. Hence, the first parameter to the merge function is None.

If an existing packet is updated, there is a packet currently in the certificate that matches the given packet. Hence, the first parameter to the merge function is Some(existing_packet).

Both packets given to the merge function are considered equal when considering the normalized form (only comparing public key parameters and ignoring unhashed signature subpackets, see Packet::normalized_hash). It must return a packet that equals the input packet. In practice that means that the merge function returns either the old packet, the new packet, or a combination of both packets. If the merge function returns a different packet, this function returns Error::InvalidOperation.

If the merge function returns the existing packet, this function will still consider this as a change to the certificate. In other words, it may return that the certificate has changed even if the serialized representation has not changed.

§Examples

In the first example, we give an explicit merge function that just returns the new packet. This policy prefers the new packet. This is the policy used by Cert::insert_packets2.

use sequoia_openpgp as openpgp;
use openpgp::crypto::Password;
use openpgp::cert::prelude::CertBuilder;

let p0 = Password::from("old password");
let p1 = Password::from("new password");

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .set_password(Some(p0.clone()))
      .generate()?;
assert!(cert.is_tsk());

// Change the password for the primary key.
let pk = cert.primary_key().key().clone().parts_into_secret()?
    .decrypt_secret(&p0)?
    .encrypt_secret(&p1)?;

// Merge it back in, with a policy projecting to the new packet.
let (cert, changed) =
    cert.insert_packets_merge(pk, |_old, new| Ok(new))?;
assert!(changed);

// Make sure we can still decrypt the primary key using the
// new password.
assert!(cert.primary_key().key().clone().parts_into_secret()?
        .decrypt_secret(&p1).is_ok());

In the second example, we give an explicit merge function that returns the old packet if given, falling back to the new packet, if not. This policy prefers the existing packets.

use sequoia_openpgp as openpgp;
use openpgp::crypto::Password;
use openpgp::cert::prelude::CertBuilder;

let p0 = Password::from("old password");
let p1 = Password::from("new password");

// Create a new key.
let (cert, rev) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .set_password(Some(p0.clone()))
      .generate()?;
assert!(cert.is_tsk());

// Change the password for the primary key.
let pk = cert.primary_key().key().clone().parts_into_secret()?
    .decrypt_secret(&p0)?
    .encrypt_secret(&p1)?;

// Merge it back in, with a policy preferring the old packet.
let (cert, changed) =
    cert.insert_packets_merge(pk, |old, new| Ok(old.unwrap_or(new)))?;
assert!(changed); // Overestimates changes.

// Make sure we can still decrypt the primary key using the
// old password.
assert!(cert.primary_key().key().clone().parts_into_secret()?
        .decrypt_secret(&p0).is_ok());
source

pub fn insert_packets<I>(self, packets: I) -> Result<Self>
where I: IntoIterator, I::Item: Into<Packet>,

Adds packets to the certificate.

Like Cert::insert_packets2, but does not return whether the certificate changed.

source

pub fn is_tsk(&self) -> bool

Returns whether at least one of the keys includes secret key material.

This returns true if either the primary key or at least one of the subkeys includes secret key material.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::policy::StandardPolicy;
use openpgp::serialize::Serialize;
use openpgp::parse::Parse;

let p = &StandardPolicy::new();

// Create a new key.
let (cert, _) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert!(cert.is_tsk());

// If we serialize the certificate, the secret key material is
// stripped, unless we first convert it to a TSK.

let mut buffer = Vec::new();
cert.as_tsk().serialize(&mut buffer);
let cert = Cert::from_bytes(&buffer)?;
assert!(cert.is_tsk());

// Now round trip it without first converting it to a TSK.  This
// drops the secret key material.
let mut buffer = Vec::new();
cert.serialize(&mut buffer);
let cert = Cert::from_bytes(&buffer)?;
assert!(!cert.is_tsk());
source

pub fn strip_secret_key_material(self) -> Cert

Strips any secret key material.

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


// Create a new key.
let (cert, _) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .generate()?;
assert!(cert.is_tsk());

let cert = cert.strip_secret_key_material();
assert!(! cert.is_tsk());
source

pub fn retain_userids<P>(self, predicate: P) -> Cert
where P: FnMut(UserIDAmalgamation<'_>) -> bool,

Retains only the userids specified by the predicate.

Removes all the userids for which the given predicate returns false.

§Warning

Because userid binding signatures are traditionally used to provide additional information like the certificate holder’s algorithm preferences (see Preferences) and primary key flags (see ValidKeyAmalgamation::key_flags). Removing a userid may inadvertently change this information.

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

// Create a new key.
let (cert, _) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      .add_userid("Alice Lovelace <alice@lovelace.name>")
      .generate()?;
assert_eq!(cert.userids().count(), 2);

let cert = cert.retain_userids(|ua| {
    if let Ok(Some(address)) = ua.email() {
        address == "alice@example.org" // Only keep this one.
    } else {
        false                          // Drop malformed userids.
    }
});
assert_eq!(cert.userids().count(), 1);
assert_eq!(cert.userids().nth(0).unwrap().email()?.unwrap(),
           "alice@example.org");
source

pub fn retain_user_attributes<P>(self, predicate: P) -> Cert

Retains only the user attributes specified by the predicate.

Removes all the user attributes for which the given predicate returns false.

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

// Create a new key.
let (cert, _) =
      CertBuilder::general_purpose(None, Some("alice@example.org"))
      // Add nonsensical user attribute.
      .add_user_attribute(vec![0, 1, 2])
      .generate()?;
assert_eq!(cert.user_attributes().count(), 1);

// Strip all user attributes
let cert = cert.retain_user_attributes(|_| false);
assert_eq!(cert.user_attributes().count(), 0);
source

pub fn retain_subkeys<P>(self, predicate: P) -> Cert

Retains only the subkeys specified by the predicate.

Removes all the subkeys for which the given predicate returns false.

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

// Create a new key.
let (cert, _) =
      CertBuilder::new()
      .add_userid("Alice Lovelace <alice@lovelace.name>")
      .add_transport_encryption_subkey()
      .add_storage_encryption_subkey()
      .generate()?;
assert_eq!(cert.keys().subkeys().count(), 2);

// Retain only the transport encryption subkey.  For that, we
// need to examine the key flags, therefore we need to turn
// the `KeyAmalgamation` into a `ValidKeyAmalgamation` under a
// policy.
let p = &StandardPolicy::new();
let cert = cert.retain_subkeys(|ka| {
    if let Ok(vka) = ka.with_policy(p, None) {
        vka.key_flags().map(|flags| flags.for_transport_encryption())
            .unwrap_or(false)      // Keep transport encryption keys.
    } else {
        false                      // Drop unbound keys.
    }
});
assert_eq!(cert.keys().subkeys().count(), 1);
assert!(cert.with_policy(p, None)?.keys().subkeys().nth(0).unwrap()
            .key_flags().unwrap().for_transport_encryption());
source

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

Associates a policy and a reference time with the certificate.

This is used to turn a Cert into a ValidCert. (See also ValidateAmalgamation, which does the same for component amalgamations.)

A certificate is considered valid if:

  • It has a self signature that is live at time t.

  • The policy considers it acceptable.

This doesn’t say anything about whether the certificate itself is alive (see ValidCert::alive) or revoked (see ValidCert::revocation_status).

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

let p = &StandardPolicy::new();

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

impl Cert

source

pub fn exportable(&self) -> bool

Returns whether the certificate should be exported.

A certificate should only be exported if it has at least one exportable direct key signature, or there is at least one user ID with at least one exportable self signature.

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

// By default, certificates are exportable.
let (cert, _) =
    CertBuilder::general_purpose(None, Some("alice@example.org"))
        .generate()?;
assert!(cert.exportable());

// Setting the exportable flag to false makes them
// not-exportable.
let (cert, _) =
    CertBuilder::general_purpose(None, Some("alice@example.org"))
        .set_exportable(false)
        .generate()?;
assert!(! cert.exportable());
source§

impl Cert

source

pub fn as_tsk(&self) -> TSK<'_>

Derive a TSK object from this key.

This object writes out secret keys during serialization.

source

pub fn into_tsk(self) -> TSK<'static>

Derive a TSK object from this key that owns the Cert.

This object writes out secret keys during serialization.

source§

impl Cert

source

pub fn armor_headers(&self) -> Vec<String>

Creates descriptive armor headers.

Returns armor headers that describe this Cert. The Cert’s primary fingerprint and valid userids (according to the default policy) are included as comments, so that it is easier to identify the Cert when looking at the armored data.

source

pub fn armored(&self) -> impl Serialize + SerializeInto + '_

Wraps this Cert in an armor structure when serialized.

Derives an object from this Cert that adds an armor structure to the serialized Cert when it is serialized. Additionally, the Cert’s User IDs are added as comments, so that it is easier to identify the Cert when looking at the armored data.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::serialize::SerializeInto;

let (cert, _) =
    CertBuilder::general_purpose(None, Some("Mr. Pink ☮☮☮"))
    .generate()?;
let armored = String::from_utf8(cert.armored().to_vec()?)?;

assert!(armored.starts_with("-----BEGIN PGP PUBLIC KEY BLOCK-----"));
assert!(armored.contains("Mr. Pink ☮☮☮"));

Trait Implementations§

source§

impl Clone for Cert

source§

fn clone(&self) -> Cert

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 Debug for Cert

source§

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

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

impl Display for Cert

source§

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

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

impl From<&Cert> for RevocationKey

source§

fn from(cert: &Cert) -> Self

Converts to this type from the input type.
source§

impl From<Cert> for PacketPile

source§

fn from(cert: Cert) -> PacketPile

Converts the Cert into a PacketPile.

If any packets include secret key material, that secret key material is included in the resulting PacketPile. In contrast, when serializing a Cert, or converting a cert to packets with Cert::into_packets2, the secret key material not included.

Note: This will change in sequoia-openpgp version 2, which will harmonize the behavior and not include secret key material.

source§

impl From<Cert> for TSK<'_>

source§

fn from(c: Cert) -> Self

Converts to this type from the input type.
source§

impl From<Cert> for Vec<Packet>

source§

fn from(cert: Cert) -> Self

Converts the Cert into a Vec<Packet>.

If any packets include secret key material, that secret key material is included in the resulting Vec<Packet>. In contrast, when serializing a Cert, or converting a cert to packets with Cert::into_packets2, the secret key material not included.

Note: This will change in sequoia-openpgp version 2, which will harmonize the behavior and not include secret key material.

source§

impl FromStr for Cert

source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses and returns a certificate.

s must return an OpenPGP-encoded certificate.

If s contains multiple certificates, this returns an error. Use CertParser if you want to parse a keyring.

§

type Err = Error

The associated error which can be returned from parsing.
source§

impl IntoIterator for Cert

source§

fn into_iter(self) -> Self::IntoIter

Converts the Cert into an iterator over Packets.

If any packets include secret key material, that secret key material is included in the resulting iterator. In contrast, when serializing a Cert, or converting a cert to packets with Cert::into_packets2, the secret key material not included.

Note: This will change in sequoia-openpgp version 2, which will harmonize the behavior and not include secret key material.

§

type Item = Packet

The type of the elements being iterated over.
§

type IntoIter = IntoIter

Which kind of iterator are we turning this into?
source§

impl Marshal for Cert

source§

fn serialize(&self, o: &mut dyn Write) -> Result<()>

Writes a serialized version of the object to o.
source§

fn export(&self, o: &mut dyn Write) -> Result<()>

Exports a serialized version of the object to o. Read more
source§

impl MarshalInto for Cert

source§

fn serialized_len(&self) -> usize

Computes the maximal length of the serialized representation. Read more
source§

fn serialize_into(&self, buf: &mut [u8]) -> Result<usize>

Serializes into the given buffer. Read more
source§

fn export_into(&self, buf: &mut [u8]) -> Result<usize>

Exports into the given buffer. Read more
source§

fn to_vec(&self) -> Result<Vec<u8>>

Serializes the packet to a vector.
source§

fn export_to_vec(&self) -> Result<Vec<u8>>

Exports to a vector. Read more
source§

impl<'a> Parse<'a, Cert> for Cert

source§

fn from_buffered_reader<R>(reader: R) -> Result<Cert>
where R: BufferedReader<Cookie> + 'a,

Parses and returns a certificate.

The reader must return an OpenPGP-encoded certificate.

If reader contains multiple certificates, this returns an error. Use CertParser if you want to parse a keyring.

source§

fn from_reader<R: Read + Send + Sync>(reader: R) -> Result<Self>

Parses and returns a certificate.

The reader must return an OpenPGP-encoded certificate.

If reader contains multiple certificates, this returns an error. Use CertParser if you want to parse a keyring.

source§

fn from_file<P: AsRef<Path>>(path: P) -> Result<Self>

Parses and returns a certificate.

The file must contain an OpenPGP-encoded certificate.

If the file contains multiple certificates, this returns an error. Use CertParser if you want to parse a keyring.

source§

fn from_bytes<D: AsRef<[u8]> + ?Sized + Send + Sync>( data: &'a D, ) -> Result<Self>

Parses and returns a certificate.

buf must contain an OpenPGP-encoded certificate.

If buf contains multiple certificates, this returns an error. Use CertParser if you want to parse a keyring.

source§

impl PartialEq for Cert

source§

fn eq(&self, other: &Cert) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Serialize for Cert

source§

fn serialize(&self, o: &mut dyn Write) -> Result<()>

Writes a serialized version of the object to o.
source§

fn export(&self, o: &mut dyn Write) -> Result<()>

Exports a serialized version of the object to o. Read more
source§

impl SerializeInto for Cert

source§

fn serialized_len(&self) -> usize

Computes the maximal length of the serialized representation. Read more
source§

fn serialize_into(&self, buf: &mut [u8]) -> Result<usize>

Serializes into the given buffer. Read more
source§

fn to_vec(&self) -> Result<Vec<u8>>

Serializes the packet to a vector.
source§

fn export_into(&self, buf: &mut [u8]) -> Result<usize>

Exports into the given buffer. Read more
source§

fn export_to_vec(&self) -> Result<Vec<u8>>

Exports to a vector. Read more
source§

impl<'a> TryFrom<&RawCert<'a>> for Cert

§

type Error = Error

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

fn try_from(c: &RawCert<'_>) -> Result<Self>

Performs the conversion.
source§

impl TryFrom<Packet> for Cert

§

type Error = Error

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

fn try_from(p: Packet) -> Result<Self>

Performs the conversion.
source§

impl TryFrom<PacketParserResult<'_>> for Cert

source§

fn try_from(ppr: PacketParserResult<'_>) -> Result<Self>

Returns the Cert found in the packet stream.

If the sequence contains multiple certificates (i.e., it is a keyring), or the certificate is followed by an invalid packet this function will fail. To parse keyrings, use CertParser instead of this function.

§

type Error = Error

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

impl TryFrom<PacketPile> for Cert

source§

fn try_from(p: PacketPile) -> Result<Self>

Returns the certificate found in the PacketPile.

If the PacketPile does not start with a certificate (specifically, if it does not start with a primary key packet), then this fails.

If the sequence contains multiple certificates (i.e., it is a keyring), or the certificate is followed by an invalid packet this function will fail. To parse keyrings, use CertParser instead of this function.

§Examples
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::packet::prelude::*;
use openpgp::PacketPile;
use std::convert::TryFrom;

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

// We should be able to turn a certificate into a PacketPile
// and back.
let pp : PacketPile = cert.into();
assert!(Cert::try_from(pp).is_ok());

// But a revocation certificate is not a certificate, so this
// will fail.
let pp : PacketPile = Packet::from(rev).into();
assert!(Cert::try_from(pp).is_err());
§

type Error = Error

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

impl<'a> TryFrom<RawCert<'a>> for Cert

§

type Error = Error

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

fn try_from(c: RawCert<'_>) -> Result<Self>

Performs the conversion.
source§

impl TryFrom<Vec<Packet>> for Cert

§

type Error = Error

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

fn try_from(p: Vec<Packet>) -> Result<Self>

Performs the conversion.
source§

impl StructuralPartialEq for Cert

Auto Trait Implementations§

§

impl !Freeze for Cert

§

impl RefUnwindSafe for Cert

§

impl Send for Cert

§

impl Sync for Cert

§

impl Unpin for Cert

§

impl UnwindSafe for Cert

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§

default unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. 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

§

type Output = T

Should always be Self
source§

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

§

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§

default 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>,

§

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>,

§

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