use super::common::{certificate, errors};
use std::fs;
#[derive(Debug, Clone)]
pub struct CertificateConfig {
pub cn: String,
pub org: String,
pub country: String,
pub validity_days: u32,
}
impl Default for CertificateConfig {
fn default() -> Self {
Self {
cn: certificate::DEFAULT_CN.to_string(),
org: certificate::DEFAULT_ORG.to_string(),
country: certificate::DEFAULT_COUNTRY.to_string(),
validity_days: certificate::DEFAULT_VALIDITY_DAYS,
}
}
}
#[derive(Debug, Clone)]
pub struct CertificatePair {
pub cert_der: Vec<u8>,
pub key_der: Vec<u8>,
}
impl CertificatePair {
pub fn generate_self_signed(_config: CertificateConfig) -> Result<Self, String> {
let subject_alt_names = certificate::ALT_NAMES
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>();
let cert = rcgen::generate_simple_self_signed(subject_alt_names)
.map_err(|e| errors::cert_generation_failed(&e))?;
let cert_der = cert.cert.der().to_vec();
let key_der = cert.key_pair.serialize_der();
Ok(CertificatePair { cert_der, key_der })
}
pub fn from_pem(cert_pem: &str, key_pem: &str) -> Result<Self, String> {
let mut cert_reader = cert_pem.as_bytes();
let certs: Result<Vec<_>, _> = rustls_pemfile::certs(&mut cert_reader).collect();
let certs = certs.map_err(|e| errors::cert_parse_failed(&e))?;
let cert_der = certs
.into_iter()
.next()
.ok_or("No certificate found in PEM")?
.to_vec();
let mut key_reader = key_pem.as_bytes();
let private_key = rustls_pemfile::private_key(&mut key_reader)
.map_err(|e| errors::key_parse_failed(&e))?
.ok_or("No private key found in PEM")?;
let key_der = private_key.secret_der().to_vec();
Ok(CertificatePair { cert_der, key_der })
}
pub fn from_der_files(cert_path: &str, key_path: &str) -> Result<Self, String> {
let cert_der =
fs::read(cert_path).map_err(|e| errors::cert_file_read_failed(cert_path, &e))?;
let key_der = fs::read(key_path).map_err(|e| errors::key_file_read_failed(key_path, &e))?;
Ok(CertificatePair { cert_der, key_der })
}
pub fn cert_der(&self) -> &[u8] {
&self.cert_der
}
pub fn key_der(&self) -> &[u8] {
&self.key_der
}
pub fn is_valid(&self) -> bool {
!self.cert_der.is_empty() && !self.key_der.is_empty()
}
}