|
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
|
} |