From 1951b063d7ec6d6e8db8a0b5074c73f887749208 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 29 Dec 2025 22:18:04 +0800 Subject: initial commit --- packet-detector/src/tls_util.rs | 73 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 packet-detector/src/tls_util.rs (limited to 'packet-detector/src/tls_util.rs') diff --git a/packet-detector/src/tls_util.rs b/packet-detector/src/tls_util.rs new file mode 100644 index 0000000..456991b --- /dev/null +++ b/packet-detector/src/tls_util.rs @@ -0,0 +1,73 @@ +use rcgen::{DistinguishedName, DnType}; +use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; +use rustls::pki_types::{CertificateDer, ServerName, UnixTime}; +use rustls::{DigitallySignedStruct, Error, SignatureScheme}; +use sha2::{Digest, Sha256}; +use x509_parser::prelude::*; + +/// SHA256 fingerprint (truncated to 16 bytes by default) +pub fn fingerprint(cert: &CertificateDer<'_>, full: bool) -> String { + let hash = Sha256::digest(cert.as_ref()); + if full { hex::encode(hash) } else { hex::encode(&hash[..16]) } +} + +pub fn dn(cn: &str, org: &str) -> DistinguishedName { + let mut d = DistinguishedName::new(); + d.push(DnType::CommonName, cn); + d.push(DnType::OrganizationName, org); + d.push(DnType::CountryName, "US"); + d +} + +/// Parse certs from PEM +pub fn parse_pem(pem: &str) -> Result>, std::io::Error> { + rustls_pemfile::certs(&mut pem.as_bytes()).collect() +} + +fn schemes() -> Vec { + rustls::crypto::ring::default_provider() + .signature_verification_algorithms + .supported_schemes() +} + +/// Macro to implement the boilerplate verifier methods +macro_rules! impl_verifier_base { + () => { + fn verify_tls12_signature(&self, _: &[u8], _: &CertificateDer<'_>, _: &DigitallySignedStruct) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + fn verify_tls13_signature(&self, _: &[u8], _: &CertificateDer<'_>, _: &DigitallySignedStruct) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + fn supported_verify_schemes(&self) -> Vec { + schemes() + } + }; +} + +/// Accepts all certificates, logs info +#[derive(Debug)] +pub struct LoggingVerifier; + +impl ServerCertVerifier for LoggingVerifier { + fn verify_server_cert(&self, cert: &CertificateDer<'_>, intermediates: &[CertificateDer<'_>], _: &ServerName<'_>, _: &[u8], _: UnixTime) -> Result { + println!("\n=== Server Certificate ==="); + match X509Certificate::from_der(cert.as_ref()) { + Ok((_, x)) => { + println!("Subject: {}", x.subject()); + println!("Issuer: {}", x.issuer()); + println!("SHA256: {}", fingerprint(cert, true)); + if x.subject() == x.issuer() { println!("Type: Self-Signed"); } + } + Err(e) => println!("Parse failed: {}", e), + } + for (i, c) in intermediates.iter().enumerate() { + if let Ok((_, x)) = X509Certificate::from_der(c.as_ref()) { + println!("Intermediate #{}: {}", i + 1, x.subject()); + } + } + println!("Chain length: {}\n", 1 + intermediates.len()); + Ok(ServerCertVerified::assertion()) + } + impl_verifier_base!(); +} -- cgit v1.2.3