use crate::*;
use proptest::prelude::*;
use rand_core::{CryptoRng, RngCore};
#[derive(Clone, Debug)]
pub struct SignatureCase<C: Ciphersuite> {
msg: Vec<u8>,
sig: Signature<C>,
vk: VerifyingKey<C>,
invalid_vk: VerifyingKey<C>,
is_valid: bool,
}
#[derive(Copy, Clone, Debug)]
pub enum Tweak {
None,
ChangeMessage,
ChangePubkey,
}
impl<C> SignatureCase<C>
where
C: Ciphersuite,
{
pub fn new<R: RngCore + CryptoRng>(mut rng: R, msg: Vec<u8>) -> Self {
let sk = SigningKey::<C>::new(&mut rng);
let sig = sk.sign(&mut rng, &msg);
let vk = VerifyingKey::<C>::from(&sk);
let invalid_vk = VerifyingKey::<C>::from(&SigningKey::new(&mut rng));
Self {
msg,
sig,
vk,
invalid_vk,
is_valid: true,
}
}
pub fn check(&self) -> bool {
let _sig = {
let bytes = self.sig.serialize().unwrap();
Signature::<C>::deserialize(&bytes)
};
let _pub_key = VerifyingKey::<C>::deserialize(&self.vk.serialize().unwrap())
.expect("The test verification key to be well-formed.");
self.is_valid == self.vk.verify(&self.msg, &self.sig).is_ok()
}
pub fn apply_tweak(&mut self, tweak: &Tweak) {
match tweak {
Tweak::None => {}
Tweak::ChangeMessage => {
self.msg.push(90);
self.is_valid = false;
}
Tweak::ChangePubkey => {
self.vk = self.invalid_vk;
self.is_valid = false;
}
}
}
}
pub fn tweak_strategy() -> impl Strategy<Value = Tweak> {
prop_oneof![
10 => Just(Tweak::None),
1 => Just(Tweak::ChangeMessage),
1 => Just(Tweak::ChangePubkey),
]
}