summaryrefslogtreecommitdiffstats
path: root/openpgp
diff options
context:
space:
mode:
authorWiktor Kwapisiewicz <wiktor@metacode.biz>2020-05-06 14:38:33 +0200
committerWiktor Kwapisiewicz <wiktor@metacode.biz>2020-06-01 15:30:15 +0200
commitebb719dcc6c0a719cab77f4fb7e296e8efe85f13 (patch)
tree959664d259f3d57396086c8c78907297130e983e /openpgp
parent09f30c446541acee77f18d365cbdbb970dd82543 (diff)
openpgp: Add doctests to types module.
- Fixes #475.
Diffstat (limited to 'openpgp')
-rw-r--r--openpgp/src/cert/builder.rs2
-rw-r--r--openpgp/src/types/compression_level.rs36
-rw-r--r--openpgp/src/types/features.rs34
-rw-r--r--openpgp/src/types/key_flags.rs33
-rw-r--r--openpgp/src/types/mod.rs453
-rw-r--r--openpgp/src/types/revocation_key.rs42
-rw-r--r--openpgp/src/types/server_preferences.rs34
-rw-r--r--openpgp/src/types/timestamp.rs74
8 files changed, 703 insertions, 5 deletions
diff --git a/openpgp/src/cert/builder.rs b/openpgp/src/cert/builder.rs
index 0c58548f..751abb55 100644
--- a/openpgp/src/cert/builder.rs
+++ b/openpgp/src/cert/builder.rs
@@ -398,7 +398,7 @@ impl CertBuilder {
/// assert_eq!(userids[1].userid(),
/// &UserID::from("Alice Lovelace <alice@lovelace.name>"));
///
- ///
+ ///
/// assert_eq!(userids[0].binding_signature().primary_userid().unwrap_or(false), true);
/// assert_eq!(userids[1].binding_signature().primary_userid().unwrap_or(false), false);
/// # Ok(())
diff --git a/openpgp/src/types/compression_level.rs b/openpgp/src/types/compression_level.rs
index 7ac32d31..f7ab0b62 100644
--- a/openpgp/src/types/compression_level.rs
+++ b/openpgp/src/types/compression_level.rs
@@ -12,6 +12,42 @@ use crate::{
/// compression libraries, `0` to `9`, where `0` means no compression,
/// `1` means fastest compression, `6` being a good default, and
/// meaning `9` best compression.
+///
+/// Note that compression is [dangerous when used naively]. To mitigate some of
+/// these issues messages should [use padding].
+///
+/// [dangerous when used naively]: https://mailarchive.ietf.org/arch/msg/openpgp/2FQUVt6Dw8XAsaMELyo5BNlh2pM
+/// [use padding]: ../serialize/stream/padding/index.html
+///
+/// # Examples
+///
+/// Write a message using the given [CompressionAlgorithm]:
+///
+/// [CompressionAlgorithm]: enum.CompressionAlgorithm.html
+///
+/// ```
+/// use sequoia_openpgp as openpgp;
+/// # fn main() -> openpgp::Result<()> {
+/// use std::io::Write;
+/// use openpgp::serialize::stream::{Message, Compressor, LiteralWriter};
+/// use openpgp::serialize::stream::padding::{Padder, padme};
+/// use openpgp::types::{CompressionAlgorithm, CompressionLevel};
+///
+/// let mut sink = Vec::new();
+/// let message = Message::new(&mut sink);
+/// let message = Compressor::new(message)
+/// .algo(CompressionAlgorithm::Zlib)
+/// # .algo(CompressionAlgorithm::Uncompressed)
+/// .level(CompressionLevel::fastest())
+/// .build()?;
+///
+/// let message = Padder::new(message, padme)?;
+///
+/// let mut message = LiteralWriter::new(message).build()?;
+/// message.write_all(b"Hello world.")?;
+/// message.finalize()?;
+/// # Ok(()) }
+/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CompressionLevel(u8);
diff --git a/openpgp/src/types/features.rs b/openpgp/src/types/features.rs
index 984b05db..892cc308 100644
--- a/openpgp/src/types/features.rs
+++ b/openpgp/src/types/features.rs
@@ -4,10 +4,44 @@ use quickcheck::{Arbitrary, Gen};
/// Describes features supported by an OpenPGP implementation.
///
+/// The features are defined in [Section 5.2.3.24 of RFC 4880], and
+/// [Section 5.2.3.25 of RFC 4880bis].
+///
+/// [Section 5.2.3.24 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.24
+/// [Section 5.2.3.25 of RFC 4880bis]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-09#section-5.2.3.25
+///
/// # A note on equality
///
/// `PartialEq` is implements semantic equality, i.e. it ignores
/// padding.
+///
+/// # Examples
+///
+/// ```
+/// use sequoia_openpgp as openpgp;
+/// # use openpgp::Result;
+/// use openpgp::cert::prelude::*;
+/// use openpgp::policy::StandardPolicy;
+///
+/// # fn main() -> Result<()> {
+/// let p = &StandardPolicy::new();
+///
+/// # let (cert, _) =
+/// # CertBuilder::general_purpose(None, Some("alice@example.org"))
+/// # .generate()?;
+/// match cert.with_policy(p, None)?.primary_userid()?.features() {
+/// Some(features) => {
+/// println!("Certificate holder's supported features:");
+/// assert!(features.supports_mdc());
+/// assert!(!features.supports_aead());
+/// }
+/// None => {
+/// println!("Certificate Holder did not specify any features.");
+/// # unreachable!();
+/// }
+/// }
+/// # Ok(()) }
+/// ```
#[derive(Clone)]
pub struct Features{
mdc: bool,
diff --git a/openpgp/src/types/key_flags.rs b/openpgp/src/types/key_flags.rs
index 9e7595eb..579d11da 100644
--- a/openpgp/src/types/key_flags.rs
+++ b/openpgp/src/types/key_flags.rs
@@ -4,13 +4,42 @@ use std::cmp;
use std::ops::{BitAnd, BitOr};
use quickcheck::{Arbitrary, Gen};
-/// Describes how a key may be used, and stores additional
-/// information.
+/// Describes how a key may be used, and stores additional information.
+///
+/// Key flags are described in [Section 5.2.3.21 of RFC 4880] and [Section 5.2.3.22
+/// of RFC 4880bis].
+///
+/// [Section 5.2.3.21 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.21
+/// [Section 5.2.3.22 of RFC 4880bis]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-09#section-5.2.3.22
///
/// # A note on equality
///
/// `PartialEq` is implements semantic equality, i.e. it ignores
/// padding.
+///
+/// # Examples
+///
+/// ```
+/// use sequoia_openpgp as openpgp;
+/// # use openpgp::Result;
+/// use openpgp::cert::prelude::*;
+/// use openpgp::policy::StandardPolicy;
+///
+/// # fn main() -> Result<()> {
+/// let p = &StandardPolicy::new();
+///
+/// let (cert, _) =
+/// CertBuilder::new()
+/// .add_userid("Alice <alice@example.com>")
+/// .add_transport_encryption_subkey()
+/// .generate()?;
+///
+/// for subkey in cert.with_policy(p, None)?.keys().subkeys() {
+/// // Key contains one Encryption subkey:
+/// assert!(subkey.key_flags().unwrap().for_transport_encryption());
+/// }
+/// # Ok(()) }
+/// ```
#[derive(Clone)]
pub struct KeyFlags{
for_certification: bool,
diff --git a/openpgp/src/types/mod.rs b/openpgp/src/types/mod.rs
index 7a8e075a..ddea9239 100644
--- a/openpgp/src/types/mod.rs
+++ b/openpgp/src/types/mod.rs
@@ -2,6 +2,48 @@
//!
//! This module provides types used in OpenPGP, like enumerations
//! describing algorithms.
+//!
+//! # Common Operations
+//!
+//! - *Rounding the creation time of signatures*: See the [`Timestamp::round_down`] method.
+//! - *Checking key usage flags*: See the [`KeyFlags`] data structure.
+//! - *Setting key validity ranges*: See the [`Timestamp`] and [`Duration`] data structures.
+//!
+//! # Data structures
+//!
+//! ## `CompressionLevel`
+//!
+//! Allows adjusting the amount of effort spent on compressing encoded data.
+//! This structure additionally has several helper methods for commonly used
+//! compression strategies.
+//!
+//! ## `Features`
+//!
+//! Describes particular features supported by the given OpenPGP implementation.
+//!
+//! ## `KeyFlags`
+//!
+//! Holds imformation about a key in particular how the given key can be used.
+//!
+//! ## `RevocationKey`
+//!
+//! Describes a key that has been designated to issue revocation signatures.
+//!
+//! # `ServerPreferences`
+//!
+//! Describes preferences regarding to key servers.
+//!
+//! ## `Timestamp` and `Duration`
+//!
+//! In OpenPGP time is represented as the number of seconds since the UNIX epoch stored
+//! as an `u32`. These two data structures allow manipulating OpenPGP time ensuring
+//! that adding or subtracting durations will never overflow or underflow without
+//! notice.
+//!
+//! [`Timestamp::round_down`]: struct.Timestamp.html#method.round_down
+//! [`KeyFlags`]: struct.KeyFlags.html
+//! [`Timestamp`]: struct.Timestamp.html
+//! [`Duration`]: struct.Duration.html
use std::fmt;
use std::str::FromStr;
@@ -41,6 +83,20 @@ pub(crate) fn bitfield_remove_padding(b: &mut Vec<u8>) -> usize {
/// The OpenPGP public key algorithms as defined in [Section 9.1 of
/// RFC 4880], and [Section 5 of RFC 6637].
///
+/// # Examples
+///
+/// ```rust
+/// use sequoia_openpgp as openpgp;
+/// use openpgp::cert::prelude::*;
+/// use openpgp::types::PublicKeyAlgorithm;
+///
+/// let (cert, _) = CertBuilder::new()
+/// .set_cipher_suite(CipherSuite::Cv25519)
+/// .generate().unwrap();
+///
+/// assert_eq!(cert.primary_key().pk_algo(), PublicKeyAlgorithm::EdDSA);
+/// ```
+///
/// [Section 9.1 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-9.1
/// [Section 5 of RFC 6637]: https://tools.ietf.org/html/rfc6637
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
@@ -82,6 +138,17 @@ pub enum PublicKeyAlgorithm {
impl PublicKeyAlgorithm {
/// Returns true if the algorithm can sign data.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::PublicKeyAlgorithm;
+ ///
+ /// assert!(PublicKeyAlgorithm::EdDSA.for_signing());
+ /// assert!(PublicKeyAlgorithm::RSAEncryptSign.for_signing());
+ /// assert!(!PublicKeyAlgorithm::ElGamalEncrypt.for_signing());
+ /// ```
pub fn for_signing(&self) -> bool {
use self::PublicKeyAlgorithm::*;
#[allow(deprecated)]
@@ -94,6 +161,17 @@ impl PublicKeyAlgorithm {
}
/// Returns true if the algorithm can encrypt data.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::PublicKeyAlgorithm;
+ ///
+ /// assert!(!PublicKeyAlgorithm::EdDSA.for_encryption());
+ /// assert!(PublicKeyAlgorithm::RSAEncryptSign.for_encryption());
+ /// assert!(PublicKeyAlgorithm::ElGamalEncrypt.for_encryption());
+ /// ```
pub fn for_encryption(&self) -> bool {
use self::PublicKeyAlgorithm::*;
#[allow(deprecated)]
@@ -106,6 +184,18 @@ impl PublicKeyAlgorithm {
}
/// Returns whether this algorithm is supported.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::PublicKeyAlgorithm;
+ ///
+ /// assert!(PublicKeyAlgorithm::EdDSA.is_supported());
+ /// assert!(PublicKeyAlgorithm::RSAEncryptSign.is_supported());
+ /// assert!(!PublicKeyAlgorithm::ElGamalEncrypt.is_supported());
+ /// assert!(!PublicKeyAlgorithm::Private(101).is_supported());
+ /// ```
pub fn is_supported(&self) -> bool {
use self::PublicKeyAlgorithm::*;
#[allow(deprecated)]
@@ -248,6 +338,18 @@ impl Curve {
/// only because some legacy PGP application like HKP need it.
///
/// Returns `None` for unknown curves.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::Curve;
+ ///
+ /// assert_eq!(Curve::NistP256.bits(), Some(256));
+ /// assert_eq!(Curve::NistP384.bits(), Some(384));
+ /// assert_eq!(Curve::Ed25519.bits(), Some(256));
+ /// assert_eq!(Curve::Unknown(Box::new([0x2B, 0x11])).bits(), None);
+ /// ```
pub fn bits(&self) -> Option<usize> {
use self::Curve::*;
@@ -299,6 +401,16 @@ const CV25519_OID: &[u8] =
impl Curve {
/// Parses the given OID.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::Curve;
+ ///
+ /// assert_eq!(Curve::from_oid(&[0x2B, 0x81, 0x04, 0x00, 0x22]), Curve::NistP384);
+ /// assert_eq!(Curve::from_oid(&[0x2B, 0x11]), Curve::Unknown(Box::new([0x2B, 0x11])));
+ /// ```
pub fn from_oid(oid: &[u8]) -> Curve {
// Match on OIDs, see section 11 of RFC6637.
match oid {
@@ -314,6 +426,16 @@ impl Curve {
}
/// Returns this curve's OID.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::Curve;
+ ///
+ /// assert_eq!(Curve::NistP384.oid(), &[0x2B, 0x81, 0x04, 0x00, 0x22]);
+ /// assert_eq!(Curve::Unknown(Box::new([0x2B, 0x11])).oid(), &[0x2B, 0x11]);
+ /// ```
pub fn oid(&self) -> &[u8] {
match self {
&Curve::NistP256 => NIST_P256_OID,
@@ -330,6 +452,18 @@ impl Curve {
/// Returns the length of a coordinate in bits.
///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::Curve;
+ ///
+ /// assert!(if let Ok(256) = Curve::NistP256.len() { true } else { false });
+ /// assert!(if let Ok(384) = Curve::NistP384.len() { true } else { false });
+ /// assert!(if let Ok(256) = Curve::Ed25519.len() { true } else { false });
+ /// assert!(if let Err(_) = Curve::Unknown(Box::new([0x2B, 0x11])).len() { true } else { false });
+ /// ```
+ ///
/// # Errors
///
/// Returns `Error::UnsupportedEllipticCurve` if the curve is not
@@ -351,6 +485,18 @@ impl Curve {
}
/// Returns whether this algorithm is supported.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::Curve;
+ ///
+ /// assert!(Curve::NistP256.is_supported());
+ /// assert!(Curve::NistP384.is_supported());
+ /// assert!(Curve::Ed25519.is_supported());
+ /// assert!(!Curve::Unknown(Box::new([0x2B, 0x11])).is_supported());
+ /// ```
pub fn is_supported(&self) -> bool {
use self::Curve::*;
match &self {
@@ -389,6 +535,24 @@ impl Arbitrary for Curve {
/// symbolic one.
///
/// [`SymmetricAlgorithm::from`]: https://doc.rust-lang.org/std/convert/trait.From.html
+///
+/// # Examples
+///
+/// Use `SymmetricAlgorithm` to set the preferred symmetric algorithms on a signature:
+///
+/// ```rust
+/// use sequoia_openpgp as openpgp;
+/// use openpgp::packet::signature::SignatureBuilder;
+/// use openpgp::types::{HashAlgorithm, SymmetricAlgorithm, SignatureType};
+///
+/// # fn main() -> openpgp::Result<()> {
+/// let mut builder = SignatureBuilder::new(SignatureType::DirectKey)
+/// .set_hash_algo(HashAlgorithm::SHA512)
+/// .set_preferred_symmetric_algorithms(vec![
+/// SymmetricAlgorithm::AES256,
+/// ])?;
+/// # Ok(()) }
+/// ```
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum SymmetricAlgorithm {
/// Null encryption.
@@ -433,6 +597,20 @@ impl Default for SymmetricAlgorithm {
impl SymmetricAlgorithm {
/// Returns whether this algorithm is supported.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::SymmetricAlgorithm;
+ ///
+ /// assert!(SymmetricAlgorithm::AES256.is_supported());
+ /// assert!(SymmetricAlgorithm::TripleDES.is_supported());
+ ///
+ /// assert!(!SymmetricAlgorithm::IDEA.is_supported());
+ /// assert!(!SymmetricAlgorithm::Unencrypted.is_supported());
+ /// assert!(!SymmetricAlgorithm::Private(101).is_supported());
+ /// ```
pub fn is_supported(&self) -> bool {
use self::SymmetricAlgorithm::*;
match &self {
@@ -543,6 +721,24 @@ impl Arbitrary for SymmetricAlgorithm {
/// [`AEADAlgorithm::from`]: https://doc.rust-lang.org/std/convert/trait.From.html
///
/// This feature is [experimental](../index.html#experimental-features).
+///
+/// # Examples
+///
+/// Use `AEADAlgorithm` to set the preferred AEAD algorithms on a signature:
+///
+/// ```rust
+/// use sequoia_openpgp as openpgp;
+/// use openpgp::packet::signature::SignatureBuilder;
+/// use openpgp::types::{Features, HashAlgorithm, AEADAlgorithm, SignatureType};
+///
+/// # fn main() -> openpgp::Result<()> {
+/// let features = Features::default().set_aead(true);
+/// let mut builder = SignatureBuilder::new(SignatureType::DirectKey)
+/// .set_features(&features)?
+/// .set_preferred_aead_algorithms(vec![
+/// AEADAlgorithm::EAX,
+/// ])?;
+/// # Ok(()) }
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum AEADAlgorithm {
/// EAX mode.
@@ -561,6 +757,17 @@ pub enum AEADAlgorithm {
impl AEADAlgorithm {
/// Returns whether this algorithm is supported.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::AEADAlgorithm;
+ ///
+ /// assert!(AEADAlgorithm::EAX.is_supported());
+ ///
+ /// assert!(!AEADAlgorithm::OCB.is_supported());
+ /// ```
pub fn is_supported(&self) -> bool {
use self::AEADAlgorithm::*;
match &self {
@@ -621,6 +828,25 @@ impl Arbitrary for AEADAlgorithm {
/// The OpenPGP compression algorithms as defined in [Section 9.3 of RFC 4880].
///
/// [Section 9.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-9.3
+///
+/// # Examples
+///
+/// Use `CompressionAlgorithm` to set the preferred compressions algorithms on
+/// a signature:
+///
+/// ```rust
+/// use sequoia_openpgp as openpgp;
+/// use openpgp::packet::signature::SignatureBuilder;
+/// use openpgp::types::{HashAlgorithm, CompressionAlgorithm, SignatureType};
+///
+/// # fn main() -> openpgp::Result<()> {
+/// let mut builder = SignatureBuilder::new(SignatureType::DirectKey)
+/// .set_hash_algo(HashAlgorithm::SHA512)
+/// .set_preferred_compression_algorithms(vec![
+/// CompressionAlgorithm::Zlib,
+/// CompressionAlgorithm::BZip2,
+/// ])?;
+/// # Ok(()) }
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum CompressionAlgorithm {
/// Null compression.
@@ -667,6 +893,18 @@ impl Default for CompressionAlgorithm {
impl CompressionAlgorithm {
/// Returns whether this algorithm is supported.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::CompressionAlgorithm;
+ ///
+ /// assert!(CompressionAlgorithm::Uncompressed.is_supported());
+ /// assert!(CompressionAlgorithm::Zip.is_supported());
+ ///
+ /// assert!(!CompressionAlgorithm::Private(101).is_supported());
+ /// ```
pub fn is_supported(&self) -> bool {
use self::CompressionAlgorithm::*;
match &self {
@@ -732,7 +970,22 @@ impl Arbitrary for CompressionAlgorithm {
/// The OpenPGP hash algorithms as defined in [Section 9.4 of RFC 4880].
///
-/// [Section 9.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-9.4
+/// # Examples
+///
+/// Use `HashAlgorithm` to set the preferred hash algorithms on a signature:
+///
+/// ```rust
+/// use sequoia_openpgp as openpgp;
+/// use openpgp::packet::signature::SignatureBuilder;
+/// use openpgp::types::{HashAlgorithm, SignatureType};
+///
+/// # fn main() -> openpgp::Result<()> {
+/// let mut builder = SignatureBuilder::new(SignatureType::DirectKey)
+/// .set_hash_algo(HashAlgorithm::SHA512);
+/// # Ok(()) }
+/// ```
+///
+/// [Section 9.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-9.4
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum HashAlgorithm {
/// Rivest et.al. message digest 5.
@@ -852,6 +1105,22 @@ impl Arbitrary for HashAlgorithm {
/// Signature type as defined in [Section 5.2.1 of RFC 4880].
///
/// [Section 5.2.1 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.1
+///
+/// # Examples
+///
+/// Use `SignatureType` to create a timestamp signature:
+///
+/// ```rust
+/// use sequoia_openpgp as openpgp;
+/// use std::time::SystemTime;
+/// use openpgp::packet::signature::SignatureBuilder;
+/// use openpgp::types::SignatureType;
+///
+/// # fn main() -> openpgp::Result<()> {
+/// let mut builder = SignatureBuilder::new(SignatureType::Timestamp)
+/// .set_signature_creation_time(SystemTime::now())?;
+/// # Ok(()) }
+/// ```
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
pub enum SignatureType {
/// Signature over a binary document.
@@ -995,6 +1264,55 @@ impl Arbitrary for SignatureType {
/// See the description of revocation subpackets [Section 5.2.3.23 of RFC 4880].
///
/// [Section 5.2.3.23 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.23
+///
+/// # Examples
+///
+/// ```rust
+/// use sequoia_openpgp as openpgp;
+/// use openpgp::cert::prelude::*;
+/// use openpgp::policy::StandardPolicy;
+/// use openpgp::types::{RevocationStatus, ReasonForRevocation, SignatureType};
+///
+/// # fn main() -> openpgp::Result<()> {
+/// let p = &StandardPolicy::new();
+///
+/// // A certificate with a User ID.
+/// let (cert, _) = CertBuilder::new()
+/// .add_userid("Alice <alice@example.org>")
+/// .generate()?;
+///
+/// let mut keypair = cert.primary_key().key().clone()
+/// .parts_into_secret()?.into_keypair()?;
+/// let ca = cert.userids().nth(0).unwrap();
+///
+/// // Generate the revocation for the first and only UserID.
+/// let revocation =
+/// UserIDRevocationBuilder::new()
+/// .set_reason_for_revocation(
+/// ReasonForRevocation::UIDRetired,
+/// b"Left example.org.")?
+/// .build(&mut keypair, &cert, ca.userid(), None)?;
+/// assert_eq!(revocation.typ(), SignatureType::CertificationRevocation);
+///
+/// // Now merge the revocation signature into the Cert.
+/// let cert = cert.merge_packets(revocation.clone())?;
+///
+/// // Check that it is revoked.
+/// let ca = cert.userids().nth(0).unwrap();
+/// let status = ca.with_policy(p, None)?.revocation_status();
+/// if let RevocationStatus::Revoked(revs) = status {
+/// assert_eq!(revs.len(), 1);
+/// let rev = revs[0];
+///
+/// assert_eq!(rev.typ(), SignatureType::CertificationRevocation);
+/// assert_eq!(rev.reason_for_revocation(),
+/// Some((ReasonForRevocation::UIDRetired,
+/// "Left example.org.".as_bytes())));
+/// // User ID has been revoked.
+/// }
+/// # else { unreachable!(); }
+/// # Ok(()) }
+/// ```
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum ReasonForRevocation {
/// No reason specified (key revocations or cert revocations)
@@ -1096,6 +1414,63 @@ impl Arbitrary for ReasonForRevocation {
/// should be considered invalid *after* the revocation signature's
/// creation time. `KeySuperseded`, `KeyRetired`, and `UIDRetired`
/// are considered soft revocations.
+///
+/// # Examples
+///
+/// A certificate is considered to be revoked when a hard revocation is present
+/// even if it is not live at the specified time.
+///
+/// Here, a certificate is generated at `t0` and then revoked later at `t2`.
+/// At `t1` (`t0` < `t1` < `t2`) depending on the revocation type it will be
+/// either considered revoked (hard revocation) or not revoked (soft revocation):
+///
+/// ```rust
+/// # use sequoia_openpgp as openpgp;
+/// use std::time::{Duration, SystemTime};
+/// use openpgp::cert::prelude::*;
+/// use openpgp::types::{RevocationStatus, ReasonForRevocation};
+/// use openpgp::policy::StandardPolicy;
+///
+/// # fn main() -> openpgp::Result<()> {
+/// let p = &StandardPolicy::new();
+///
+/// let t0 = SystemTime::now();
+/// let (cert, _) =
+/// CertBuilder::general_purpose(None, Some("alice@example.org"))
+/// .set_creation_time(t0)
+/// .generate()?;
+///
+/// let t2 = t0 + Duration::from_secs(3600);
+///
+/// let mut signer = cert.primary_key().key().clone()
+/// .parts_into_secret()?.into_keypair()?;
+///
+/// // Create a hard revocation (KeyCompromised):
+/// let sig = CertRevocationBuilder::new()
+/// .set_reason_for_revocation(ReasonForRevocation::KeyCompromised,
+/// b"The butler did it :/")?
+/// .set_signature_creation_time(t2)?
+/// .build(&mut signer, &cert, None)?;
+///
+/// let t1 = t0 + Duration::from_secs(1200);
+/// let cert1 = cert.clone().merge_packets(sig.clone())?;
+/// assert_eq!(cert1.revocation_status(p, Some(t1)),
+/// RevocationStatus::Revoked(vec![ &sig.into() ]));
+///
+/// // Create a soft revocation (KeySuperseded):
+/// let sig = CertRevocationBuilder::new()
+/// .set_reason_for_revocation(ReasonForRevocation::KeySuperseded,
+/// b"Migrated to key XYZ")?
+/// .set_signature_creation_time(t2)?
+/// .build(&mut signer, &cert, None)?;
+///
+/// let t1 = t0 + Duration::from_secs(1200);
+/// let cert2 = cert.clone().merge_packets(sig.clone())?;
+/// assert_eq!(cert2.revocation_status(p, Some(t1)),
+/// RevocationStatus::NotAsFarAsWeKnow);
+/// # Ok(())
+/// # }
+/// ```
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RevocationType {
/// A hard revocation.
@@ -1118,6 +1493,18 @@ pub enum RevocationType {
impl ReasonForRevocation {
/// Returns the revocation's `RevocationType`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::types::{ReasonForRevocation, RevocationType};
+ ///
+ /// assert_eq!(ReasonForRevocation::KeyCompromised.revocation_type(), RevocationType::Hard);
+ /// assert_eq!(ReasonForRevocation::Private(101).revocation_type(), RevocationType::Hard);
+ ///
+ /// assert_eq!(ReasonForRevocation::KeyRetired.revocation_type(), RevocationType::Soft);
+ /// ```
pub fn revocation_type(&self) -> RevocationType {
match self {
ReasonForRevocation::Unspecified => RevocationType::Hard,
@@ -1137,6 +1524,28 @@ impl ReasonForRevocation {
/// See the description of literal data packets [Section 5.9 of RFC 4880].
///
/// [Section 5.9 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.9
+///
+/// # Examples
+///
+/// Construct a new [`Message`] containing one text literal packet:
+///
+/// [`Message`]: struct.Message.html
+///
+/// ```rust
+/// use sequoia_openpgp as openpgp;
+/// use std::convert::TryFrom;
+/// use openpgp::packet::prelude::*;
+/// use openpgp::types::DataFormat;