diff options
author | Wiktor Kwapisiewicz <wiktor@metacode.biz> | 2020-05-06 14:38:33 +0200 |
---|---|---|
committer | Wiktor Kwapisiewicz <wiktor@metacode.biz> | 2020-06-01 15:30:15 +0200 |
commit | ebb719dcc6c0a719cab77f4fb7e296e8efe85f13 (patch) | |
tree | 959664d259f3d57396086c8c78907297130e983e /openpgp | |
parent | 09f30c446541acee77f18d365cbdbb970dd82543 (diff) |
openpgp: Add doctests to types module.
- Fixes #475.
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/src/cert/builder.rs | 2 | ||||
-rw-r--r-- | openpgp/src/types/compression_level.rs | 36 | ||||
-rw-r--r-- | openpgp/src/types/features.rs | 34 | ||||
-rw-r--r-- | openpgp/src/types/key_flags.rs | 33 | ||||
-rw-r--r-- | openpgp/src/types/mod.rs | 453 | ||||
-rw-r--r-- | openpgp/src/types/revocation_key.rs | 42 | ||||
-rw-r--r-- | openpgp/src/types/server_preferences.rs | 34 | ||||
-rw-r--r-- | openpgp/src/types/timestamp.rs | 74 |
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; |