Skip to content

Commit

Permalink
fixup: docs pass
Browse files Browse the repository at this point in the history
  • Loading branch information
ctz committed Sep 25, 2024
1 parent d2b4dcb commit 6cd7872
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 14 deletions.
142 changes: 135 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@
//! Types here can be created from:
//!
//! - DER using (for example) [`PrivatePkcs8KeyDer::from`].
//! - PEM using (for example) [`PrivatePkcs8KeyDer::from_pem_slice`].
//! - PEM using (for example) [`pem::PemObject::from_pem_slice()`].
//!
//! `from_pem_slice` returns the first matching item from the given input.
//! `iter_pem_slice` returns every matching item from the given input.
//! It is usual for a given PEM file to contain multiple items of some types,
//! the iterator API should be used to access these.
//! The [`pem::PemObject`] trait contains the full selection of ways to construct
//! these types from PEM encodings. That includes ways to open and read from a file,
//! from a slice, or from an `std::io` stream.
//!
//! There is also a lower-level API that allows a given PEM file to be fully consumed
//! in one pass, even if it contains different data types: see [`pem::from_slice()`]
//! and the implementation of the [`pem::PemObject`] trait on the `(pem::SectionKind, Vec<u8>)`
//! tuple.
//!
//! ## Creating new certificates and keys
//!
Expand Down Expand Up @@ -98,6 +102,24 @@ pub use server_name::{
/// A DER-encoded X.509 private key, in one of several formats
///
/// See variant inner types for more detailed information.
///
/// This can load several types of PEM-encoded private key, and then reveal
/// which types were found:
///
/// ```rust
/// use rustls_pki_types::{PrivateKeyDer, pem::PemObject};
///
/// # #[cfg(feature = "std")] {
/// // load from a PEM file
/// let pkcs8 = PrivateKeyDer::from_pem_file("tests/data/nistp256key.pkcs8.pem").unwrap();
/// let pkcs1 = PrivateKeyDer::from_pem_file("tests/data/rsa1024.pkcs1.pem").unwrap();
/// let sec1 = PrivateKeyDer::from_pem_file("tests/data/nistp256key.pem").unwrap();
/// assert!(matches!(pkcs8, PrivateKeyDer::Pkcs8(_)));
/// assert!(matches!(pkcs1, PrivateKeyDer::Pkcs1(_)));
/// assert!(matches!(sec1, PrivateKeyDer::Sec1(_)));
/// # }
/// ```
#[non_exhaustive]
#[derive(Debug, PartialEq, Eq)]
pub enum PrivateKeyDer<'a> {
Expand Down Expand Up @@ -261,8 +283,19 @@ impl<'a> TryFrom<Vec<u8>> for PrivateKeyDer<'a> {
/// A DER-encoded plaintext RSA private key; as specified in PKCS#1/RFC 3447
///
/// RSA private keys are identified in PEM context as `RSA PRIVATE KEY` and when stored in a
/// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate
/// documentation.
/// file usually use a `.pem` or `.key` extension.
///
/// ```rust
/// use rustls_pki_types::{PrivatePkcs1KeyDer, pem::PemObject};
///
/// # #[cfg(feature = "std")]
/// // load from a PEM file
/// PrivatePkcs1KeyDer::from_pem_file("tests/data/rsa1024.pkcs1.pem").unwrap();
///
/// // or from a PEM byte slice...
/// # let byte_slice = include_bytes!("../tests/data/rsa1024.pkcs1.pem");
/// PrivatePkcs1KeyDer::from_pem_slice(byte_slice).unwrap();
/// ```
#[derive(PartialEq, Eq)]
pub struct PrivatePkcs1KeyDer<'a>(Der<'a>);

Expand Down Expand Up @@ -310,6 +343,18 @@ impl fmt::Debug for PrivatePkcs1KeyDer<'_> {
/// Sec1 private keys are identified in PEM context as `EC PRIVATE KEY` and when stored in a
/// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate
/// documentation.
///
/// ```rust
/// use rustls_pki_types::{PrivateSec1KeyDer, pem::PemObject};
///
/// # #[cfg(feature = "std")]
/// // load from a PEM file
/// PrivateSec1KeyDer::from_pem_file("tests/data/nistp256key.pem").unwrap();
///
/// // or from a PEM byte slice...
/// # let byte_slice = include_bytes!("../tests/data/nistp256key.pem");
/// PrivateSec1KeyDer::from_pem_slice(byte_slice).unwrap();
/// ```
#[derive(PartialEq, Eq)]
pub struct PrivateSec1KeyDer<'a>(Der<'a>);

Expand Down Expand Up @@ -357,6 +402,20 @@ impl fmt::Debug for PrivateSec1KeyDer<'_> {
/// PKCS#8 private keys are identified in PEM context as `PRIVATE KEY` and when stored in a
/// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate
/// documentation.
///
/// ```rust
/// use rustls_pki_types::{PrivatePkcs8KeyDer, pem::PemObject};
///
/// // load from a PEM file
/// # #[cfg(feature = "std")]
/// PrivatePkcs8KeyDer::from_pem_file("tests/data/nistp256key.pkcs8.pem").unwrap();
/// # #[cfg(feature = "std")]
/// PrivatePkcs8KeyDer::from_pem_file("tests/data/rsa1024.pkcs8.pem").unwrap();
///
/// // or from a PEM byte slice...
/// # let byte_slice = include_bytes!("../tests/data/nistp256key.pkcs8.pem");
/// PrivatePkcs8KeyDer::from_pem_slice(byte_slice).unwrap();
/// ```
#[derive(PartialEq, Eq)]
pub struct PrivatePkcs8KeyDer<'a>(Der<'a>);

Expand Down Expand Up @@ -440,6 +499,28 @@ impl TrustAnchor<'_> {
///
/// Certificate revocation lists are identified in PEM context as `X509 CRL` and when stored in a
/// file usually use a `.crl` extension. For more on PEM files, refer to the crate documentation.
///
/// ```rust
/// use rustls_pki_types::{CertificateRevocationListDer, pem::PemObject};
///
/// # #[cfg(feature = "std")]
/// // load several from a PEM file
/// let crls: Vec<_> = CertificateRevocationListDer::pem_file_iter("tests/data/crl.pem")
/// .unwrap()
/// .collect();
/// # #[cfg(feature = "std")]
/// assert!(crls.len() >= 1);
///
/// // or one from a PEM byte slice...
/// # let byte_slice = include_bytes!("../tests/data/crl.pem");
/// CertificateRevocationListDer::from_pem_slice(byte_slice).unwrap();
///
/// // or several from a PEM byte slice
/// let crls: Vec<_> = CertificateRevocationListDer::pem_slice_iter(byte_slice)
/// .collect();
/// assert!(crls.len() >= 1);
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CertificateRevocationListDer<'a>(Der<'a>);

Expand Down Expand Up @@ -479,6 +560,18 @@ impl<'a> From<Vec<u8>> for CertificateRevocationListDer<'a> {
///
/// Certificate signing requests are identified in PEM context as `CERTIFICATE REQUEST` and when stored in a
/// file usually use a `.csr` extension. For more on PEM files, refer to the crate documentation.
///
/// ```rust
/// use rustls_pki_types::{CertificateSigningRequestDer, pem::PemObject};
///
/// // load from a PEM file
/// # #[cfg(feature = "std")]
/// CertificateSigningRequestDer::from_pem_file("tests/data/csr.pem").unwrap();
///
/// // or from a PEM byte slice...
/// # let byte_slice = include_bytes!("../tests/data/csr.pem");
/// CertificateSigningRequestDer::from_pem_slice(byte_slice).unwrap();
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CertificateSigningRequestDer<'a>(Der<'a>);

Expand Down Expand Up @@ -519,6 +612,27 @@ impl<'a> From<Vec<u8>> for CertificateSigningRequestDer<'a> {
/// Certificates are identified in PEM context as `CERTIFICATE` and when stored in a
/// file usually use a `.pem`, `.cer` or `.crt` extension. For more on PEM files, refer to the
/// crate documentation.
///
/// ```rust
/// use rustls_pki_types::{CertificateDer, pem::PemObject};
///
/// # #[cfg(feature = "std")]
/// // load several from a PEM file
/// let certs: Vec<_> = CertificateDer::pem_file_iter("tests/data/certificate.chain.pem")
/// .unwrap()
/// .collect();
/// # #[cfg(feature = "std")]
/// assert_eq!(certs.len(), 3);
///
/// // or one from a PEM byte slice...
/// # let byte_slice = include_bytes!("../tests/data/certificate.chain.pem");
/// CertificateDer::from_pem_slice(byte_slice).unwrap();
///
/// // or several from a PEM byte slice
/// let certs: Vec<_> = CertificateDer::pem_slice_iter(byte_slice)
/// .collect();
/// assert_eq!(certs.len(), 3);
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CertificateDer<'a>(Der<'a>);

Expand Down Expand Up @@ -574,6 +688,20 @@ impl CertificateDer<'_> {
pub type SubjectPublicKeyInfo<'a> = SubjectPublicKeyInfoDer<'a>;

/// A DER-encoded SubjectPublicKeyInfo (SPKI), as specified in RFC 5280.
///
/// Public keys are identified in PEM context as a `PUBLIC KEY`.
///
/// ```rust
/// use rustls_pki_types::{SubjectPublicKeyInfoDer, pem::PemObject};
///
/// // load from a PEM file
/// # #[cfg(feature = "std")]
/// SubjectPublicKeyInfoDer::from_pem_file("tests/data/spki.pem").unwrap();
///
/// // or from a PEM byte slice...
/// # let byte_slice = include_bytes!("../tests/data/spki.pem");
/// SubjectPublicKeyInfoDer::from_pem_slice(byte_slice).unwrap();
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SubjectPublicKeyInfoDer<'a>(Der<'a>);

Expand Down
19 changes: 12 additions & 7 deletions src/pem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub trait PemObject: Sized {
/// Decode the first section of this type from PEM contained in
/// a byte slice.
///
/// `Err(NoItemsFound)` is returned if no such items are found.
/// [`Error::NoItemsFound`] is returned if no such items are found.
fn from_pem_slice(pem: &[u8]) -> Result<Self, Error> {
Self::pem_slice_iter(pem)
.next()
Expand All @@ -33,7 +33,7 @@ pub trait PemObject: Sized {

/// Decode the first section of this type from the PEM contents of the named file.
///
/// `Err(NoItemsFound)` is returned if no such items are found.
/// [`Error::NoItemsFound`] is returned if no such items are found.
#[cfg(feature = "std")]
fn from_pem_file(file_name: impl AsRef<std::path::Path>) -> Result<Self, Error> {
Self::pem_file_iter(file_name)?
Expand All @@ -43,8 +43,10 @@ pub trait PemObject: Sized {

/// Iterate over all sections of this type from the PEM contents of the named file.
///
/// Unlike other `iter_*` functions, this eagerly consumes all the sections
/// to bring together errors opening the file and parsing the contents.
/// This reports errors in two phases:
///
/// - errors opening the file are reported from this function directly,
/// - errors reading from the file are reported from the returned iterator,
#[cfg(feature = "std")]
fn pem_file_iter(
file_name: impl AsRef<std::path::Path>,
Expand All @@ -55,15 +57,15 @@ pub trait PemObject: Sized {
})
}

/// Decode the first section of this type from PEM read from an `io::Read`.
/// Decode the first section of this type from PEM read from an [`io::Read`].
#[cfg(feature = "std")]
fn from_pem_reader(rd: impl std::io::Read) -> Result<Self, Error> {
Self::pem_reader_iter(rd)
.next()
.unwrap_or(Err(Error::NoItemsFound))
}

/// Iterate over all sections of this type from PEM present in an `io::Read`.
/// Iterate over all sections of this type from PEM present in an [`io::Read`].
#[cfg(feature = "std")]
fn pem_reader_iter<R: std::io::Read>(rd: R) -> ReadIter<io::BufReader<R>, Self> {
ReadIter::<_, Self> {
Expand All @@ -72,7 +74,10 @@ pub trait PemObject: Sized {
}
}

/// Conversion from a PEM SectionKind and body data.
/// Conversion from a PEM [`SectionKind`] and body data.
///
/// This inspects `kind`, and if it matches this type's PEM section kind,
/// converts `der` into this type.
fn from_pem(kind: SectionKind, der: Vec<u8>) -> Option<Self>;
}

Expand Down

0 comments on commit 6cd7872

Please sign in to comment.