mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-12 00:41:32 +01:00
Initial commit to extract crypto-primitives to new crate
This commit is contained in:
18
crypto-primitives/src/signature/constraints.rs
Normal file
18
crypto-primitives/src/signature/constraints.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use algebra::Field;
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
use r1cs_std::prelude::*;
|
||||
|
||||
use crate::signature::SignatureScheme;
|
||||
|
||||
pub trait SigRandomizePkGadget<S: SignatureScheme, ConstraintF: Field> {
|
||||
type ParametersGadget: AllocGadget<S::Parameters, ConstraintF> + Clone;
|
||||
|
||||
type PublicKeyGadget: ToBytesGadget<ConstraintF> + EqGadget<ConstraintF> + AllocGadget<S::PublicKey, ConstraintF> + Clone;
|
||||
|
||||
fn check_randomization_gadget<CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
parameters: &Self::ParametersGadget,
|
||||
public_key: &Self::PublicKeyGadget,
|
||||
randomness: &[UInt8],
|
||||
) -> Result<Self::PublicKeyGadget, SynthesisError>;
|
||||
}
|
||||
106
crypto-primitives/src/signature/mod.rs
Normal file
106
crypto-primitives/src/signature/mod.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
use algebra::bytes::ToBytes;
|
||||
use crate::Error;
|
||||
use rand::Rng;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[cfg(feature = "r1cs")]
|
||||
pub mod constraints;
|
||||
#[cfg(feature = "r1cs")]
|
||||
pub use constraints::*;
|
||||
|
||||
|
||||
pub mod schnorr;
|
||||
|
||||
pub trait SignatureScheme {
|
||||
type Parameters: Clone + Send + Sync;
|
||||
type PublicKey: ToBytes + Hash + Eq + Clone + Default + Send + Sync;
|
||||
type SecretKey: ToBytes + Clone + Default;
|
||||
type Signature: Clone + Default + Send + Sync;
|
||||
|
||||
fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error>;
|
||||
|
||||
fn keygen<R: Rng>(
|
||||
pp: &Self::Parameters,
|
||||
rng: &mut R,
|
||||
) -> Result<(Self::PublicKey, Self::SecretKey), Error>;
|
||||
|
||||
fn sign<R: Rng>(
|
||||
pp: &Self::Parameters,
|
||||
sk: &Self::SecretKey,
|
||||
message: &[u8],
|
||||
rng: &mut R,
|
||||
) -> Result<Self::Signature, Error>;
|
||||
|
||||
fn verify(
|
||||
pp: &Self::Parameters,
|
||||
pk: &Self::PublicKey,
|
||||
message: &[u8],
|
||||
signature: &Self::Signature,
|
||||
) -> Result<bool, Error>;
|
||||
|
||||
fn randomize_public_key(
|
||||
pp: &Self::Parameters,
|
||||
public_key: &Self::PublicKey,
|
||||
randomness: &[u8],
|
||||
) -> Result<Self::PublicKey, Error>;
|
||||
|
||||
fn randomize_signature(
|
||||
pp: &Self::Parameters,
|
||||
signature: &Self::Signature,
|
||||
randomness: &[u8],
|
||||
) -> Result<Self::Signature, Error>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{signature::schnorr::SchnorrSignature, SignatureScheme};
|
||||
use algebra::{
|
||||
curves::edwards_sw6::EdwardsAffine as Edwards, groups::Group, to_bytes, ToBytes,
|
||||
};
|
||||
use blake2::Blake2s;
|
||||
use rand::thread_rng;
|
||||
use algebra::UniformRand;
|
||||
|
||||
fn sign_and_verify<S: SignatureScheme>(message: &[u8]) {
|
||||
let rng = &mut thread_rng();
|
||||
let parameters = S::setup::<_>(rng).unwrap();
|
||||
let (pk, sk) = S::keygen(¶meters, rng).unwrap();
|
||||
let sig = S::sign(¶meters, &sk, &message, rng).unwrap();
|
||||
assert!(S::verify(¶meters, &pk, &message, &sig).unwrap());
|
||||
}
|
||||
|
||||
fn failed_verification<S: SignatureScheme>(message: &[u8], bad_message: &[u8]) {
|
||||
let rng = &mut thread_rng();
|
||||
let parameters = S::setup::<_>(rng).unwrap();
|
||||
let (pk, sk) = S::keygen(¶meters, rng).unwrap();
|
||||
let sig = S::sign(¶meters, &sk, message, rng).unwrap();
|
||||
assert!(!S::verify(¶meters, &pk, bad_message, &sig).unwrap());
|
||||
}
|
||||
|
||||
fn randomize_and_verify<S: SignatureScheme>(message: &[u8], randomness: &[u8]) {
|
||||
let rng = &mut thread_rng();
|
||||
let parameters = S::setup::<_>(rng).unwrap();
|
||||
let (pk, sk) = S::keygen(¶meters, rng).unwrap();
|
||||
let sig = S::sign(¶meters, &sk, message, rng).unwrap();
|
||||
assert!(S::verify(¶meters, &pk, message, &sig).unwrap());
|
||||
let randomized_pk = S::randomize_public_key(¶meters, &pk, randomness).unwrap();
|
||||
let randomized_sig = S::randomize_signature(¶meters, &sig, randomness).unwrap();
|
||||
assert!(S::verify(¶meters, &randomized_pk, &message, &randomized_sig).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn schnorr_signature_test() {
|
||||
let message = "Hi, I am a Schnorr signature!";
|
||||
let rng = &mut thread_rng();
|
||||
sign_and_verify::<SchnorrSignature<Edwards, Blake2s>>(message.as_bytes());
|
||||
failed_verification::<SchnorrSignature<Edwards, Blake2s>>(
|
||||
message.as_bytes(),
|
||||
"Bad message".as_bytes(),
|
||||
);
|
||||
let random_scalar = to_bytes!(<Edwards as Group>::ScalarField::rand(rng)).unwrap();
|
||||
randomize_and_verify::<SchnorrSignature<Edwards, Blake2s>>(
|
||||
message.as_bytes(),
|
||||
&random_scalar.as_slice(),
|
||||
);
|
||||
}
|
||||
}
|
||||
210
crypto-primitives/src/signature/schnorr/constraints.rs
Normal file
210
crypto-primitives/src/signature/schnorr/constraints.rs
Normal file
@@ -0,0 +1,210 @@
|
||||
use algebra::{groups::Group, Field};
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
use r1cs_std::prelude::*;
|
||||
|
||||
use crate::signature::SigRandomizePkGadget;
|
||||
|
||||
use std::{borrow::Borrow, marker::PhantomData};
|
||||
|
||||
use crate::signature::schnorr::{
|
||||
SchnorrPublicKey, SchnorrSigParameters, SchnorrSignature,
|
||||
};
|
||||
use digest::Digest;
|
||||
|
||||
pub struct SchnorrSigGadgetParameters<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
|
||||
generator: GG,
|
||||
_group: PhantomData<*const G>,
|
||||
_engine: PhantomData<*const ConstraintF>,
|
||||
}
|
||||
|
||||
impl<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> Clone
|
||||
for SchnorrSigGadgetParameters<G, ConstraintF, GG>
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
generator: self.generator.clone(),
|
||||
_group: PhantomData,
|
||||
_engine: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(
|
||||
Debug(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
|
||||
Clone(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
|
||||
PartialEq(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
|
||||
Eq(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>")
|
||||
)]
|
||||
pub struct SchnorrSigGadgetPk<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
|
||||
pub_key: GG,
|
||||
#[doc(hidden)]
|
||||
_group: PhantomData<*const G>,
|
||||
#[doc(hidden)]
|
||||
_engine: PhantomData<*const ConstraintF>,
|
||||
}
|
||||
|
||||
pub struct SchnorrRandomizePkGadget<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
|
||||
#[doc(hidden)]
|
||||
_group: PhantomData<*const G>,
|
||||
#[doc(hidden)]
|
||||
_group_gadget: PhantomData<*const GG>,
|
||||
#[doc(hidden)]
|
||||
_engine: PhantomData<*const ConstraintF>,
|
||||
}
|
||||
|
||||
impl<G, GG, D, ConstraintF> SigRandomizePkGadget<SchnorrSignature<G, D>, ConstraintF>
|
||||
for SchnorrRandomizePkGadget<G, ConstraintF, GG>
|
||||
where
|
||||
G: Group,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
D: Digest + Send + Sync,
|
||||
ConstraintF: Field,
|
||||
{
|
||||
type ParametersGadget = SchnorrSigGadgetParameters<G, ConstraintF, GG>;
|
||||
type PublicKeyGadget = SchnorrSigGadgetPk<G, ConstraintF, GG>;
|
||||
|
||||
fn check_randomization_gadget<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
parameters: &Self::ParametersGadget,
|
||||
public_key: &Self::PublicKeyGadget,
|
||||
randomness: &[UInt8],
|
||||
) -> Result<Self::PublicKeyGadget, SynthesisError> {
|
||||
let base = parameters.generator.clone();
|
||||
let randomness = randomness
|
||||
.iter()
|
||||
.flat_map(|b| b.into_bits_le())
|
||||
.collect::<Vec<_>>();
|
||||
let rand_pk = base.mul_bits(
|
||||
&mut cs.ns(|| "Compute Randomizer"),
|
||||
&public_key.pub_key,
|
||||
randomness.iter(),
|
||||
)?;
|
||||
Ok(SchnorrSigGadgetPk {
|
||||
pub_key: rand_pk,
|
||||
_group: PhantomData,
|
||||
_engine: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<G, ConstraintF, GG, D> AllocGadget<SchnorrSigParameters<G, D>, ConstraintF>
|
||||
for SchnorrSigGadgetParameters<G, ConstraintF, GG>
|
||||
where
|
||||
G: Group,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
D: Digest,
|
||||
{
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<SchnorrSigParameters<G, D>>,
|
||||
{
|
||||
let generator = GG::alloc_checked(cs, || f().map(|pp| pp.borrow().generator))?;
|
||||
Ok(Self {
|
||||
generator,
|
||||
_engine: PhantomData,
|
||||
_group: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<SchnorrSigParameters<G, D>>,
|
||||
{
|
||||
let generator = GG::alloc_input(cs, || f().map(|pp| pp.borrow().generator))?;
|
||||
Ok(Self {
|
||||
generator,
|
||||
_engine: PhantomData,
|
||||
_group: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<G, ConstraintF, GG> AllocGadget<SchnorrPublicKey<G>, ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
|
||||
where
|
||||
G: Group,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
{
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<SchnorrPublicKey<G>>,
|
||||
{
|
||||
let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
|
||||
Ok(Self {
|
||||
pub_key,
|
||||
_engine: PhantomData,
|
||||
_group: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<SchnorrPublicKey<G>>,
|
||||
{
|
||||
let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
|
||||
Ok(Self {
|
||||
pub_key,
|
||||
_engine: PhantomData,
|
||||
_group: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<G, ConstraintF, GG> ConditionalEqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
|
||||
where
|
||||
G: Group,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
{
|
||||
#[inline]
|
||||
fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
other: &Self,
|
||||
condition: &Boolean,
|
||||
) -> Result<(), SynthesisError> {
|
||||
self.pub_key.conditional_enforce_equal(
|
||||
&mut cs.ns(|| "PubKey equality"),
|
||||
&other.pub_key,
|
||||
condition,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cost() -> usize {
|
||||
<GG as ConditionalEqGadget<ConstraintF>>::cost()
|
||||
}
|
||||
}
|
||||
|
||||
impl<G, ConstraintF, GG> EqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
|
||||
where
|
||||
G: Group,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<G, ConstraintF, GG> ToBytesGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
|
||||
where
|
||||
G: Group,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
{
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
self.pub_key.to_bytes(&mut cs.ns(|| "PubKey To Bytes"))
|
||||
}
|
||||
|
||||
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
self.pub_key
|
||||
.to_bytes_strict(&mut cs.ns(|| "PubKey To Bytes"))
|
||||
}
|
||||
}
|
||||
223
crypto-primitives/src/signature/schnorr/mod.rs
Normal file
223
crypto-primitives/src/signature/schnorr/mod.rs
Normal file
@@ -0,0 +1,223 @@
|
||||
use crate::SignatureScheme;
|
||||
use algebra::{
|
||||
bytes::ToBytes,
|
||||
fields::{Field, PrimeField},
|
||||
groups::Group,
|
||||
to_bytes,
|
||||
};
|
||||
use digest::Digest;
|
||||
use crate::Error;
|
||||
use algebra::UniformRand;
|
||||
use rand::Rng;
|
||||
use std::{
|
||||
hash::Hash,
|
||||
io::{Result as IoResult, Write},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
#[cfg(feature = "r1cs")]
|
||||
pub mod constraints;
|
||||
|
||||
pub struct SchnorrSignature<G: Group, D: Digest> {
|
||||
_group: PhantomData<G>,
|
||||
_hash: PhantomData<D>,
|
||||
}
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Clone(bound = "G: Group, H: Digest"))]
|
||||
pub struct SchnorrSigParameters<G: Group, H: Digest> {
|
||||
_hash: PhantomData<H>,
|
||||
pub generator: G,
|
||||
pub salt: [u8; 32],
|
||||
}
|
||||
|
||||
pub type SchnorrPublicKey<G> = G;
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Clone(bound = "G: Group"), Default(bound = "G: Group"))]
|
||||
pub struct SchnorrSecretKey<G: Group>(pub G::ScalarField);
|
||||
|
||||
impl<G: Group> ToBytes for SchnorrSecretKey<G> {
|
||||
#[inline]
|
||||
fn write<W: Write>(&self, writer: W) -> IoResult<()> {
|
||||
self.0.write(writer)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Clone(bound = "G: Group"), Default(bound = "G: Group"))]
|
||||
pub struct SchnorrSig<G: Group> {
|
||||
pub prover_response: G::ScalarField,
|
||||
pub verifier_challenge: G::ScalarField,
|
||||
}
|
||||
|
||||
impl<G: Group + Hash, D: Digest + Send + Sync> SignatureScheme for SchnorrSignature<G, D>
|
||||
where
|
||||
G::ScalarField: PrimeField,
|
||||
{
|
||||
type Parameters = SchnorrSigParameters<G, D>;
|
||||
type PublicKey = G;
|
||||
type SecretKey = SchnorrSecretKey<G>;
|
||||
type Signature = SchnorrSig<G>;
|
||||
|
||||
fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
|
||||
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<R: Rng>(
|
||||
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<R: Rng>(
|
||||
parameters: &Self::Parameters,
|
||||
sk: &Self::SecretKey,
|
||||
message: &[u8],
|
||||
rng: &mut R,
|
||||
) -> Result<Self::Signature, Error> {
|
||||
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<bool, Error> {
|
||||
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<Self::PublicKey, Error> {
|
||||
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<Self::Signature, Error> {
|
||||
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<bool> {
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user