use crate::*;
use once_cell::sync::Lazy;
use std::sync::Arc;
pub const WK_CA_KEYPAIR_PEM: &str = r#"-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgkxOEyiRyocjLRpQk
RE7/bOwmHtkdLLGQrlz23m4aKQOhRANCAATUDekPM40vfqOMxf00KZwRk6gSciHx
xkzPZovign1qmbu0vZstKoVLXoGvlA/Kral9txqhSEGqIL7TdbKyMMQz
-----END PRIVATE KEY-----"#;
pub const WK_CA_ID: &str = "aKdjnmYOn1HVc_RwSdxR6qa.aQLW3d5D1nYiSSO2cOrcT7a";
static WK_CA_RCGEN_CERT: Lazy<Arc<rcgen::Certificate>> = Lazy::new(|| {
let mut params = rcgen::CertificateParams::new(vec![WK_CA_ID.into()]);
params.alg = &rcgen::PKCS_ECDSA_P256_SHA256;
params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained);
params
.extended_key_usages
.push(rcgen::ExtendedKeyUsagePurpose::Any);
params.distinguished_name = rcgen::DistinguishedName::new();
params.distinguished_name.push(
rcgen::DnType::CommonName,
"Lair Well-Known Pseudo-Self-Signing CA",
);
params
.distinguished_name
.push(rcgen::DnType::OrganizationName, "Holochain Foundation");
params.key_pair =
Some(rcgen::KeyPair::from_pem(WK_CA_KEYPAIR_PEM).unwrap());
let cert = rcgen::Certificate::from_params(params).unwrap();
Arc::new(cert)
});
pub static WK_CA_CERT_DER: Lazy<Arc<Vec<u8>>> = Lazy::new(|| {
let cert = WK_CA_RCGEN_CERT.as_ref();
let cert = cert.serialize_der().unwrap();
Arc::new(cert)
});
pub struct TlsCertGenResult {
pub sni: Arc<str>,
pub priv_key: sodoken::BufRead,
pub cert: Arc<[u8]>,
pub digest: Arc<[u8; 32]>,
}
pub async fn tls_cert_self_signed_new() -> LairResult<TlsCertGenResult> {
let (sni, priv_key, cert) = tokio::task::spawn_blocking(|| {
let sni = format!("a{}a.a{}a", nanoid::nanoid!(), nanoid::nanoid!());
let mut params = rcgen::CertificateParams::new(vec![sni.clone()]);
params.alg = &rcgen::PKCS_ECDSA_P256_SHA256;
params
.extended_key_usages
.push(rcgen::ExtendedKeyUsagePurpose::Any);
params
.extended_key_usages
.push(rcgen::ExtendedKeyUsagePurpose::ServerAuth);
params
.extended_key_usages
.push(rcgen::ExtendedKeyUsagePurpose::ClientAuth);
params.distinguished_name = rcgen::DistinguishedName::new();
params.distinguished_name.push(
rcgen::DnType::CommonName,
format!("Lair Pseudo-Self-Signed Cert {}", &sni),
);
let cert = rcgen::Certificate::from_params(params)
.map_err(one_err::OneErr::new)?;
let cert_pk = zeroize::Zeroizing::new(cert.serialize_private_key_der());
let priv_key = sodoken::BufWrite::new_mem_locked(cert_pk.len())?;
priv_key.write_lock().copy_from_slice(&cert_pk);
let priv_key = priv_key.to_read();
let root_cert = &**WK_CA_RCGEN_CERT;
let cert_der = cert
.serialize_der_with_signer(root_cert)
.map_err(one_err::OneErr::new)?;
LairResult::Ok((sni, priv_key, cert_der))
})
.await
.map_err(one_err::OneErr::new)??;
let digest = sodoken::BufWriteSized::new_no_lock();
sodoken::hash::blake2b::hash(digest.clone(), cert.clone()).await?;
Ok(TlsCertGenResult {
sni: sni.into(),
priv_key,
cert: cert.into(),
digest: digest.try_unwrap_sized().unwrap().into(),
})
}