signalscreen-checker 0.2.0

Windows code-signing hygiene checker. Reads the Authenticode signature in a PE file and grades it A-F. Pure Rust, no Windows dependency.
Documentation
// Pins the real authenticode 0.4.3 API against a known signed PE before we
// write typed modules. Run: cargo run --example explore -- <file>
use authenticode::AttributeCertificateIterator;
use object::read::pe::PeFile64;

fn main() {
    let path = std::env::args().nth(1).expect("usage: explore <file>");
    let data = std::fs::read(&path).unwrap();
    let pe = PeFile64::parse(&*data).expect("parse PE");

    match AttributeCertificateIterator::new(&pe).expect("cert table iterator") {
        None => println!("UNSIGNED: no attribute certificate table"),
        Some(iter) => {
            for cert in iter {
                let cert = cert.expect("attribute certificate");
                let sig = cert
                    .get_authenticode_signature()
                    .expect("authenticode signature");
                let si = sig.signer_info();
                println!("digest_alg.oid    = {}", si.digest_alg.oid);
                match si.unsigned_attrs.as_ref() {
                    Some(ua) => {
                        for a in ua.iter() {
                            println!("unsigned_attr.oid = {}", a.oid);
                        }
                    }
                    None => println!("unsigned_attrs    = none"),
                }
                println!("cert count        = {}", sig.certificates().count());
                // The signer (leaf) cert is identified by SignerInfo.sid, NOT by
                // position in certificates() (that bundle includes CA certs).
                use cms::signed_data::SignerIdentifier;
                let leaf = match &si.sid {
                    SignerIdentifier::IssuerAndSerialNumber(isn) => sig.certificates().find(|c| {
                        c.tbs_certificate.issuer == isn.issuer
                            && c.tbs_certificate.serial_number == isn.serial_number
                    }),
                    SignerIdentifier::SubjectKeyIdentifier(_) => None,
                };
                match leaf {
                    Some(c) => {
                        println!("LEAF subject      = {}", c.tbs_certificate.subject);
                        println!("LEAF issuer       = {}", c.tbs_certificate.issuer);
                        println!(
                            "LEAF not_after    = {}",
                            c.tbs_certificate.validity.not_after
                        );
                    }
                    None => println!("LEAF              = not found by sid"),
                }
            }
        }
    }
}