浏览代码

Add ca dir

Signed-off-by: zu1k <[email protected]>
zu1k 3 年之前
父节点
当前提交
d3e64f2644
共有 4 个文件被更改,包括 178 次插入3 次删除
  1. 3 3
      .gitignore
  2. 35 0
      src/ca/gen.rs
  3. 5 0
      src/ca/mod.rs
  4. 135 0
      src/ca/root.rs

+ 3 - 3
.gitignore

@@ -1,5 +1,5 @@
-target
-bin
-ca
+/target
+/bin
+/ca
 .vscode
 .idea

+ 35 - 0
src/ca/gen.rs

@@ -0,0 +1,35 @@
+extern crate rcgen;
+use log::error;
+use rcgen::*;
+use std::fs;
+
+pub fn gen_ca() {
+    let mut params = CertificateParams::default();
+    let mut distinguished_name = DistinguishedName::new();
+    distinguished_name.push(DnType::CommonName, "Good-MITM");
+    distinguished_name.push(DnType::OrganizationName, "Good-MITM");
+    distinguished_name.push(DnType::CountryName, "CN");
+    distinguished_name.push(DnType::LocalityName, "CN");
+    params.distinguished_name = distinguished_name;
+    params.key_usages = vec![
+        KeyUsagePurpose::DigitalSignature,
+        KeyUsagePurpose::KeyCertSign,
+        KeyUsagePurpose::CrlSign,
+    ];
+    params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
+    let cert = Certificate::from_params(params).unwrap();
+    let cert_crt = cert.serialize_pem().unwrap();
+
+    fs::create_dir("ca").unwrap();
+
+    println!("{}", cert_crt);
+    if let Err(err) = fs::write("ca/cert.crt", cert_crt) {
+        error!("cert file write failed: {}", err);
+    }
+
+    let private_key = cert.serialize_private_key_pem();
+    println!("{}", private_key);
+    if let Err(err) = fs::write("ca/private.key", private_key) {
+        error!("private key file write failed: {}", err);
+    }
+}

+ 5 - 0
src/ca/mod.rs

@@ -0,0 +1,5 @@
+mod gen;
+pub use gen::*;
+
+mod root;
+pub use root::*;

+ 135 - 0
src/ca/root.rs

@@ -0,0 +1,135 @@
+use crate::error::Error;
+use chrono::{Duration, Utc};
+use http::uri::Authority;
+use moka::future::Cache;
+use rcgen::{
+    DistinguishedName, DnType, ExtendedKeyUsagePurpose, KeyPair, KeyUsagePurpose, RcgenError,
+    SanType,
+};
+use std::{
+    sync::{Arc, Mutex},
+    time::{SystemTime, UNIX_EPOCH},
+};
+use tokio_rustls::rustls::{self, ServerConfig};
+
+/// Issues certificates for use when communicating with clients.
+///
+/// Issues certificates for communicating with clients over TLS. Certificates are cached in memory
+/// up to a max size that is provided when creating the authority. Clients should be configured to
+/// either trust the provided root certificate, or to ignore certificate errors.
+#[derive(Clone)]
+pub struct CertificateAuthority {
+    private_key: rustls::PrivateKey,
+    ca_cert: rustls::Certificate,
+    ca_cert_string: String,
+    cache: Cache<Authority, Arc<ServerConfig>>,
+    serial_number: Arc<Mutex<u64>>,
+}
+
+impl CertificateAuthority {
+    /// Attempts to create a new certificate authority.
+    ///
+    /// This will fail if the provided key or certificate is invalid, or if the key does not match
+    /// the certificate.
+    pub fn new(
+        private_key: rustls::PrivateKey,
+        ca_cert: rustls::Certificate,
+        ca_cert_string: String,
+        cache_size: usize,
+    ) -> Result<CertificateAuthority, Error> {
+        let ca = CertificateAuthority {
+            private_key,
+            ca_cert,
+            ca_cert_string,
+            cache: Cache::new(cache_size),
+            serial_number: Arc::new(Mutex::new(now_seconds())),
+        };
+
+        ca.validate()?;
+        Ok(ca)
+    }
+
+    pub(crate) async fn gen_server_config(&self, authority: &Authority) -> Arc<ServerConfig> {
+        if let Some(server_cfg) = self.cache.get(authority) {
+            return server_cfg;
+        }
+
+        let certs = vec![self.gen_cert(authority)];
+
+        let server_cfg = ServerConfig::builder()
+            .with_safe_defaults()
+            .with_no_client_auth()
+            .with_single_cert(certs, self.private_key.clone())
+            .expect("Failed to set certificate");
+        let server_cfg = Arc::new(server_cfg);
+
+        self.cache
+            .insert(authority.clone(), Arc::clone(&server_cfg))
+            .await;
+
+        server_cfg
+    }
+
+    fn gen_cert(&self, authority: &Authority) -> rustls::Certificate {
+        let now = Utc::now();
+        let mut params = rcgen::CertificateParams::default();
+
+        {
+            let serial_number = Arc::clone(&self.serial_number);
+            let mut serial_number = serial_number.lock().unwrap();
+            params.serial_number = Some(*serial_number);
+            *serial_number += 1;
+        }
+
+        params.not_before = now - Duration::weeks(1);
+        params.not_after = now + Duration::weeks(52);
+        params
+            .subject_alt_names
+            .push(SanType::DnsName(authority.host().to_string()));
+        let mut distinguished_name = DistinguishedName::new();
+        distinguished_name.push(DnType::CommonName, authority.host());
+        params.distinguished_name = distinguished_name;
+
+        params.key_usages = vec![KeyUsagePurpose::DigitalSignature];
+        params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ServerAuth];
+
+        let key_pair = KeyPair::from_der(&self.private_key.0).expect("Failed to parse private key");
+        params.alg = key_pair
+            .compatible_algs()
+            .next()
+            .expect("Failed to find compatible algorithm");
+        params.key_pair = Some(key_pair);
+
+        let key_pair = KeyPair::from_der(&self.private_key.0).expect("Failed to parse private key");
+
+        let ca_cert_params = rcgen::CertificateParams::from_ca_cert_der(&self.ca_cert.0, key_pair)
+            .expect("Failed to parse CA certificate");
+        let ca_cert = rcgen::Certificate::from_params(ca_cert_params)
+            .expect("Failed to generate CA certificate");
+
+        let cert = rcgen::Certificate::from_params(params).expect("Failed to generate certificate");
+
+        rustls::Certificate(
+            cert.serialize_der_with_signer(&ca_cert)
+                .expect("Failed to serialize certificate"),
+        )
+    }
+
+    fn validate(&self) -> Result<(), RcgenError> {
+        let key_pair = rcgen::KeyPair::from_der(&self.private_key.0)?;
+        rcgen::CertificateParams::from_ca_cert_der(&self.ca_cert.0, key_pair)?;
+        Ok(())
+    }
+
+    pub fn get_cert(&self) -> String {
+        self.ca_cert_string.clone()
+    }
+}
+
+fn now_seconds() -> u64 {
+    let start = SystemTime::now();
+    let since_the_epoch = start
+        .duration_since(UNIX_EPOCH)
+        .expect("Time went backwards");
+    since_the_epoch.as_secs()
+}