1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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<Vec<CertificateDer<'static>>, std::io::Error> {
rustls_pemfile::certs(&mut pem.as_bytes()).collect()
}
fn schemes() -> Vec<SignatureScheme> {
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<HandshakeSignatureValid, Error> {
Ok(HandshakeSignatureValid::assertion())
}
fn verify_tls13_signature(&self, _: &[u8], _: &CertificateDer<'_>, _: &DigitallySignedStruct) -> Result<HandshakeSignatureValid, Error> {
Ok(HandshakeSignatureValid::assertion())
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
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<ServerCertVerified, Error> {
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!();
}
|