1 use openssl::{
2 asn1::Asn1Time,
3 pkey::PKey,
4 rsa::Rsa,
5 x509::{
6 extension::{AuthorityKeyIdentifier, BasicConstraints, SubjectKeyIdentifier},
7 X509NameBuilder, X509,
8 },
9 };
10
11 pub fn generate_certificate() -> anyhow::Result<(String, String)> {
12 let cert_result: Result<(Vec<u8>, Vec<u8>), openssl::error::ErrorStack> = {
13 let rsa = Rsa::generate(4096)?;
14 let pkey = PKey::from_rsa(rsa)?;
15 let mut name = X509NameBuilder::new()?;
16 name.append_entry_by_text("CN", "localhost")?;
17 let name = name.build();
18 let mut builder = X509::builder()?;
19 builder.set_version(2)?;
20 builder.set_subject_name(&name)?;
21 builder.set_issuer_name(&name)?;
22 builder.set_pubkey(&pkey)?;
23 let now = Asn1Time::days_from_now(0)?;
24 let later = Asn1Time::days_from_now(3650)?;
25 builder.set_not_before(now.as_ref())?;
26 builder.set_not_after(later.as_ref())?;
27 builder.append_extension(BasicConstraints::new().critical().ca().build()?)?;
28 builder.append_extension(
29 SubjectKeyIdentifier::new().build(&builder.x509v3_context(None, None))?,
30 )?;
31 builder.append_extension(
32 AuthorityKeyIdentifier::new()
33 .keyid(true)
34 .issuer(true)
35 .build(&builder.x509v3_context(None, None))?,
36 )?;
37 builder.sign(&pkey, openssl::hash::MessageDigest::sha256())?;
38 let c = builder.build();
39 Ok((c.to_pem()?, pkey.private_key_to_pem_pkcs8()?))
40 };
41 let (pem_certificate, pem_private_key) = cert_result?;
42
43 Ok((
44 String::from_utf8_lossy(&pem_certificate).to_string(),
45 String::from_utf8_lossy(&pem_private_key).to_string(),
46 ))
47 }