1use lazy_static::lazy_static;
2use openssl::ec::{Asn1Flag, EcGroup, EcKey};
3use openssl::hash::MessageDigest;
4use openssl::nid::Nid;
5use openssl::pkey::{self, PKey};
6use openssl::rsa::Rsa;
7use openssl::stack::Stack;
8use openssl::x509::extension::SubjectAlternativeName;
9use openssl::x509::{X509Req, X509ReqBuilder, X509};
10
11use crate::Result;
12
13lazy_static! {
14 pub(crate) static ref EC_GROUP_P256: EcGroup = ec_group(Nid::X9_62_PRIME256V1);
15 pub(crate) static ref EC_GROUP_P384: EcGroup = ec_group(Nid::SECP384R1);
16}
17
18fn ec_group(nid: Nid) -> EcGroup {
19 let mut g = EcGroup::from_curve_name(nid).expect("EcGroup");
20 g.set_asn1_flag(Asn1Flag::NAMED_CURVE);
22 g
23}
24
25pub fn create_rsa_key(bits: u32) -> PKey<pkey::Private> {
30 let pri_key_rsa = Rsa::generate(bits).expect("Rsa::generate");
31 PKey::from_rsa(pri_key_rsa).expect("from_rsa")
32}
33
34pub fn create_p256_key() -> PKey<pkey::Private> {
36 let pri_key_ec = EcKey::generate(&*EC_GROUP_P256).expect("EcKey");
37 PKey::from_ec_key(pri_key_ec).expect("from_ec_key")
38}
39
40pub fn create_p384_key() -> PKey<pkey::Private> {
42 let pri_key_ec = EcKey::generate(&*EC_GROUP_P384).expect("EcKey");
43 PKey::from_ec_key(pri_key_ec).expect("from_ec_key")
44}
45
46pub(crate) fn create_csr(pkey: &PKey<pkey::Private>, domains: &[&str]) -> Result<X509Req> {
47 let mut req_bld = X509ReqBuilder::new().expect("X509ReqBuilder");
50
51 req_bld.set_pubkey(pkey).expect("set_pubkey");
53
54 let mut stack = Stack::new().expect("Stack::new");
56 let ctx = req_bld.x509v3_context(None);
57 let mut an = SubjectAlternativeName::new();
58 for d in domains {
59 an.dns(d);
60 }
61
62 let ext = an.build(&ctx).expect("SubjectAlternativeName::build");
63 stack.push(ext).expect("Stack::push");
64 req_bld.add_extensions(&stack).expect("add_extensions");
65
66 req_bld
68 .sign(pkey, MessageDigest::sha256())
69 .expect("csr_sign");
70
71 Ok(req_bld.build())
73}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct Certificate {
78 private_key: String,
79 certificate: String,
80}
81
82impl Certificate {
83 pub(crate) fn new(private_key: String, certificate: String) -> Self {
84 Certificate {
85 private_key,
86 certificate,
87 }
88 }
89
90 pub fn private_key(&self) -> &str {
92 &self.private_key
93 }
94
95 pub fn private_key_der(&self) -> Vec<u8> {
97 let pkey = PKey::private_key_from_pem(self.private_key.as_bytes()).expect("from_pem");
98 pkey.private_key_to_der().expect("private_key_to_der")
99 }
100
101 pub fn certificate(&self) -> &str {
103 &self.certificate
104 }
105
106 pub fn certificate_der(&self) -> Vec<u8> {
108 let x509 = X509::from_pem(self.certificate.as_bytes()).expect("from_pem");
109 x509.to_der().expect("to_der")
110 }
111
112 pub fn valid_days_left(&self) -> i64 {
120 if cfg!(test) {
122 return 89;
123 }
124
125 let x509 = X509::from_pem(self.certificate.as_bytes()).expect("from_pem");
127
128 let not_after = format!("{}", x509.not_after());
130 let expires = parse_date(¬_after);
133 let dur = expires - time::now();
134
135 dur.num_days()
136 }
137}
138
139fn parse_date(s: &str) -> time::Tm {
140 debug!("Parse date/time: {}", s);
141 time::strptime(s, "%h %e %H:%M:%S %Y %Z").expect("strptime")
142}
143
144#[cfg(test)]
145mod test {
146 use super::*;
147
148 #[test]
149 fn test_parse_date() {
150 let x = parse_date("May 3 07:40:15 2019 GMT");
151 assert_eq!(time::strftime("%F %T", &x).unwrap(), "2019-05-03 07:40:15");
152 }
153}