arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/crypto-primitives/src/signature/schnorr/mod.rs
crypto-primitives/src/signature/schnorr/mod.rsRaw
  1use crate::{Error, SignatureScheme, Vec};
  2use algebra_core::{
  3    bytes::ToBytes,
  4    fields::{Field, PrimeField},
  5    io::{Result as IoResult, Write},
  6    to_bytes, AffineCurve, One, ProjectiveCurve, ToConstraintField, UniformRand, Zero,
  7};
  8use core::{hash::Hash, marker::PhantomData};
  9use digest::Digest;
 10use rand::Rng;
 11
 12#[cfg(feature = "r1cs")]
 13pub mod constraints;
 14
 15pub struct Schnorr<C: ProjectiveCurve, D: Digest> {
 16    _group: PhantomData<C>,
 17    _hash: PhantomData<D>,
 18}
 19
 20#[derive(Derivative)]
 21#[derivative(Clone(bound = "C: ProjectiveCurve, H: Digest"), Debug)]
 22pub struct Parameters<C: ProjectiveCurve, H: Digest> {
 23    _hash: PhantomData<H>,
 24    pub generator: C::Affine,
 25    pub salt: [u8; 32],
 26}
 27
 28pub type PublicKey<C> = <C as ProjectiveCurve>::Affine;
 29
 30#[derive(Clone, Default, Debug)]
 31pub struct SecretKey<C: ProjectiveCurve>(pub C::ScalarField);
 32
 33impl<C: ProjectiveCurve> ToBytes for SecretKey<C> {
 34    #[inline]
 35    fn write<W: Write>(&self, writer: W) -> IoResult<()> {
 36        self.0.write(writer)
 37    }
 38}
 39
 40#[derive(Clone, Default, Debug)]
 41pub struct Signature<C: ProjectiveCurve> {
 42    pub prover_response: C::ScalarField,
 43    pub verifier_challenge: C::ScalarField,
 44}
 45
 46impl<C: ProjectiveCurve + Hash, D: Digest + Send + Sync> SignatureScheme for Schnorr<C, D>
 47where
 48    C::ScalarField: PrimeField,
 49{
 50    type Parameters = Parameters<C, D>;
 51    type PublicKey = PublicKey<C>;
 52    type SecretKey = SecretKey<C>;
 53    type Signature = Signature<C>;
 54
 55    fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
 56        let setup_time = start_timer!(|| "SchnorrSig::Setup");
 57
 58        let mut salt = [0u8; 32];
 59        rng.fill_bytes(&mut salt);
 60        let generator = C::rand(rng).into();
 61
 62        end_timer!(setup_time);
 63        Ok(Parameters {
 64            _hash: PhantomData,
 65            generator,
 66            salt,
 67        })
 68    }
 69
 70    fn keygen<R: Rng>(
 71        parameters: &Self::Parameters,
 72        rng: &mut R,
 73    ) -> Result<(Self::PublicKey, Self::SecretKey), Error> {
 74        let keygen_time = start_timer!(|| "SchnorrSig::KeyGen");
 75
 76        let secret_key = C::ScalarField::rand(rng);
 77        let public_key = parameters.generator.mul(secret_key).into();
 78
 79        end_timer!(keygen_time);
 80        Ok((public_key, SecretKey(secret_key)))
 81    }
 82
 83    fn sign<R: Rng>(
 84        parameters: &Self::Parameters,
 85        sk: &Self::SecretKey,
 86        message: &[u8],
 87        rng: &mut R,
 88    ) -> Result<Self::Signature, Error> {
 89        let sign_time = start_timer!(|| "SchnorrSig::Sign");
 90        // (k, e);
 91        let (random_scalar, verifier_challenge) = loop {
 92            // Sample a random scalar `k` from the prime scalar field.
 93            let random_scalar: C::ScalarField = C::ScalarField::rand(rng);
 94            // Commit to the random scalar via r := k · G.
 95            // This is the prover's first msg in the Sigma protocol.
 96            let prover_commitment = parameters.generator.mul(random_scalar).into_affine();
 97
 98            // Hash everything to get verifier challenge.
 99            let mut hash_input = Vec::new();
100            hash_input.extend_from_slice(&parameters.salt);
101            hash_input.extend_from_slice(&to_bytes![prover_commitment]?);
102            hash_input.extend_from_slice(message);
103
104            // Compute the supposed verifier response: e := H(salt || r || msg);
105            if let Some(verifier_challenge) =
106                C::ScalarField::from_random_bytes(&D::digest(&hash_input))
107            {
108                break (random_scalar, verifier_challenge);
109            };
110        };
111
112        // k - xe;
113        let prover_response = random_scalar - &(verifier_challenge * &sk.0);
114        let signature = Signature {
115            prover_response,
116            verifier_challenge,
117        };
118
119        end_timer!(sign_time);
120        Ok(signature)
121    }
122
123    fn verify(
124        parameters: &Self::Parameters,
125        pk: &Self::PublicKey,
126        message: &[u8],
127        signature: &Self::Signature,
128    ) -> Result<bool, Error> {
129        let verify_time = start_timer!(|| "SchnorrSig::Verify");
130
131        let Signature {
132            prover_response,
133            verifier_challenge,
134        } = signature;
135        let mut claimed_prover_commitment = parameters.generator.mul(*prover_response);
136        let public_key_times_verifier_challenge = pk.mul(*verifier_challenge);
137        claimed_prover_commitment += &public_key_times_verifier_challenge;
138        let claimed_prover_commitment = claimed_prover_commitment.into_affine();
139
140        let mut hash_input = Vec::new();
141        hash_input.extend_from_slice(&parameters.salt);
142        hash_input.extend_from_slice(&to_bytes![claimed_prover_commitment]?);
143        hash_input.extend_from_slice(&message);
144
145        let obtained_verifier_challenge = if let Some(obtained_verifier_challenge) =
146            C::ScalarField::from_random_bytes(&D::digest(&hash_input))
147        {
148            obtained_verifier_challenge
149        } else {
150            return Ok(false);
151        };
152        end_timer!(verify_time);
153        Ok(verifier_challenge == &obtained_verifier_challenge)
154    }
155
156    fn randomize_public_key(
157        parameters: &Self::Parameters,
158        public_key: &Self::PublicKey,
159        randomness: &[u8],
160    ) -> Result<Self::PublicKey, Error> {
161        let rand_pk_time = start_timer!(|| "SchnorrSig::RandomizePubKey");
162
163        let randomized_pk = *public_key;
164        let base = parameters.generator;
165        let mut encoded = C::zero();
166        for bit in bytes_to_bits(randomness)
167            .into_iter()
168            .rev()
169            .skip_while(|b| !b)
170        {
171            encoded.double_in_place();
172            if bit {
173                encoded.add_assign_mixed(&base)
174            }
175        }
176        encoded.add_assign_mixed(&randomized_pk);
177
178        end_timer!(rand_pk_time);
179
180        Ok(encoded.into())
181    }
182
183    fn randomize_signature(
184        _parameter: &Self::Parameters,
185        signature: &Self::Signature,
186        randomness: &[u8],
187    ) -> Result<Self::Signature, Error> {
188        let rand_signature_time = start_timer!(|| "SchnorrSig::RandomizeSig");
189        let Signature {
190            prover_response,
191            verifier_challenge,
192        } = signature;
193        let mut base = C::ScalarField::one();
194        let mut multiplier = C::ScalarField::zero();
195        for bit in bytes_to_bits(randomness) {
196            if bit {
197                multiplier += &base;
198            }
199            base.double_in_place();
200        }
201
202        let new_sig = Signature {
203            prover_response: *prover_response - &(*verifier_challenge * &multiplier),
204            verifier_challenge: *verifier_challenge,
205        };
206        end_timer!(rand_signature_time);
207        Ok(new_sig)
208    }
209}
210
211pub fn bytes_to_bits(bytes: &[u8]) -> Vec<bool> {
212    let mut bits = Vec::with_capacity(bytes.len() * 8);
213    for byte in bytes {
214        for i in 0..8 {
215            let bit = (*byte >> (8 - i - 1)) & 1;
216            bits.push(bit == 1);
217        }
218    }
219    bits
220}
221
222impl<ConstraintF: Field, C: ProjectiveCurve + ToConstraintField<ConstraintF>, D: Digest>
223    ToConstraintField<ConstraintF> for Parameters<C, D>
224{
225    #[inline]
226    fn to_field_elements(&self) -> Result<Vec<ConstraintF>, Error> {
227        self.generator.into_projective().to_field_elements()
228    }
229}