use crate::{Error, SignatureScheme, Vec}; use algebra::{ bytes::ToBytes, fields::{Field, PrimeField}, groups::Group, io::{Result as IoResult, Write}, to_bytes, One, ToConstraintField, UniformRand, Zero, }; use core::{hash::Hash, marker::PhantomData}; use digest::Digest; use rand::Rng; #[cfg(feature = "r1cs")] pub mod constraints; pub struct SchnorrSignature { _group: PhantomData, _hash: PhantomData, } #[derive(Derivative)] #[derivative(Clone(bound = "G: Group, H: Digest"))] pub struct SchnorrSigParameters { _hash: PhantomData, pub generator: G, pub salt: [u8; 32], } pub type SchnorrPublicKey = G; #[derive(Derivative)] #[derivative(Clone(bound = "G: Group"), Default(bound = "G: Group"))] pub struct SchnorrSecretKey(pub G::ScalarField); impl ToBytes for SchnorrSecretKey { #[inline] fn write(&self, writer: W) -> IoResult<()> { self.0.write(writer) } } #[derive(Derivative)] #[derivative(Clone(bound = "G: Group"), Default(bound = "G: Group"))] pub struct SchnorrSig { pub prover_response: G::ScalarField, pub verifier_challenge: G::ScalarField, } impl SignatureScheme for SchnorrSignature where G::ScalarField: PrimeField, { type Parameters = SchnorrSigParameters; type PublicKey = G; type SecretKey = SchnorrSecretKey; type Signature = SchnorrSig; fn setup(rng: &mut R) -> Result { let setup_time = start_timer!(|| "SchnorrSig::Setup"); let mut salt = [0u8; 32]; rng.fill_bytes(&mut salt); let generator = G::rand(rng); end_timer!(setup_time); Ok(SchnorrSigParameters { _hash: PhantomData, generator, salt, }) } fn keygen( parameters: &Self::Parameters, rng: &mut R, ) -> Result<(Self::PublicKey, Self::SecretKey), Error> { let keygen_time = start_timer!(|| "SchnorrSig::KeyGen"); let secret_key = G::ScalarField::rand(rng); let public_key = parameters.generator.mul(&secret_key); end_timer!(keygen_time); Ok((public_key, SchnorrSecretKey(secret_key))) } fn sign( parameters: &Self::Parameters, sk: &Self::SecretKey, message: &[u8], rng: &mut R, ) -> Result { let sign_time = start_timer!(|| "SchnorrSig::Sign"); // (k, e); let (random_scalar, verifier_challenge) = loop { // Sample a random scalar `k` from the prime scalar field. let random_scalar: G::ScalarField = G::ScalarField::rand(rng); // Commit to the random scalar via r := k ยท g. // This is the prover's first msg in the Sigma protocol. let prover_commitment: G = parameters.generator.mul(&random_scalar); // Hash everything to get verifier challenge. let mut hash_input = Vec::new(); hash_input.extend_from_slice(¶meters.salt); hash_input.extend_from_slice(&to_bytes![prover_commitment]?); hash_input.extend_from_slice(message); // Compute the supposed verifier response: e := H(salt || r || msg); if let Some(verifier_challenge) = G::ScalarField::from_random_bytes(&D::digest(&hash_input)) { break (random_scalar, verifier_challenge); }; }; // k - xe; let prover_response = random_scalar - &(verifier_challenge * &sk.0); let signature = SchnorrSig { prover_response, verifier_challenge, }; end_timer!(sign_time); Ok(signature) } fn verify( parameters: &Self::Parameters, pk: &Self::PublicKey, message: &[u8], signature: &Self::Signature, ) -> Result { let verify_time = start_timer!(|| "SchnorrSig::Verify"); let SchnorrSig { prover_response, verifier_challenge, } = signature; let mut claimed_prover_commitment = parameters.generator.mul(prover_response); let public_key_times_verifier_challenge = pk.mul(verifier_challenge); claimed_prover_commitment += &public_key_times_verifier_challenge; let mut hash_input = Vec::new(); hash_input.extend_from_slice(¶meters.salt); hash_input.extend_from_slice(&to_bytes![claimed_prover_commitment]?); hash_input.extend_from_slice(&message); let obtained_verifier_challenge = if let Some(obtained_verifier_challenge) = G::ScalarField::from_random_bytes(&D::digest(&hash_input)) { obtained_verifier_challenge } else { return Ok(false); }; end_timer!(verify_time); Ok(verifier_challenge == &obtained_verifier_challenge) } fn randomize_public_key( parameters: &Self::Parameters, public_key: &Self::PublicKey, randomness: &[u8], ) -> Result { let rand_pk_time = start_timer!(|| "SchnorrSig::RandomizePubKey"); let mut randomized_pk = *public_key; let mut base = parameters.generator; let mut encoded = G::zero(); for bit in bytes_to_bits(randomness) { if bit { encoded += &base; } base.double_in_place(); } randomized_pk += &encoded; end_timer!(rand_pk_time); Ok(randomized_pk) } fn randomize_signature( _parameter: &Self::Parameters, signature: &Self::Signature, randomness: &[u8], ) -> Result { let rand_signature_time = start_timer!(|| "SchnorrSig::RandomizeSig"); let SchnorrSig { prover_response, verifier_challenge, } = signature; let mut base = G::ScalarField::one(); let mut multiplier = G::ScalarField::zero(); for bit in bytes_to_bits(randomness) { if bit { multiplier += &base; } base.double_in_place(); } let new_sig = SchnorrSig { prover_response: *prover_response - &(*verifier_challenge * &multiplier), verifier_challenge: *verifier_challenge, }; end_timer!(rand_signature_time); Ok(new_sig) } } pub fn bytes_to_bits(bytes: &[u8]) -> Vec { let mut bits = Vec::with_capacity(bytes.len() * 8); for byte in bytes { for i in 0..8 { let bit = (*byte >> (8 - i - 1)) & 1; bits.push(bit == 1); } } bits } impl, D: Digest> ToConstraintField for SchnorrSigParameters { #[inline] fn to_field_elements(&self) -> Result, Error> { self.generator.to_field_elements() } }