rustls/
key.rs

1use std::fmt;
2
3use crate::Error;
4
5/// This type contains a private key by value.
6///
7/// The private key must be DER-encoded ASN.1 in either
8/// PKCS#8, PKCS#1, or Sec1 format.
9///
10/// A common format for storing private keys is
11/// [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail).
12/// PEM private keys are commonly stored in files with a `.pem` or `.key` suffix, and look like this:
13///
14/// ```txt
15/// -----BEGIN PRIVATE KEY-----
16/// <base64-encoded private key content>
17/// -----END PRIVATE KEY-----
18/// ```
19///
20/// The [`rustls-pemfile`](https://docs.rs/rustls-pemfile/latest/rustls_pemfile/) crate can be used
21/// to parse PEM files. The [`rcgen`](https://docs.rs/rcgen/latest/rcgen/) can be used to generate
22/// certificates and private keys.
23///
24/// ## Examples
25///
26/// Creating a `PrivateKey` from a PEM file containing a PKCS8-encoded private key using the `rustls_pemfile` crate:
27///
28/// ```rust
29/// use std::fs::File;
30/// use std::io::BufReader;
31/// use rustls::PrivateKey;
32///
33/// fn load_private_key_from_file(path: &str) -> Result<PrivateKey, Box<dyn std::error::Error>> {
34///     let file = File::open(&path)?;
35///     let mut reader = BufReader::new(file);
36///     let mut keys = rustls_pemfile::pkcs8_private_keys(&mut reader)?;
37///
38///     match keys.len() {
39///         0 => Err(format!("No PKCS8-encoded private key found in {path}").into()),
40///         1 => Ok(PrivateKey(keys.remove(0))),
41///         _ => Err(format!("More than one PKCS8-encoded private key found in {path}").into()),
42///     }
43/// }
44/// ```
45#[derive(Debug, Clone, Eq, PartialEq)]
46pub struct PrivateKey(pub Vec<u8>);
47
48/// This type contains a single certificate by value.
49///
50/// The certificate must be in DER-encoded X.509 format.
51///
52/// A common format for storing certificates is
53/// [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail).
54/// PEM certificates are commonly stored in files with a `.pem`, `.cer` or `.crt` suffix, and look
55/// like this:
56///
57/// ```txt
58/// -----BEGIN CERTIFICATE-----
59/// <base64-encoded certificate content>
60/// -----END CERTIFICATE-----
61/// ```
62///
63/// The [`rustls-pemfile`](https://docs.rs/rustls-pemfile/latest/rustls_pemfile/) crate can be used
64/// to parse PEM files. The [`rcgen`](https://docs.rs/rcgen/latest/rcgen/) crate can be used to
65/// generate certificates and private keys.
66///
67/// ## Examples
68///
69/// Parsing a PEM file to extract DER-encoded certificates:
70///
71/// ```rust
72/// use std::fs::File;
73/// use std::io::BufReader;
74/// use rustls::Certificate;
75///
76/// fn load_certificates_from_pem(path: &str) -> std::io::Result<Vec<Certificate>> {
77///     let file = File::open(path)?;
78///     let mut reader = BufReader::new(file);
79///     let certs = rustls_pemfile::certs(&mut reader)?;
80///
81///     Ok(certs.into_iter().map(Certificate).collect())
82/// }
83/// ```
84#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
85pub struct Certificate(pub Vec<u8>);
86
87impl AsRef<[u8]> for Certificate {
88    fn as_ref(&self) -> &[u8] {
89        &self.0
90    }
91}
92
93impl fmt::Debug for Certificate {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        use super::bs_debug::BsDebug;
96        f.debug_tuple("Certificate")
97            .field(&BsDebug(&self.0))
98            .finish()
99    }
100}
101
102/// wrapper around internal representation of a parsed certificate. This is used in order to avoid parsing twice when specifying custom verification
103#[cfg_attr(not(feature = "dangerous_configuration"), allow(unreachable_pub))]
104#[cfg_attr(docsrs, doc(cfg(feature = "dangerous_configuration")))]
105pub struct ParsedCertificate<'a>(pub(crate) webpki::EndEntityCert<'a>);
106
107impl<'a> TryFrom<&'a Certificate> for ParsedCertificate<'a> {
108    type Error = Error;
109    fn try_from(value: &'a Certificate) -> Result<Self, Self::Error> {
110        webpki::EndEntityCert::try_from(value.0.as_ref())
111            .map_err(crate::verify::pki_error)
112            .map(ParsedCertificate)
113    }
114}
115
116#[cfg(test)]
117mod test {
118    use super::Certificate;
119
120    #[test]
121    fn certificate_debug() {
122        assert_eq!(
123            "Certificate(b\"ab\")",
124            format!("{:?}", Certificate(b"ab".to_vec()))
125        );
126    }
127}