mirror of
https://github.com/arnaucube/ark-ec-blind-signatures.git
synced 2026-01-12 00:21:29 +01:00
Parametrize signed-msg length (for Poseidon input)
Now message to be signed is an array of field elements that can have the length defined by the lib instantiation.
This commit is contained in:
@@ -35,7 +35,7 @@ pub struct PublicKeyVar<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
||||
where
|
||||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
||||
{
|
||||
pub_key: GC,
|
||||
pub pub_key: GC,
|
||||
#[doc(hidden)]
|
||||
_group: PhantomData<*const C>,
|
||||
}
|
||||
@@ -59,31 +59,43 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// TODO parametrize Msg & MsgVar length
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
// pub struct Msg<C: ProjectiveCurve>(pub Vec<ConstraintF<C>>);
|
||||
pub struct Msg<C: ProjectiveCurve>(pub [ConstraintF<C>; 3]);
|
||||
pub struct Msg<const MSG_LEN: usize, C: ProjectiveCurve>(pub [ConstraintF<C>; 3]);
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(
|
||||
Debug(bound = "C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>"),
|
||||
Clone(bound = "C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>")
|
||||
)]
|
||||
pub struct MsgVar<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
||||
pub struct MsgVar<const MSG_LEN: usize, C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
||||
where
|
||||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
||||
{
|
||||
m: [FpVar<ConstraintF<C>>; 3],
|
||||
m: [FpVar<ConstraintF<C>>; MSG_LEN],
|
||||
_gc: PhantomData<GC>,
|
||||
}
|
||||
impl<C, GC> AllocVar<Msg<C>, ConstraintF<C>> for MsgVar<C, GC>
|
||||
impl<const MSG_LEN: usize, C, GC> MsgVar<MSG_LEN, C, GC>
|
||||
where
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
||||
{
|
||||
fn new_variable<T: Borrow<Msg<C>>>(
|
||||
pub fn new(m: [FpVar<ConstraintF<C>>; MSG_LEN]) -> Self {
|
||||
Self {
|
||||
m,
|
||||
_gc: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const MSG_LEN: usize, C, GC> AllocVar<Msg<MSG_LEN, C>, ConstraintF<C>>
|
||||
for MsgVar<MSG_LEN, C, GC>
|
||||
where
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
||||
{
|
||||
fn new_variable<T: Borrow<Msg<MSG_LEN, C>>>(
|
||||
cs: impl Into<Namespace<ConstraintF<C>>>,
|
||||
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
@@ -91,9 +103,21 @@ where
|
||||
f().and_then(|m| {
|
||||
let m = m.borrow();
|
||||
let cs = cs.into();
|
||||
let msg: Vec<FpVar<ConstraintF<C>>> = Vec::new_variable(cs, || Ok(m.clone().0), mode)?;
|
||||
let msg_vec: Vec<FpVar<ConstraintF<C>>> =
|
||||
Vec::new_variable(cs, || Ok(m.clone().0), mode)?;
|
||||
let m: [FpVar<ConstraintF<C>>; MSG_LEN] =
|
||||
msg_vec
|
||||
.try_into()
|
||||
.unwrap_or_else(|v: Vec<FpVar<ConstraintF<C>>>| {
|
||||
// WIP
|
||||
panic!(
|
||||
"Expected Vec of length: {}, actual length: {}",
|
||||
MSG_LEN,
|
||||
v.len()
|
||||
)
|
||||
});
|
||||
Ok(Self {
|
||||
m: [msg[0].clone(), msg[1].clone(), msg[2].clone()],
|
||||
m,
|
||||
_gc: PhantomData,
|
||||
})
|
||||
})
|
||||
@@ -181,15 +205,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BlindSigVerifyGadget<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
||||
where
|
||||
pub struct BlindSigVerifyGadget<
|
||||
const MSG_LEN: usize,
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
> where
|
||||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
||||
{
|
||||
_params: Parameters<C>, // TODO review if needed, maybe delete
|
||||
_gc: PhantomData<GC>,
|
||||
}
|
||||
|
||||
impl<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>> BlindSigVerifyGadget<C, GC>
|
||||
impl<const MSG_LEN: usize, C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
||||
BlindSigVerifyGadget<MSG_LEN, C, GC>
|
||||
where
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
@@ -202,10 +230,10 @@ where
|
||||
FpVar<<C as ProjectiveCurve>::BaseField>: Mul<FpVar<Fp256<FqParameters>>>,
|
||||
FpVar<<C as ProjectiveCurve>::BaseField>: From<FpVar<Fp256<FqParameters>>>,
|
||||
{
|
||||
fn verify(
|
||||
pub fn verify(
|
||||
parameters: &ParametersVar<C, GC>,
|
||||
poseidon_hash: &PoseidonGadget<ConstraintF<C>>,
|
||||
m: &MsgVar<C, GC>,
|
||||
m: &MsgVar<MSG_LEN, C, GC>,
|
||||
s: &SignatureVar<C, GC>,
|
||||
q: &PublicKeyVar<C, GC>,
|
||||
) -> Result<Boolean<ConstraintF<C>>, SynthesisError> {
|
||||
@@ -230,9 +258,10 @@ where
|
||||
}
|
||||
|
||||
pub struct BlindSigBatchVerifyGadget<
|
||||
const NUM_SIGS: usize,
|
||||
const MSG_LEN: usize,
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
const NUM_SIGS: usize,
|
||||
> where
|
||||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
||||
{
|
||||
@@ -240,8 +269,12 @@ pub struct BlindSigBatchVerifyGadget<
|
||||
_gc: PhantomData<GC>,
|
||||
}
|
||||
|
||||
impl<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>, const NUM_SIGS: usize>
|
||||
BlindSigBatchVerifyGadget<C, GC, NUM_SIGS>
|
||||
impl<
|
||||
const NUM_SIGS: usize,
|
||||
const MSG_LEN: usize,
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
> BlindSigBatchVerifyGadget<NUM_SIGS, MSG_LEN, C, GC>
|
||||
where
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
@@ -254,10 +287,10 @@ where
|
||||
FpVar<<C as ProjectiveCurve>::BaseField>: Mul<FpVar<Fp256<FqParameters>>>,
|
||||
FpVar<<C as ProjectiveCurve>::BaseField>: From<FpVar<Fp256<FqParameters>>>,
|
||||
{
|
||||
fn batch_verify(
|
||||
pub fn batch_verify(
|
||||
parameters: &ParametersVar<C, GC>,
|
||||
poseidon_hash: &PoseidonGadget<ConstraintF<C>>,
|
||||
m: &MsgVar<C, GC>,
|
||||
m: &MsgVar<MSG_LEN, C, GC>,
|
||||
sigs: &[SignatureVar<C, GC>],
|
||||
q: &PublicKeyVar<C, GC>,
|
||||
) -> Result<Boolean<ConstraintF<C>>, SynthesisError> {
|
||||
@@ -287,8 +320,11 @@ where
|
||||
|
||||
// example of circuit using BlindSigVerifyGadget to verify a single blind signature
|
||||
#[derive(Clone)]
|
||||
pub struct BlindSigVerifyCircuit<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
||||
where
|
||||
pub struct BlindSigVerifyCircuit<
|
||||
const MSG_LEN: usize,
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
> where
|
||||
<C as ProjectiveCurve>::BaseField: PrimeField,
|
||||
{
|
||||
_group: PhantomData<*const GC>,
|
||||
@@ -296,11 +332,11 @@ where
|
||||
pub poseidon_hash_native: poseidon_native::Poseidon<ConstraintF<C>>,
|
||||
pub signature: Option<Signature<C>>,
|
||||
pub pub_key: Option<PublicKey<C>>,
|
||||
pub message: Option<Msg<C>>,
|
||||
pub message: Option<Msg<MSG_LEN, C>>,
|
||||
}
|
||||
|
||||
impl<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>> ConstraintSynthesizer<ConstraintF<C>>
|
||||
for BlindSigVerifyCircuit<C, GC>
|
||||
impl<const MSG_LEN: usize, C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
||||
ConstraintSynthesizer<ConstraintF<C>> for BlindSigVerifyCircuit<MSG_LEN, C, GC>
|
||||
where
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
@@ -325,7 +361,7 @@ where
|
||||
PublicKeyVar::<C, GC>::new_input(ark_relations::ns!(cs, "public key"), || {
|
||||
self.pub_key.ok_or(SynthesisError::AssignmentMissing)
|
||||
})?;
|
||||
let m = MsgVar::<C, GC>::new_input(ark_relations::ns!(cs, "message"), || {
|
||||
let m = MsgVar::<MSG_LEN, C, GC>::new_input(ark_relations::ns!(cs, "message"), || {
|
||||
self.message.ok_or(SynthesisError::AssignmentMissing)
|
||||
})?;
|
||||
let signature =
|
||||
@@ -339,7 +375,7 @@ where
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let v = BlindSigVerifyGadget::<C, GC>::verify(
|
||||
let v = BlindSigVerifyGadget::<MSG_LEN, C, GC>::verify(
|
||||
¶meters,
|
||||
&poseidon_hash,
|
||||
&m,
|
||||
@@ -353,9 +389,10 @@ where
|
||||
// example of circuit using BlindSigVerifyGadget to verify a batch of blind signatures
|
||||
#[derive(Clone)]
|
||||
pub struct BlindSigBatchVerifyCircuit<
|
||||
const NUM_SIGS: usize,
|
||||
const MSG_LEN: usize,
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
const NUM_SIGS: usize,
|
||||
> where
|
||||
<C as ProjectiveCurve>::BaseField: PrimeField,
|
||||
{
|
||||
@@ -364,11 +401,15 @@ pub struct BlindSigBatchVerifyCircuit<
|
||||
pub poseidon_hash_native: poseidon_native::Poseidon<ConstraintF<C>>,
|
||||
pub signatures: Option<Vec<Signature<C>>>,
|
||||
pub pub_key: Option<PublicKey<C>>,
|
||||
pub message: Option<Msg<C>>,
|
||||
pub message: Option<Msg<MSG_LEN, C>>,
|
||||
}
|
||||
|
||||
impl<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>, const NUM_SIGS: usize>
|
||||
ConstraintSynthesizer<ConstraintF<C>> for BlindSigBatchVerifyCircuit<C, GC, NUM_SIGS>
|
||||
impl<
|
||||
const NUM_SIGS: usize,
|
||||
const MSG_LEN: usize,
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
> ConstraintSynthesizer<ConstraintF<C>> for BlindSigBatchVerifyCircuit<NUM_SIGS, MSG_LEN, C, GC>
|
||||
where
|
||||
C: ProjectiveCurve,
|
||||
GC: CurveVar<C, ConstraintF<C>>,
|
||||
@@ -393,7 +434,7 @@ where
|
||||
PublicKeyVar::<C, GC>::new_input(ark_relations::ns!(cs, "public key"), || {
|
||||
self.pub_key.ok_or(SynthesisError::AssignmentMissing)
|
||||
})?;
|
||||
let m = MsgVar::<C, GC>::new_input(ark_relations::ns!(cs, "message"), || {
|
||||
let m = MsgVar::<MSG_LEN, C, GC>::new_input(ark_relations::ns!(cs, "message"), || {
|
||||
self.message.ok_or(SynthesisError::AssignmentMissing)
|
||||
})?;
|
||||
|
||||
@@ -415,7 +456,7 @@ where
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let v = BlindSigBatchVerifyGadget::<C, GC, NUM_SIGS>::batch_verify(
|
||||
let v = BlindSigBatchVerifyGadget::<NUM_SIGS, MSG_LEN, C, GC>::batch_verify(
|
||||
¶meters,
|
||||
&poseidon_hash,
|
||||
&m,
|
||||
@@ -447,7 +488,7 @@ mod test {
|
||||
) -> (
|
||||
Parameters<BabyJubJub>,
|
||||
PublicKey<BabyJubJub>,
|
||||
Msg<BabyJubJub>,
|
||||
Msg<3, BabyJubJub>,
|
||||
Signature<BabyJubJub>,
|
||||
) {
|
||||
let mut rng = ark_std::test_rng();
|
||||
@@ -457,7 +498,7 @@ mod test {
|
||||
let m = [Fq::from(1234), Fq::from(5689), Fq::from(3456)];
|
||||
let (m_blinded, u) = S::blind(¶ms, &mut rng, &poseidon_hash, &m, signer_r).unwrap();
|
||||
let s_blinded = S::blind_sign(sk, k, m_blinded);
|
||||
let s = S::unblind(s_blinded, u);
|
||||
let s = S::unblind(s_blinded, &u);
|
||||
let verified = S::verify(¶ms, &poseidon_hash, &m, s.clone(), pk);
|
||||
assert!(verified);
|
||||
(params, pk, Msg(m), s)
|
||||
@@ -469,7 +510,7 @@ mod test {
|
||||
) -> (
|
||||
Parameters<BabyJubJub>,
|
||||
PublicKey<BabyJubJub>,
|
||||
Msg<BabyJubJub>,
|
||||
Msg<3, BabyJubJub>,
|
||||
Vec<Signature<BabyJubJub>>,
|
||||
) {
|
||||
let mut rng = ark_std::test_rng();
|
||||
@@ -481,7 +522,7 @@ mod test {
|
||||
let (k, signer_r) = S::new_request_params(¶ms, &mut rng);
|
||||
let (m_blinded, u) = S::blind(¶ms, &mut rng, &poseidon_hash, &m, signer_r).unwrap();
|
||||
let s_blinded = S::blind_sign(sk, k, m_blinded);
|
||||
let s = S::unblind(s_blinded, u);
|
||||
let s = S::unblind(s_blinded, &u);
|
||||
let verified = S::verify(¶ms, &poseidon_hash, &m, s.clone(), pk);
|
||||
assert!(verified);
|
||||
signatures.push(s);
|
||||
@@ -491,15 +532,15 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_single_verify() {
|
||||
// TODO N_INPUTS+1 (N_INPUTS msg_to_sign_length)
|
||||
let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 4);
|
||||
let poseidon_hash = poseidon::Poseidon::new(poseidon_params);
|
||||
const MSG_LEN: usize = 3;
|
||||
|
||||
// create signature using native-rust lib
|
||||
let (params, pk, m, s) = generate_single_sig_native_data(&poseidon_hash);
|
||||
|
||||
// use the constraint system to verify the signature
|
||||
type SG = BlindSigVerifyGadget<BabyJubJub, BabyJubJubVar>;
|
||||
type SG = BlindSigVerifyGadget<MSG_LEN, BabyJubJub, BabyJubJubVar>;
|
||||
let cs = ConstraintSystem::<Fq>::new_ref();
|
||||
|
||||
let params_var =
|
||||
@@ -508,7 +549,8 @@ mod test {
|
||||
SignatureVar::<BabyJubJub, BabyJubJubVar>::new_witness(cs.clone(), || Ok(&s)).unwrap();
|
||||
let pk_var =
|
||||
PublicKeyVar::<BabyJubJub, BabyJubJubVar>::new_witness(cs.clone(), || Ok(&pk)).unwrap();
|
||||
let m_var = MsgVar::<BabyJubJub, BabyJubJubVar>::new_witness(cs.clone(), || Ok(m)).unwrap();
|
||||
let m_var = MsgVar::<MSG_LEN, BabyJubJub, BabyJubJubVar>::new_witness(cs.clone(), || Ok(m))
|
||||
.unwrap();
|
||||
let poseidon_hash_var =
|
||||
PoseidonGadget::<Fq>::from_native(&mut cs.clone(), poseidon_hash).unwrap();
|
||||
|
||||
@@ -528,12 +570,13 @@ mod test {
|
||||
fn test_single_verify_constraint_system() {
|
||||
let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 4);
|
||||
let poseidon_hash = poseidon::Poseidon::new(poseidon_params);
|
||||
const MSG_LEN: usize = 3;
|
||||
|
||||
// create signature using native-rust lib
|
||||
let (params, pk, m, s) = generate_single_sig_native_data(&poseidon_hash);
|
||||
|
||||
// use the constraint system to verify the signature
|
||||
let circuit = BlindSigVerifyCircuit::<BabyJubJub, BabyJubJubVar> {
|
||||
let circuit = BlindSigVerifyCircuit::<MSG_LEN, BabyJubJub, BabyJubJubVar> {
|
||||
params,
|
||||
poseidon_hash_native: poseidon_hash.clone(),
|
||||
signature: Some(s),
|
||||
@@ -552,13 +595,14 @@ mod test {
|
||||
fn test_batch_verify_constraint_system() {
|
||||
let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 4);
|
||||
let poseidon_hash = poseidon::Poseidon::new(poseidon_params);
|
||||
const MSG_LEN: usize = 3;
|
||||
|
||||
// create signatures using native-rust lib
|
||||
const NUM_SIGS: usize = 5;
|
||||
let (params, pk, m, sigs) = generate_batch_sig_native_data(&poseidon_hash, NUM_SIGS);
|
||||
|
||||
// use the constraint system to verify the batch of signatures
|
||||
let circuit = BlindSigBatchVerifyCircuit::<BabyJubJub, BabyJubJubVar, NUM_SIGS> {
|
||||
let circuit = BlindSigBatchVerifyCircuit::<NUM_SIGS, MSG_LEN, BabyJubJub, BabyJubJubVar> {
|
||||
params,
|
||||
poseidon_hash_native: poseidon_hash.clone(),
|
||||
signatures: Some(sigs),
|
||||
|
||||
@@ -34,7 +34,7 @@ pub struct Signature<C: ProjectiveCurve> {
|
||||
r: <C as ProjectiveCurve>::Affine,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct UserSecretData<C: ProjectiveCurve> {
|
||||
a: C::ScalarField,
|
||||
b: C::ScalarField,
|
||||
@@ -153,7 +153,7 @@ where
|
||||
Ok((m_blinded, u))
|
||||
}
|
||||
|
||||
pub fn unblind(s_blinded: C::ScalarField, u: UserSecretData<C>) -> Signature<C> {
|
||||
pub fn unblind(s_blinded: C::ScalarField, u: &UserSecretData<C>) -> Signature<C> {
|
||||
// s = a s' + b
|
||||
let s = u.a * s_blinded + u.b;
|
||||
Signature { s, r: u.r }
|
||||
@@ -240,7 +240,7 @@ mod tests {
|
||||
|
||||
let s_blinded = S::blind_sign(sk, k, m_blinded);
|
||||
|
||||
let s = S::unblind(s_blinded, u);
|
||||
let s = S::unblind(s_blinded, &u);
|
||||
|
||||
let verified = S::verify(¶ms, &poseidon_hash, &m, s, pk);
|
||||
assert!(verified);
|
||||
|
||||
Reference in New Issue
Block a user