use rand_core::{RngCore, CryptoRng}; use ff::Field; use group::Group; use multiexp::BatchVerifier; use crate::Curve; #[allow(non_snake_case)] #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct SchnorrSignature { pub R: C::G, pub s: C::F, } impl SchnorrSignature { pub fn serialize(&self) -> Vec { let mut res = Vec::with_capacity(C::G_len() + C::F_len()); res.extend(C::G_to_bytes(&self.R)); res.extend(C::F_to_bytes(&self.s)); res } } pub(crate) fn sign( private_key: C::F, nonce: C::F, challenge: C::F ) -> SchnorrSignature { SchnorrSignature { R: C::generator_table() * nonce, s: nonce + (private_key * challenge) } } pub(crate) fn verify( public_key: C::G, challenge: C::F, signature: &SchnorrSignature ) -> bool { (C::generator_table() * signature.s) == (signature.R + (public_key * challenge)) } pub(crate) fn batch_verify( rng: &mut R, triplets: &[(u16, C::G, C::F, SchnorrSignature)] ) -> Result<(), u16> { let mut values = [(C::F::one(), C::G::generator()); 3]; let mut batch = BatchVerifier::new(triplets.len(), C::little_endian()); for triple in triplets { // s = r + ca // sG == R + cA // R + cA - sG == 0 // R values[0].1 = triple.3.R; // cA values[1] = (triple.2, triple.1); // -sG values[2].0 = -triple.3.s; batch.queue(rng, triple.0, values); } batch.verify_vartime_with_vartime_blame() }