kutil_http/tls/
pem.rs

1use {
2    rustls::{crypto::aws_lc_rs::sign::*, sign::*},
3    rustls_pki_types::*,
4    std::{io, sync::*},
5};
6
7/// Creates a [CertifiedKey] by parsing PEM (Privacy-Enhanced Mail) files as X.509 certificates.
8pub fn certified_key_from_pem(certificates_pem: &[u8], private_key_pem: &[u8]) -> io::Result<CertifiedKey> {
9    let certificates = parse_certificates_pem(certificates_pem)?;
10    let signing_key = get_signing_key_from_pem(private_key_pem)?;
11    Ok(CertifiedKey { cert: certificates, key: signing_key, ocsp: None })
12}
13
14/// Parses a PEM (Privacy-Enhanced Mail) file as X.509 certificates.
15///
16/// Returns them in DER (Distinguished Encoding Rules) format.
17pub fn parse_certificates_pem(pem: &[u8]) -> io::Result<Vec<CertificateDer<'static>>> {
18    let mut certificates = Vec::new();
19    for certificate in rustls_pemfile::certs(&mut pem.as_ref()) {
20        certificates.push(certificate?);
21    }
22    Ok(certificates)
23}
24
25/// Parses a PEM (Privacy-Enhanced Mail) file as a X.509 private key.
26///
27/// Only parses the first entry in the PEM, ignoring the rest.
28///
29/// Returns it in DER (Distinguished Encoding Rules) format.
30pub fn parse_private_key_pem(pem: &[u8]) -> io::Result<PrivateKeyDer<'static>> {
31    // Note: axum_server seems to not know about rustls_pemfile::private_key
32    // https://github.com/programatik29/axum-server/blob/f60b6150bba0aecf4910f877fd0bc12ac24d030b/src/tls_rustls/mod.rs#L302
33
34    match rustls_pemfile::private_key(&mut pem.as_ref())? {
35        Some(private_key) => Ok(private_key),
36        None => Err(io::Error::other("no private key in PEM")),
37    }
38}
39
40/// Get a signing key from a PEM (Privacy-Enhanced Mail) file.
41///
42/// See [parse_private_key_pem].
43pub fn get_signing_key_from_pem(pem: &[u8]) -> io::Result<Arc<dyn SigningKey>> {
44    any_supported_type(&parse_private_key_pem(pem)?).map_err(io::Error::other)
45}