Skip to content

Commit

Permalink
Correctly absorb curve points into cryptographic sponge (arkworks-rs#115
Browse files Browse the repository at this point in the history
)
  • Loading branch information
slumber authored Aug 21, 2023
1 parent a0e1e85 commit 93dcba9
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 49 deletions.
15 changes: 14 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,17 @@ required-features = [ "prf" ]
name = "schnorr_sig"
path = "benches/signature.rs"
harness = false
required-features = [ "signature" ]
required-features = [ "signature" ]

[patch.crates-io]
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/" }
ark-ff = { git = "https://github.com/arkworks-rs/algebra/" }
ark-ec = { git = "https://github.com/arkworks-rs/algebra/" }
ark-poly = { git = "https://github.com/arkworks-rs/algebra/" }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra/" }

ark-ed-on-bls12-377 = { git = "https://github.com/arkworks-rs/curves/" }
ark-ed-on-bls12-381 = { git = "https://github.com/arkworks-rs/curves/" }
ark-bls12-377 = { git = "https://github.com/arkworks-rs/curves/" }
ark-mnt4-298 = { git = "https://github.com/arkworks-rs/curves/" }
ark-mnt6-298 = { git = "https://github.com/arkworks-rs/curves/" }
3 changes: 2 additions & 1 deletion src/crh/bowe_hopwood/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use rayon::prelude::*;
use super::pedersen;
use crate::crh::{CRHScheme, TwoToOneCRHScheme};
use ark_ec::{
twisted_edwards::Projective as TEProjective, twisted_edwards::TECurveConfig, CurveGroup, Group,
twisted_edwards::Projective as TEProjective, twisted_edwards::TECurveConfig, AdditiveGroup,
CurveGroup,
};
use ark_ff::{biginteger::BigInteger, fields::PrimeField};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
Expand Down
4 changes: 2 additions & 2 deletions src/encryption/elgamal/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ where
let ns = cs.into();
let cs = ns.cs();
let prep = f().map(|g| *g.borrow());
let c1 = GG::new_variable(cs.clone(), || prep.map(|g| g.borrow().0), mode)?;
let c2 = GG::new_variable(cs.clone(), || prep.map(|g| g.borrow().1), mode)?;
let c1 = GG::new_variable(cs.clone(), || prep.map(|g| g.0), mode)?;
let c2 = GG::new_variable(cs.clone(), || prep.map(|g| g.1), mode)?;
Ok(Self {
c1,
c2,
Expand Down
6 changes: 3 additions & 3 deletions src/encryption/elgamal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub mod constraints;

use crate::encryption::AsymmetricEncryptionScheme;
use crate::Error;
use ark_ec::{CurveGroup, Group};
use ark_ec::{AdditiveGroup, CurveGroup};
use ark_ff::{fields::PrimeField, UniformRand};
use ark_std::marker::PhantomData;
use ark_std::ops::Mul;
Expand All @@ -26,7 +26,7 @@ pub struct Randomness<C: CurveGroup>(pub C::ScalarField);
impl<C: CurveGroup> UniformRand for Randomness<C> {
#[inline]
fn rand<R: Rng + ?Sized>(rng: &mut R) -> Self {
Randomness(<C as Group>::ScalarField::rand(rng))
Randomness(<C as AdditiveGroup>::Scalar::rand(rng))
}
}

Expand Down Expand Up @@ -57,7 +57,7 @@ where
rng: &mut R,
) -> Result<(Self::PublicKey, Self::SecretKey), Error> {
// get a random element from the scalar field
let secret_key: <C as Group>::ScalarField = C::ScalarField::rand(rng);
let secret_key: <C as AdditiveGroup>::Scalar = C::ScalarField::rand(rng);

// compute secret_key*generator to derive the public key
let public_key = pp.generator.mul(secret_key).into();
Expand Down
1 change: 0 additions & 1 deletion src/merkle_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,6 @@ impl<P: Config> MerkleTree<P> {
new_leaf: &P::Leaf,
asserted_new_root: &P::InnerDigest,
) -> Result<bool, crate::Error> {
let new_leaf = new_leaf.borrow();
assert!(index < self.leaf_nodes.len(), "index out of range");
let (updated_leaf_hash, mut updated_path) = self.updated_path(index, new_leaf)?;
if &updated_path[0] != asserted_new_root {
Expand Down
4 changes: 2 additions & 2 deletions src/signature/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub trait SignatureScheme {
#[cfg(test)]
mod test {
use crate::signature::{schnorr, *};
use ark_ec::Group;
use ark_ec::AdditiveGroup;
use ark_ed_on_bls12_381::EdwardsProjective as JubJub;
use ark_std::{test_rng, vec::Vec, UniformRand};
use blake2::Blake2s256 as Blake2s;
Expand Down Expand Up @@ -95,7 +95,7 @@ mod test {
"Bad message".as_bytes(),
);
let mut random_scalar_bytes = Vec::new();
let random_scalar = <JubJub as Group>::ScalarField::rand(rng);
let random_scalar = <JubJub as AdditiveGroup>::Scalar::rand(rng);
random_scalar
.serialize_compressed(&mut random_scalar_bytes)
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/signature/schnorr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{signature::SignatureScheme, Error, Vec};
use ark_ec::{AffineRepr, CurveGroup};
use ark_ff::{
fields::{Field, PrimeField},
One, ToConstraintField, UniformRand, Zero,
AdditiveGroup, One, ToConstraintField, UniformRand, Zero,
};
use ark_serialize::CanonicalSerialize;
use ark_std::ops::Mul;
Expand Down
13 changes: 5 additions & 8 deletions src/sponge/absorb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,8 @@ impl Absorb for isize {

impl<CF: PrimeField, P: TEModelParameters<BaseField = CF>> Absorb for TEAffine<P> {
fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
self.to_field_elements()
.unwrap()
.serialize_compressed(dest)
.unwrap()
dest.append(&mut self.x.into_bigint().to_bytes_le());
dest.append(&mut self.y.into_bigint().to_bytes_le());
}

fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
Expand All @@ -242,10 +240,9 @@ impl<CF: PrimeField, P: TEModelParameters<BaseField = CF>> Absorb for TEAffine<P

impl<CF: PrimeField, P: SWModelParameters<BaseField = CF>> Absorb for SWAffine<P> {
fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
self.to_field_elements()
.unwrap()
.serialize_compressed(dest)
.unwrap()
dest.append(&mut self.x.into_bigint().to_bytes_le());
dest.append(&mut self.y.into_bigint().to_bytes_le());
dest.push(self.infinity.into());
}

fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
Expand Down
154 changes: 124 additions & 30 deletions src/sponge/constraints/absorb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,32 +93,49 @@ impl<F: PrimeField> AbsorbGadget<F> for FpVar<F> {
}
}

macro_rules! impl_absorbable_group {
($group:ident, $params:ident) => {
impl<P, F> AbsorbGadget<<P::BaseField as Field>::BasePrimeField> for $group<P, F>
where
P: $params,
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
F: ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField>,
{
fn to_sponge_bytes(
&self,
) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
self.to_constraint_field()?.to_sponge_bytes()
}

fn to_sponge_field_elements(
&self,
) -> Result<Vec<FpVar<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
self.to_constraint_field()
}
}
};
impl<P, F> AbsorbGadget<<P::BaseField as Field>::BasePrimeField> for TEAffineVar<P, F>
where
P: TEModelParameters,
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
F: ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField>,
{
fn to_sponge_bytes(
&self,
) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
self.to_constraint_field()?.to_sponge_bytes()
}

fn to_sponge_field_elements(
&self,
) -> Result<Vec<FpVar<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
self.to_constraint_field()
}
}

impl_absorbable_group!(TEAffineVar, TEModelParameters);
impl_absorbable_group!(SWAffineVar, SWModelParameters);
impl<P, F> AbsorbGadget<<P::BaseField as Field>::BasePrimeField> for SWAffineVar<P, F>
where
P: SWModelParameters,
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
F: ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField>,
{
fn to_sponge_bytes(
&self,
) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
let mut bytes = self.x.to_constraint_field()?.to_sponge_bytes()?;
bytes.append(&mut self.y.to_constraint_field()?.to_sponge_bytes()?);
bytes.append(&mut self.infinity.to_bytes()?.to_sponge_bytes()?);

Ok(bytes)
}

fn to_sponge_field_elements(
&self,
) -> Result<Vec<FpVar<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
self.to_constraint_field()
}
}

impl<P, F> AbsorbGadget<<P::BaseField as Field>::BasePrimeField> for SWProjectiveVar<P, F>
where
Expand Down Expand Up @@ -225,20 +242,89 @@ macro_rules! collect_sponge_field_elements_gadget {
#[cfg(test)]
mod tests {
use crate::sponge::constraints::AbsorbGadget;
use crate::sponge::test::Fr;
use crate::sponge::Absorb;
use ark_r1cs_std::alloc::AllocVar;
use ark_bls12_377::{Fq, G1Projective as G};
use ark_ec::CurveGroup;
use ark_ec::{
short_weierstrass::{Projective as SWProjective, SWCurveConfig},
twisted_edwards::{Projective as TEProjective, TECurveConfig},
};
use ark_ed_on_bls12_377::EdwardsProjective;
use ark_ff::PrimeField;
use ark_r1cs_std::fields::fp::FpVar;
use ark_r1cs_std::uint8::UInt8;
use ark_r1cs_std::R1CSVar;
use ark_relations::r1cs::ConstraintSystem;
use ark_r1cs_std::{
alloc::AllocVar,
groups::curves::{
short_weierstrass::ProjectiveVar as SWProjectiveVar,
twisted_edwards::AffineVar as TEAffineVar,
},
};
use ark_relations::r1cs::{ConstraintSystem, ConstraintSystemRef};
use ark_relations::*;
use ark_std::{test_rng, UniformRand};
use ark_std::{test_rng, UniformRand, Zero};

fn sw_curve_consistency_check<C>(
cs: ConstraintSystemRef<C::BaseField>,
g: SWProjective<C>,
) -> r1cs::Result<()>
where
C: SWCurveConfig,
C::BaseField: PrimeField,
{
let g_affine = g.into_affine();
let native_point_bytes = g_affine.to_sponge_bytes_as_vec();
let native_point_field = g_affine.to_sponge_field_elements_as_vec::<C::BaseField>();

let cs_point =
SWProjectiveVar::<C, FpVar<C::BaseField>>::new_input(ns!(cs, "sw_projective"), || {
Ok(g)
})?;
let cs_point_bytes = cs_point.to_sponge_bytes()?;
let cs_point_field = cs_point.to_sponge_field_elements()?;

let cs_affine_point = cs_point.to_affine()?;
let cs_affine_bytes = cs_affine_point.to_sponge_bytes()?;
let cs_affine_field = cs_affine_point.to_sponge_field_elements()?;

assert_eq!(native_point_bytes, cs_point_bytes.value()?);
assert_eq!(native_point_field, cs_point_field.value()?);

assert_eq!(native_point_bytes, cs_affine_bytes.value()?);
assert_eq!(native_point_field, cs_affine_field.value()?);

Ok(())
}

fn te_curve_consistency_check<C>(g: TEProjective<C>) -> r1cs::Result<()>
where
C: TECurveConfig,
C::BaseField: PrimeField,
{
let cs = ConstraintSystem::<C::BaseField>::new_ref();

let g_affine = g.into_affine();
let native_point_bytes = g_affine.to_sponge_bytes_as_vec();
let native_point_field = g_affine.to_sponge_field_elements_as_vec::<C::BaseField>();

let cs_point =
TEAffineVar::<C, FpVar<C::BaseField>>::new_input(ns!(cs, "te_affine"), || Ok(g))?;
let cs_point_bytes = cs_point.to_sponge_bytes()?;
let cs_point_field = cs_point.to_sponge_field_elements()?;

assert_eq!(native_point_bytes, cs_point_bytes.value()?);
assert_eq!(native_point_field, cs_point_field.value()?);

assert!(cs.is_satisfied()?);

Ok(())
}

#[test]
fn consistency_check() {
// test constraint is consistent with native
let cs = ConstraintSystem::<Fr>::new_ref();
let cs = ConstraintSystem::<Fq>::new_ref();
let mut rng = test_rng();
// uint8
let data = vec![0u8, 1u8, 2u8, 3u8, 4u8, 5u8];
Expand All @@ -251,7 +337,7 @@ mod tests {

// field

let data: Vec<_> = (0..10).map(|_| Fr::rand(&mut rng)).collect();
let data: Vec<_> = (0..10).map(|_| Fq::rand(&mut rng)).collect();
let data_var: Vec<_> = data
.iter()
.map(|item| FpVar::new_input(ns!(cs, "fpdata"), || Ok(*item)).unwrap())
Expand All @@ -261,6 +347,14 @@ mod tests {
let constraint_bytes = data_var.to_sponge_bytes().unwrap();
assert_eq!(constraint_bytes.value().unwrap(), native_bytes);

// sw curve
sw_curve_consistency_check(cs.clone(), G::zero()).unwrap();
sw_curve_consistency_check(cs.clone(), G::rand(&mut rng)).unwrap();

// twisted edwards curve
te_curve_consistency_check(EdwardsProjective::zero()).unwrap();
te_curve_consistency_check(EdwardsProjective::rand(&mut rng)).unwrap();

assert!(cs.is_satisfied().unwrap())
}
}

0 comments on commit 93dcba9

Please sign in to comment.