use crate::Error; use algebra_core::bytes::ToBytes; use core::hash::Hash; use rand::Rng; #[cfg(feature = "r1cs")] pub mod constraints; #[cfg(feature = "r1cs")] pub use constraints::*; pub mod schnorr; pub trait SignatureScheme { type Parameters: Clone + Send + Sync; type PublicKey: ToBytes + Hash + Eq + Clone + Default + Send + Sync; type SecretKey: ToBytes + Clone + Default; type Signature: Clone + Default + Send + Sync; fn setup(rng: &mut R) -> Result; fn keygen( pp: &Self::Parameters, rng: &mut R, ) -> Result<(Self::PublicKey, Self::SecretKey), Error>; fn sign( pp: &Self::Parameters, sk: &Self::SecretKey, message: &[u8], rng: &mut R, ) -> Result; fn verify( pp: &Self::Parameters, pk: &Self::PublicKey, message: &[u8], signature: &Self::Signature, ) -> Result; fn randomize_public_key( pp: &Self::Parameters, public_key: &Self::PublicKey, randomness: &[u8], ) -> Result; fn randomize_signature( pp: &Self::Parameters, signature: &Self::Signature, randomness: &[u8], ) -> Result; } #[cfg(test)] mod test { use crate::{signature::schnorr::SchnorrSignature, SignatureScheme}; use algebra::{ groups::Group, jubjub::JubJubAffine as JubJub, test_rng, to_bytes, ToBytes, UniformRand, }; use blake2::Blake2s; fn sign_and_verify(message: &[u8]) { let rng = &mut test_rng(); let parameters = S::setup::<_>(rng).unwrap(); let (pk, sk) = S::keygen(¶meters, rng).unwrap(); let sig = S::sign(¶meters, &sk, &message, rng).unwrap(); assert!(S::verify(¶meters, &pk, &message, &sig).unwrap()); } fn failed_verification(message: &[u8], bad_message: &[u8]) { let rng = &mut test_rng(); let parameters = S::setup::<_>(rng).unwrap(); let (pk, sk) = S::keygen(¶meters, rng).unwrap(); let sig = S::sign(¶meters, &sk, message, rng).unwrap(); assert!(!S::verify(¶meters, &pk, bad_message, &sig).unwrap()); } fn randomize_and_verify(message: &[u8], randomness: &[u8]) { let rng = &mut test_rng(); let parameters = S::setup::<_>(rng).unwrap(); let (pk, sk) = S::keygen(¶meters, rng).unwrap(); let sig = S::sign(¶meters, &sk, message, rng).unwrap(); assert!(S::verify(¶meters, &pk, message, &sig).unwrap()); let randomized_pk = S::randomize_public_key(¶meters, &pk, randomness).unwrap(); let randomized_sig = S::randomize_signature(¶meters, &sig, randomness).unwrap(); assert!(S::verify(¶meters, &randomized_pk, &message, &randomized_sig).unwrap()); } #[test] fn schnorr_signature_test() { let message = "Hi, I am a Schnorr signature!"; let rng = &mut test_rng(); sign_and_verify::>(message.as_bytes()); failed_verification::>( message.as_bytes(), "Bad message".as_bytes(), ); let random_scalar = to_bytes!(::ScalarField::rand(rng)).unwrap(); randomize_and_verify::>( message.as_bytes(), &random_scalar.as_slice(), ); } }