1use std::str::FromStr;
2
3use rcgen::{CertificateParams, DistinguishedName, DnType, Ia5String, KeyPair, SanType};
4use rsa::{
5 pkcs8::{EncodePrivateKey, LineEnding},
6 RsaPrivateKey,
7};
8use time::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time};
9
10mod ca;
11mod error;
12
13pub use ca::*;
14pub use error::*;
15
16#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct ChikCertificate {
18 pub cert_pem: String,
19 pub key_pem: String,
20}
21
22impl ChikCertificate {
23 pub fn generate() -> Result<ChikCertificate> {
24 let mut rng = rand::thread_rng();
25
26 let key = RsaPrivateKey::new(&mut rng, 2048)?;
27 let key_pem = key.to_pkcs8_pem(LineEnding::default())?.to_string();
28
29 let mut params = CertificateParams::default();
30
31 let mut subject = DistinguishedName::new();
32 subject.push(DnType::CommonName, "Chik");
33 subject.push(DnType::OrganizationName, "Chik");
34 subject.push(DnType::OrganizationalUnitName, "Organic Farming Division");
35 params.distinguished_name = subject;
36
37 params.subject_alt_names = vec![SanType::DnsName(Ia5String::from_str("chiknetwork.com")?)];
38
39 params.not_before = OffsetDateTime::now_utc() - Duration::DAY;
40 params.not_after = PrimitiveDateTime::new(
41 Date::from_calendar_date(2100, Month::August, 2)?,
42 Time::MIDNIGHT,
43 )
44 .assume_utc();
45
46 let key_pair = KeyPair::from_pem_and_sign_algo(&key_pem, &rcgen::PKCS_RSA_SHA256)?;
47 let cert = params.signed_by(&key_pair, &CHIK_CA, &CHIK_CA_KEY_PAIR)?;
48 let cert_pem = cert.pem();
49
50 Ok(ChikCertificate { cert_pem, key_pem })
51 }
52}