1use rcgen::{CertificateParams, IsCa, KeyPair, KeyUsagePurpose};
2use rustls::pki_types::{CertificateDer, PrivateKeyDer};
3
4use crate::Error;
5
6pub struct CertificateAuthority {
8 pub(crate) cert: rcgen::Certificate,
9 pub(crate) key: KeyPair,
10}
11
12impl CertificateAuthority {
13 pub fn from_pem(cert_pem: &str, key_pem: &str) -> Result<Self, Error> {
15 let key = KeyPair::from_pem(key_pem)?;
16 let params = CertificateParams::from_ca_cert_pem(cert_pem)?;
17 let cert = params.self_signed(&key)?;
18 Ok(Self { cert, key })
19 }
20
21 pub fn from_pem_files(
23 cert_path: impl AsRef<std::path::Path>,
24 key_path: impl AsRef<std::path::Path>,
25 ) -> Result<Self, Error> {
26 let cert_pem = std::fs::read_to_string(cert_path)?;
27 let key_pem = std::fs::read_to_string(key_path)?;
28 Self::from_pem(&cert_pem, &key_pem)
29 }
30
31 pub fn generate() -> Result<Self, Error> {
33 Self::generate_with_cn("MITM CA")
34 }
35
36 pub fn generate_with_cn(cn: &str) -> Result<Self, Error> {
38 let mut params = CertificateParams::default();
39 params.is_ca = IsCa::Ca(rcgen::BasicConstraints::Unconstrained);
40 params
41 .distinguished_name
42 .push(rcgen::DnType::CommonName, cn);
43 params.key_usages = vec![KeyUsagePurpose::KeyCertSign, KeyUsagePurpose::CrlSign];
44
45 let key = KeyPair::generate()?;
46 let cert = params.self_signed(&key)?;
47 Ok(Self { cert, key })
48 }
49
50 pub fn to_pem_files(
52 &self,
53 cert_path: impl AsRef<std::path::Path>,
54 key_path: impl AsRef<std::path::Path>,
55 ) -> Result<(), Error> {
56 std::fs::write(cert_path, self.cert.pem())?;
57 std::fs::write(key_path, self.key.serialize_pem())?;
58 Ok(())
59 }
60
61 pub fn cert_pem(&self) -> String {
63 self.cert.pem()
64 }
65
66 pub fn key_pem(&self) -> String {
68 self.key.serialize_pem()
69 }
70
71 pub fn generate_cert(
73 &self,
74 hostname: &str,
75 ) -> Result<(CertificateDer<'static>, PrivateKeyDer<'static>), Error> {
76 let mut params = CertificateParams::new(vec![hostname.to_string()])?;
77 params.is_ca = IsCa::NoCa;
78 params.key_usages = vec![KeyUsagePurpose::DigitalSignature];
79 params
80 .distinguished_name
81 .push(rcgen::DnType::CommonName, hostname);
82
83 let key_pair = KeyPair::generate()?;
84 let key_der = PrivateKeyDer::Pkcs8(key_pair.serialized_der().to_vec().into());
85 let cert = params.signed_by(&key_pair, &self.cert, &self.key)?;
86 let cert_der = cert.der().clone();
87
88 Ok((cert_der, key_der))
89 }
90}