use jevil::{
Error, Goldilocks4, Params, PublicKey, SecretKey, Signature, SignerCache, keygen, sign, verify,
};
use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
fn setup() -> (PublicKey, SecretKey, SignerCache, Params) {
let params = Params::new(3);
let mut rng = ChaCha20Rng::seed_from_u64(42);
let (pk, sk, cache) = keygen(&mut rng, params);
(pk, sk, cache, params)
}
#[test]
fn rejects_tampered_y() {
let (pk, sk, cache, params) = setup();
let mut sig = sign(&sk, &pk, &cache, params, b"hi");
sig.y_values[0] += Goldilocks4::ONE;
assert!(verify(&pk, params, b"hi", &sig).is_err());
}
#[test]
fn rejects_tampered_whir_proof_byte() {
let (pk, sk, cache, params) = setup();
let mut sig = sign(&sk, &pk, &cache, params, b"hi");
let mid = sig.whir_proof.len() / 2;
sig.whir_proof[mid] ^= 0x80;
assert!(verify(&pk, params, b"hi", &sig).is_err());
}
#[test]
fn rejects_wrong_root() {
let (mut pk, sk, cache, params) = setup();
let sig = sign(&sk, &pk, &cache, params, b"hi");
pk.root[0] ^= 1;
assert!(verify(&pk, params, b"hi", &sig).is_err());
}
#[test]
fn rejects_tampered_w() {
let (mut pk, sk, cache, params) = setup();
let sig = sign(&sk, &pk, &cache, params, b"hi");
pk.w += Goldilocks4::ONE;
assert!(verify(&pk, params, b"hi", &sig).is_err());
}
#[test]
fn rejects_wrong_msg() {
let (pk, sk, cache, params) = setup();
let sig = sign(&sk, &pk, &cache, params, b"a");
assert!(verify(&pk, params, b"b", &sig).is_err());
}
#[test]
fn rejects_wrong_n_star_in_params() {
let (pk, sk, cache, params) = setup();
let sig = sign(&sk, &pk, &cache, params, b"hi");
assert_eq!(params.n_star, 3);
let wrong = Params::new(7);
assert_eq!(verify(&pk, wrong, b"hi", &sig), Err(Error::ParamsMismatch));
}
#[test]
fn rejects_short_signature() {
let bytes = vec![0u8; 5];
assert_eq!(Signature::from_bytes(&bytes), Err(Error::InvalidLength));
}
#[test]
fn rejects_non_canonical_y() {
let k = Params::K as usize;
let mut bytes = vec![0u8; k * 32 + 1];
bytes[..8].copy_from_slice(&u64::MAX.to_le_bytes());
assert_eq!(Signature::from_bytes(&bytes), Err(Error::NonCanonicalField));
}
#[test]
fn rejects_oversized_opening_header() {
let (pk, sk, cache, params) = setup();
let mut sig = sign(&sk, &pk, &cache, params, b"dos");
for byte in sig.whir_proof.iter_mut() {
*byte = 0xff;
}
assert_eq!(
verify(&pk, params, b"dos", &sig),
Err(Error::VerificationFailed)
);
}