| use std::fmt; |
| |
| use crate::Error; |
| |
| /// This type contains a private key by value. |
| /// |
| /// The private key must be DER-encoded ASN.1 in either |
| /// PKCS#8, PKCS#1, or Sec1 format. |
| /// |
| /// A common format for storing private keys is |
| /// [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail). |
| /// PEM private keys are commonly stored in files with a `.pem` or `.key` suffix, and look like this: |
| /// |
| /// ```txt |
| /// -----BEGIN PRIVATE KEY----- |
| /// <base64-encoded private key content> |
| /// -----END PRIVATE KEY----- |
| /// ``` |
| /// |
| /// The [`rustls-pemfile`](https://docs.rs/rustls-pemfile/latest/rustls_pemfile/) crate can be used |
| /// to parse PEM files. The [`rcgen`](https://docs.rs/rcgen/latest/rcgen/) can be used to generate |
| /// certificates and private keys. |
| /// |
| /// ## Examples |
| /// |
| /// Creating a `PrivateKey` from a PEM file containing a PKCS8-encoded private key using the `rustls_pemfile` crate: |
| /// |
| /// ```rust |
| /// use std::fs::File; |
| /// use std::io::BufReader; |
| /// use rustls::PrivateKey; |
| /// |
| /// fn load_private_key_from_file(path: &str) -> Result<PrivateKey, Box<dyn std::error::Error>> { |
| /// let file = File::open(&path)?; |
| /// let mut reader = BufReader::new(file); |
| /// let mut keys = rustls_pemfile::pkcs8_private_keys(&mut reader)?; |
| /// |
| /// match keys.len() { |
| /// 0 => Err(format!("No PKCS8-encoded private key found in {path}").into()), |
| /// 1 => Ok(PrivateKey(keys.remove(0))), |
| /// _ => Err(format!("More than one PKCS8-encoded private key found in {path}").into()), |
| /// } |
| /// } |
| /// ``` |
| #[derive(Debug, Clone, Eq, PartialEq)] |
| pub struct PrivateKey(pub Vec<u8>); |
| |
| /// This type contains a single certificate by value. |
| /// |
| /// The certificate must be in DER-encoded X.509 format. |
| /// |
| /// A common format for storing certificates is |
| /// [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail). |
| /// PEM certificates are commonly stored in files with a `.pem`, `.cer` or `.crt` suffix, and look |
| /// like this: |
| /// |
| /// ```txt |
| /// -----BEGIN CERTIFICATE----- |
| /// <base64-encoded certificate content> |
| /// -----END CERTIFICATE----- |
| /// ``` |
| /// |
| /// The [`rustls-pemfile`](https://docs.rs/rustls-pemfile/latest/rustls_pemfile/) crate can be used |
| /// to parse PEM files. The [`rcgen`](https://docs.rs/rcgen/latest/rcgen/) crate can be used to |
| /// generate certificates and private keys. |
| /// |
| /// ## Examples |
| /// |
| /// Parsing a PEM file to extract DER-encoded certificates: |
| /// |
| /// ```rust |
| /// use std::fs::File; |
| /// use std::io::BufReader; |
| /// use rustls::Certificate; |
| /// |
| /// fn load_certificates_from_pem(path: &str) -> std::io::Result<Vec<Certificate>> { |
| /// let file = File::open(path)?; |
| /// let mut reader = BufReader::new(file); |
| /// let certs = rustls_pemfile::certs(&mut reader)?; |
| /// |
| /// Ok(certs.into_iter().map(Certificate).collect()) |
| /// } |
| /// ``` |
| #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] |
| pub struct Certificate(pub Vec<u8>); |
| |
| impl AsRef<[u8]> for Certificate { |
| fn as_ref(&self) -> &[u8] { |
| &self.0 |
| } |
| } |
| |
| impl fmt::Debug for Certificate { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| use super::bs_debug::BsDebug; |
| f.debug_tuple("Certificate") |
| .field(&BsDebug(&self.0)) |
| .finish() |
| } |
| } |
| |
| /// wrapper around internal representation of a parsed certificate. This is used in order to avoid parsing twice when specifying custom verification |
| #[cfg_attr(not(feature = "dangerous_configuration"), allow(unreachable_pub))] |
| #[cfg_attr(docsrs, doc(cfg(feature = "dangerous_configuration")))] |
| pub struct ParsedCertificate<'a>(pub(crate) webpki::EndEntityCert<'a>); |
| |
| impl<'a> TryFrom<&'a Certificate> for ParsedCertificate<'a> { |
| type Error = Error; |
| fn try_from(value: &'a Certificate) -> Result<ParsedCertificate<'a>, Self::Error> { |
| webpki::EndEntityCert::try_from(value.0.as_ref()) |
| .map_err(crate::verify::pki_error) |
| .map(ParsedCertificate) |
| } |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use super::Certificate; |
| |
| #[test] |
| fn certificate_debug() { |
| assert_eq!( |
| "Certificate(b\"ab\")", |
| format!("{:?}", Certificate(b"ab".to_vec())) |
| ); |
| } |
| } |