use rand_core::{RngCore, CryptoRng}; use ff::Field; use crate::{Curve, schnorr, algorithm::SchnorrSignature}; pub(crate) fn sign(rng: &mut R) { let private_key = C::F::random(&mut *rng); let nonce = C::F::random(&mut *rng); let challenge = C::F::random(rng); // Doesn't bother to craft an HRAM assert!( schnorr::verify::( C::generator_table() * private_key, challenge, &schnorr::sign(private_key, nonce, challenge) ) ); } // The above sign function verifies signing works // This verifies invalid signatures don't pass, using zero signatures, which should effectively be // random pub(crate) fn verify(rng: &mut R) { assert!( !schnorr::verify::( C::generator_table() * C::F::random(&mut *rng), C::F::random(rng), &SchnorrSignature { R: C::generator_table() * C::F::zero(), s: C::F::zero() } ) ); } pub(crate) fn batch_verify(rng: &mut R) { // Create 5 signatures let mut keys = vec![]; let mut challenges = vec![]; let mut sigs = vec![]; for i in 0 .. 5 { keys.push(C::F::random(&mut *rng)); challenges.push(C::F::random(&mut *rng)); sigs.push(schnorr::sign::(keys[i], C::F::random(&mut *rng), challenges[i])); } // Batch verify let triplets = (0 .. 5).map( |i| (u16::try_from(i + 1).unwrap(), C::generator_table() * keys[i], challenges[i], sigs[i]) ).collect::>(); schnorr::batch_verify(rng, &triplets).unwrap(); // Shift 1 from s from one to another and verify it fails // This test will fail if unique factors aren't used per-signature, hence its inclusion { let mut triplets = triplets.clone(); triplets[1].3.s += C::F::one(); triplets[2].3.s -= C::F::one(); if let Err(blame) = schnorr::batch_verify(rng, &triplets) { assert_eq!(blame, 2); } else { assert!(false); } } // Make sure a completely invalid signature fails when included for i in 0 .. 5 { let mut triplets = triplets.clone(); triplets[i].3.s = C::F::random(&mut *rng); if let Err(blame) = schnorr::batch_verify(rng, &triplets) { assert_eq!(blame, u16::try_from(i + 1).unwrap()); } else { assert!(false); } } }