provenance/tests/maven_pgp.rs
//! Real Maven Central OpenPGP signatures, verified OFFLINE against pinned keys.
//!
//! Fetched once on the online side (2026-10-24) from `https://repo1.maven.org/maven2`:
//!
//! * `maven/guava-33.3.1-jre.pom` and its `.asc`
//! (`com/google/guava/guava/33.3.1-jre/`), an RSA 2048 signature over SHA-512 by
//! `BDB5FA4FE719D787FB3D3197F6D4A1D411E9D1AE`; the key file is that key from
//! `keys.openpgp.org`;
//! * `maven/slf4j-api-2.0.16.pom` and its `.asc` (`org/slf4j/slf4j-api/2.0.16/`), an
//! ECDSA P-521 signature by `60200AC4AE761F1614D6C46766D68DAA073BE985`; the key
//! file is from `keys.openpgp.org`.
//!
//! Both keys were exported with `gpg --export-options export-minimal`, then their
//! User ID packets and the certifications over them were stripped, so no e-mail
//! address is committed: the primary key, the subkey and its binding signature
//! remain. GnuPG 2.4 said "Good signature" for both pairs before they were committed.
//! Both POMs name no e-mail address either.
//!
//! The verifier is opt-in (T9b): this file needs holger-provenance's `pgp` feature. It
//! runs in the workspace run, in `cargo xtask suite-check` (`trust:maven-pgp`) and as the
//! `maven_pgp` arm of `.nornir/testmatrix-arms.json`. What a build WITHOUT the feature
//! does with the same pins is `tests/pgp_build_feature.rs`.
#![cfg(feature = "pgp")]
use holger_provenance::pgp::{verify_detached, PgpKey};
use holger_provenance::{
check_tightens, effective, verify_artifact, EffectivePolicy, KeyAlg, ProvenanceFloor,
ProvenanceGate, SignerInfo, TrustRoot, TrustedKey, Verdict,
};
const FX: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/maven");
const POVIRK: &str = "povirk-BDB5FA4FE719D787FB3D3197F6D4A1D411E9D1AE.asc";
const CEKI: &str = "ceki-60200AC4AE761F1614D6C46766D68DAA073BE985.asc";
const POVIRK_FPR: &str = "bdb5fa4fe719d787fb3d3197f6d4a1d411e9d1ae";
const CEKI_FPR: &str = "60200ac4ae761f1614d6c46766d68daa073be985";
const GUAVA: &str = "guava-33.3.1-jre.pom";
const SLF4J: &str = "slf4j-api-2.0.16.pom";
fn read(f: &str) -> Vec<u8> {
std::fs::read(format!("{FX}/{f}")).unwrap_or_else(|e| panic!("{f}: {e}"))
}
fn key(f: &str) -> PgpKey {
PgpKey::from_armored(f, &read(f)).unwrap()
}
/// A trust root that pins only these PGP keys (by their file names).
fn trust(keys: &[&str]) -> TrustRoot {
let k: Vec<(String, Vec<u8>)> = keys.iter().map(|f| (f.to_string(), read(f))).collect();
TrustRoot::default().with_pgp_keys(&k).unwrap()
}
fn require() -> EffectivePolicy {
effective(
&ProvenanceFloor {
require_signed: true,
require_provenance: true,
..Default::default()
},
&ProvenanceGate::Off,
)
}
fn run(
artifact: &str,
asc: &str,
policy: &EffectivePolicy,
trust: &TrustRoot,
) -> holger_provenance::ProvenanceReport {
verify_artifact(
&read(artifact),
&[(asc.to_string(), read(asc))],
policy,
Some(trust),
)
}
fn gate_pgp(keys: &[&str]) -> ProvenanceGate {
ProvenanceGate::Require {
identity: None,
identities: vec![],
builders: vec![],
keys: vec![],
apk_keys: vec![],
pgp_keys: keys.iter().map(|s| s.to_string()).collect(),
slsa_min: None,
}
}
#[test]
fn the_pinned_keys_load_with_their_fingerprints() {
let g = key(POVIRK);
assert_eq!(g.name, POVIRK);
assert_eq!(g.fingerprint, POVIRK_FPR);
assert_eq!(key(CEKI).fingerprint, CEKI_FPR);
assert!(PgpKey::from_armored(
"junk",
b"-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nnope\n-----END PGP PUBLIC KEY BLOCK-----\n"
)
.is_err());
// A signature is not a key.
assert!(PgpKey::from_armored("sig", &read(&format!("{GUAVA}.asc"))).is_err());
}
#[test]
fn guava_rsa_sha512_verifies_with_the_pinned_key() {
let v = verify_detached(
&read(GUAVA),
&read(&format!("{GUAVA}.asc")),
&[key(CEKI), key(POVIRK)],
)
.unwrap();
assert_eq!(v.key, POVIRK);
assert_eq!(v.fingerprint, POVIRK_FPR);
assert!(v.alg.starts_with("rsa"), "{}", v.alg);
let r = run(
GUAVA,
&format!("{GUAVA}.asc"),
&require(),
&trust(&[POVIRK]),
);
assert_eq!(r.verdict, Verdict::Pass, "{r:#?}");
let c = r.verified_provenance().next().unwrap();
assert_eq!(c.origin, format!("pgp-signature:{GUAVA}.asc"));
assert_eq!(
c.builder_id.as_deref(),
Some(format!("pgp-key:{POVIRK}").as_str())
);
assert!(matches!(&c.signer, Some(SignerInfo::Key { id, .. }) if id == POVIRK));
}
#[test]
fn slf4j_ecdsa_p521_verifies_with_the_pinned_key() {
let v = verify_detached(&read(SLF4J), &read(&format!("{SLF4J}.asc")), &[key(CEKI)]).unwrap();
assert_eq!(v.fingerprint, CEKI_FPR);
assert!(v.alg.starts_with("ecdsa"), "{}", v.alg);
let r = run(
SLF4J,
&format!("{SLF4J}.asc"),
&require(),
&trust(&[CEKI, POVIRK]),
);
assert_eq!(r.verdict, Verdict::Pass, "{r:#?}");
}
#[test]
fn an_unknown_key_is_unverified_never_a_pass() {
// The signer's key is not pinned: refused under require, warned under prefer.
let e =
verify_detached(&read(GUAVA), &read(&format!("{GUAVA}.asc")), &[key(CEKI)]).unwrap_err();
assert_eq!(e.code_str(), "holger-provenance-4", "{e}");
assert!(
e.to_string().contains("unverified") && e.to_string().contains(&POVIRK_FPR.to_uppercase()),
"{e}"
);
let r = run(GUAVA, &format!("{GUAVA}.asc"), &require(), &trust(&[CEKI]));
assert_eq!(r.verdict, Verdict::Block, "{r:#?}");
assert_eq!(r.code.as_deref(), Some("holger-provenance-4"));
let prefer = effective(&ProvenanceFloor::default(), &ProvenanceGate::Prefer);
let r = run(GUAVA, &format!("{GUAVA}.asc"), &prefer, &trust(&[CEKI]));
assert_eq!(r.verdict, Verdict::Warn, "{r:#?}");
assert!(r.candidates.iter().all(|c| !c.verified));
// No PGP key pinned at all, and no trust root at all.
let r = run(
GUAVA,
&format!("{GUAVA}.asc"),
&require(),
&TrustRoot::default(),
);
assert_eq!(
(r.verdict, r.code.as_deref()),
(Verdict::Block, Some("holger-provenance-4")),
"{r:#?}"
);
let r = verify_artifact(
&read(GUAVA),
&[(format!("{GUAVA}.asc"), read(&format!("{GUAVA}.asc")))],
&require(),
None,
);
assert_eq!(
(r.verdict, r.code.as_deref()),
(Verdict::Block, Some("holger-provenance-4")),
"{r:#?}"
);
}
#[test]
fn a_changed_byte_or_another_file_fails_the_signature() {
let mut pom = read(GUAVA);
let at = pom.len() / 2;
pom[at] ^= 1;
let e = verify_detached(&pom, &read(&format!("{GUAVA}.asc")), &[key(POVIRK)]).unwrap_err();
assert_eq!(e.code_str(), "holger-provenance-3", "{e}");
// slf4j's signature against guava's bytes, both keys pinned.
let r = run(
GUAVA,
&format!("{SLF4J}.asc"),
&require(),
&trust(&[CEKI, POVIRK]),
);
assert_eq!(
(r.verdict, r.code.as_deref()),
(Verdict::Block, Some("holger-provenance-3")),
"{r:#?}"
);
}
#[test]
fn require_pgp_keys_narrows_the_pinned_keys_per_source() {
let floor = ProvenanceFloor::default();
let gate = gate_pgp(&[CEKI]);
check_tightens(&floor, &gate, "central").unwrap();
let policy = effective(&floor, &gate);
assert_eq!(policy.pgp_keys, vec![CEKI.to_string()]);
// Both keys pinned in the bundle, but this source allows only Ceki's.
let r = run(
GUAVA,
&format!("{GUAVA}.asc"),
&policy,
&trust(&[CEKI, POVIRK]),
);
assert_eq!(
(r.verdict, r.code.as_deref()),
(Verdict::Block, Some("holger-provenance-4")),
"{r:#?}"
);
let r = run(
SLF4J,
&format!("{SLF4J}.asc"),
&policy,
&trust(&[CEKI, POVIRK]),
);
assert_eq!(r.verdict, Verdict::Pass, "{r:#?}");
// A source that demands an SLSA level cannot be satisfied by a bare signature.
let mut slsa = gate_pgp(&[POVIRK]);
if let ProvenanceGate::Require { slsa_min, .. } = &mut slsa {
*slsa_min = Some(1);
}
let r = run(
GUAVA,
&format!("{GUAVA}.asc"),
&effective(&floor, &slsa),
&trust(&[POVIRK]),
);
assert_eq!(
(r.verdict, r.code.as_deref()),
(Verdict::Block, Some("holger-provenance-7")),
"{r:#?}"
);
}
#[test]
fn the_ron_writes_require_pgp_keys() {
let gate: ProvenanceGate =
ron::from_str(&format!(r#"require(pgp_keys: ["{POVIRK}"])"#)).unwrap();
assert_eq!(gate, gate_pgp(&[POVIRK]));
assert!(
ron::from_str::<ProvenanceGate>(r#"require(pgp_key: ["x"])"#).is_err(),
"a typo is refused by name"
);
}
#[test]
fn a_floor_key_of_alg_openpgp_is_a_pinned_pgp_key() {
let armored = String::from_utf8(read(POVIRK)).unwrap();
let floor = ProvenanceFloor {
keys: vec![TrustedKey {
id: "guava-release".into(),
alg: KeyAlg::Openpgp,
public_key: armored,
}],
..Default::default()
};
let gate = ProvenanceGate::Require {
identity: None,
identities: vec![],
builders: vec![],
keys: vec!["guava-release".into()],
apk_keys: vec![],
pgp_keys: vec![],
slsa_min: None,
};
check_tightens(&floor, &gate, "central").unwrap();
let r = run(
GUAVA,
&format!("{GUAVA}.asc"),
&effective(&floor, &gate),
&TrustRoot::default(),
);
assert_eq!(r.verdict, Verdict::Pass, "{r:#?}");
assert!(
matches!(&r.candidates[0].signer, Some(SignerInfo::Key { id, .. }) if id == "guava-release")
);
// A floor key that is not an OpenPGP key refuses the policy by name.
let bad = ProvenanceFloor {
keys: vec![TrustedKey {
id: "x".into(),
alg: KeyAlg::Openpgp,
public_key: "not a key".into(),
}],
..Default::default()
};
let e = check_tightens(&bad, &ProvenanceGate::Off, "central").unwrap_err();
assert_eq!(e.code_str(), "holger-provenance-11", "{e}");
}