From d45473b2bdfb68f44988f46ab0f130408a3eb717 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Wed, 25 May 2022 00:57:00 -0400 Subject: [PATCH] Add a test for batch verification --- crypto/frost/src/tests/curve.rs | 2 ++ crypto/frost/src/tests/literal/schnorr.rs | 2 +- crypto/frost/src/tests/schnorr.rs | 40 +++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/crypto/frost/src/tests/curve.rs b/crypto/frost/src/tests/curve.rs index 9560ac21..ab83a0d9 100644 --- a/crypto/frost/src/tests/curve.rs +++ b/crypto/frost/src/tests/curve.rs @@ -22,6 +22,8 @@ pub fn test_curve(rng: &mut R) { // TODO: Test the Curve functions themselves // Test Schnorr signatures work as expected + // This is a bit unnecessary, as they should for any valid curve, yet this provides tests with + // meaning, which the above tests won't have sign::<_, C>(rng); verify::<_, C>(rng); batch_verify::<_, C>(rng); diff --git a/crypto/frost/src/tests/literal/schnorr.rs b/crypto/frost/src/tests/literal/schnorr.rs index d9d1eacc..1ceac748 100644 --- a/crypto/frost/src/tests/literal/schnorr.rs +++ b/crypto/frost/src/tests/literal/schnorr.rs @@ -4,7 +4,7 @@ use rand::rngs::OsRng; use crate::{ Curve, schnorr, algorithm::{Hram, Schnorr}, - tests::{key_gen, algorithm_machines, sign as sign_test, actual::secp256k1::{Secp256k1, TestHram}} + tests::{key_gen, algorithm_machines, sign as sign_test, literal::secp256k1::{Secp256k1, TestHram}} }; const MESSAGE: &[u8] = b"Hello World"; diff --git a/crypto/frost/src/tests/schnorr.rs b/crypto/frost/src/tests/schnorr.rs index 15bdaa48..617cd549 100644 --- a/crypto/frost/src/tests/schnorr.rs +++ b/crypto/frost/src/tests/schnorr.rs @@ -30,3 +30,43 @@ pub(crate) fn verify(rng: &mut R) { ); } +pub(crate) fn batch_verify(rng: &mut R) { + // Create 3 signatures + let mut keys = vec![]; + let mut challenges = vec![]; + let mut sigs = vec![]; + for i in 0 .. 3 { + 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 mut triplets = (0 .. 3).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); + } + } + // Sanity + schnorr::batch_verify(rng, &triplets).unwrap(); + + // Make sure a completely invalid signature fails when included + triplets[0].3.s = C::F::random(&mut *rng); + if let Err(blame) = schnorr::batch_verify(rng, &triplets) { + assert_eq!(blame, 1); + } else { + assert!(false); + } +}