#![allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::indexing_slicing,
clippy::panic
)]
use dsse::{Envelope, Error};
fn parse(json: &str) -> Result<Envelope, Error> {
Envelope::from_json(json.as_bytes())
}
#[test]
fn envelope_with_no_signatures_is_refused() {
let env = parse(r#"{"payload":"eA==","payloadType":"t","signatures":[]}"#).unwrap();
let err = dsse::verify(&env, &[], 1).unwrap_err();
assert_eq!(err, Error::NoSignatures, "got {err:?}");
}
#[test]
fn payload_with_non_zero_trailing_bits_is_refused() {
let env =
parse(r#"{"payload":"eB==","payloadType":"t","signatures":[{"sig":"AAAA"}]}"#).unwrap();
let err = dsse::verify(&env, &[], 1).unwrap_err();
assert_eq!(
err,
Error::NonCanonicalBase64 { field: "payload" },
"got {err:?}"
);
}
#[test]
fn signature_with_non_zero_trailing_bits_is_refused() {
let env =
parse(r#"{"payload":"eA==","payloadType":"t","signatures":[{"sig":"eB=="}]}"#).unwrap();
let err = dsse::verify(&env, &[], 1).unwrap_err();
assert_eq!(
err,
Error::NonCanonicalBase64 {
field: "signatures[].sig"
},
"got {err:?}"
);
}
#[test]
fn unpadded_payload_is_refused() {
let env = parse(r#"{"payload":"eA","payloadType":"t","signatures":[{"sig":"AAAA"}]}"#).unwrap();
let err = dsse::verify(&env, &[], 1).unwrap_err();
assert_eq!(err, Error::NonCanonicalBase64 { field: "payload" });
}
#[test]
fn payload_mixing_both_alphabets_is_refused() {
let env =
parse(r#"{"payload":"a-b+cd==","payloadType":"t","signatures":[{"sig":"AAAA"}]}"#).unwrap();
let err = dsse::verify(&env, &[], 1).unwrap_err();
assert_eq!(err, Error::NonCanonicalBase64 { field: "payload" });
}
#[test]
fn both_alphabets_are_accepted_when_canonical() {
for (label, encoded) in [("standard", "+w=="), ("url-safe", "-w==")] {
let json = format!(
r#"{{"payload":"{encoded}","payloadType":"t","signatures":[{{"sig":"AAAA"}}]}}"#
);
let env = parse(&json).unwrap();
let err = dsse::verify(&env, &[], 1).unwrap_err();
assert_eq!(
err,
Error::ThresholdNotMet {
accepted: 0,
threshold: 1
},
"{label} alphabet must decode, then fail only on the threshold; got {err:?}"
);
}
}
#[test]
fn zero_threshold_is_refused() {
let env =
parse(r#"{"payload":"eA==","payloadType":"t","signatures":[{"sig":"AAAA"}]}"#).unwrap();
let err = dsse::verify(&env, &[], 0).unwrap_err();
assert_eq!(err, Error::ZeroThreshold, "got {err:?}");
}
#[test]
fn missing_required_members_are_refused() {
for json in [
r#"{"payloadType":"t","signatures":[{"sig":"AAAA"}]}"#,
r#"{"payload":"eA==","signatures":[{"sig":"AAAA"}]}"#,
r#"{"payload":"eA==","payloadType":"t"}"#,
r#"{"payload":"eA==","payloadType":"t","signatures":[{"keyid":"k"}]}"#,
] {
let err = parse(json).unwrap_err();
assert!(
matches!(err, Error::MalformedEnvelope(_)),
"{json} should be malformed, got {err:?}"
);
}
}
#[test]
fn empty_payload_is_legal() {
let env = parse(r#"{"payload":"","payloadType":"t","signatures":[{"sig":"AAAA"}]}"#).unwrap();
let err = dsse::verify(&env, &[], 1).unwrap_err();
assert_eq!(
err,
Error::ThresholdNotMet {
accepted: 0,
threshold: 1
},
"an empty payload must decode cleanly; got {err:?}"
);
}