signalscreen-checker 0.3.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
use signalscreen_checker::analyze;

#[test]
fn unsigned_file_grades_f() {
    let data = std::fs::read("fixtures/unsigned.exe").unwrap();
    let r = analyze("unsigned.exe", &data, 0).unwrap();
    assert_eq!(r.grade, 'F');
    assert!(!r.signature.present);
}

#[test]
fn selfsigned_no_timestamp_is_penalized() {
    let data = std::fs::read("fixtures/selfsigned-sha256.exe").unwrap();
    let r = analyze("selfsigned-sha256.exe", &data, 0).unwrap();
    assert!(r.signature.present);
    assert_eq!(r.signature.digest_algo, "SHA-256");
    // self-signed (-40) + no timestamp (-40) => 20 => F
    assert!(r.score <= 60, "score was {}", r.score);
    assert!(r.checks.iter().any(|c| c.id == "chain"));
    let cert = r.certificate.expect("cert summary");
    assert_eq!(cert.subject_o.as_deref(), Some("SignalScreen Test"));
}

#[test]
fn intact_signed_file_reports_a_verified_image_hash() {
    let data = std::fs::read("fixtures/selfsigned-sha256.exe").unwrap();
    let r = analyze("selfsigned-sha256.exe", &data, 0).unwrap();
    assert_eq!(r.signature.image_hash, "verified");
    // The signature check passes: what costs this file points is being self-signed
    // and untimestamped, not the signature failing to match the file.
    let sig = r.checks.iter().find(|c| c.id == "signature").unwrap();
    assert_eq!(format!("{:?}", sig.status), "Pass");
}

#[test]
fn tampered_signed_file_grades_f() {
    // Alter a byte in the Authenticode-hashed region (DOS header, loader-ignored):
    // the file still parses as a signed PE, but the bytes no longer match the
    // signed digest, so the signature is invalid — an outright F.
    let mut data = std::fs::read("fixtures/selfsigned-sha256.exe").unwrap();
    data[2] ^= 0xff;
    let r = analyze("tampered.exe", &data, 0).unwrap();
    assert_eq!(r.grade, 'F');
    assert_eq!(r.signature.image_hash, "mismatch");
    assert!(!r.signature.valid);
    let sig = r.checks.iter().find(|c| c.id == "signature").unwrap();
    assert_eq!(format!("{:?}", sig.status), "Fail");
}