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}