mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-08 08:43:06 +00:00
ECDSA gadget and test
This commit is contained in:
parent
f55948a621
commit
b796c73e49
@ -1,5 +1,3 @@
|
||||
use std::ops::Mul;
|
||||
|
||||
use itertools::unfold;
|
||||
|
||||
use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar};
|
||||
@ -11,8 +9,8 @@ pub struct ECDSASignature<C: Curve> {
|
||||
pub s: C::ScalarField,
|
||||
}
|
||||
|
||||
pub struct ECDSASecretKey<C: Curve>(C::ScalarField);
|
||||
pub struct ECDSAPublicKey<C: Curve>(AffinePoint<C>);
|
||||
pub struct ECDSASecretKey<C: Curve>(pub C::ScalarField);
|
||||
pub struct ECDSAPublicKey<C: Curve>(pub AffinePoint<C>);
|
||||
|
||||
pub fn base_to_scalar<C: Curve>(x: C::BaseField) -> C::ScalarField {
|
||||
C::ScalarField::from_biguint(x.to_biguint())
|
||||
@ -22,15 +20,6 @@ pub fn scalar_to_base<C: Curve>(x: C::ScalarField) -> C::BaseField {
|
||||
C::BaseField::from_biguint(x.to_biguint())
|
||||
}
|
||||
|
||||
pub fn hash_to_scalar<F: RichField, C: Curve>(msg: F, num_bits: usize) -> C::ScalarField {
|
||||
let h_bits = hash_to_bits(msg, num_bits);
|
||||
let h_u32 = h_bits
|
||||
.iter()
|
||||
.zip(0..32)
|
||||
.fold(0u32, |acc, (&bit, pow)| acc + (bit as u32) * (2 << pow));
|
||||
C::ScalarField::from_canonical_u32(h_u32)
|
||||
}
|
||||
|
||||
pub fn hash_to_bits<F: RichField>(x: F, num_bits: usize) -> Vec<bool> {
|
||||
let hashed = hash_n_to_1(vec![x], true);
|
||||
|
||||
@ -44,6 +33,15 @@ pub fn hash_to_bits<F: RichField>(x: F, num_bits: usize) -> Vec<bool> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn hash_to_scalar<F: RichField, C: Curve>(x: F, num_bits: usize) -> C::ScalarField {
|
||||
let h_bits = hash_to_bits(x, num_bits);
|
||||
let h_u32 = h_bits
|
||||
.iter()
|
||||
.zip(0..32)
|
||||
.fold(0u32, |acc, (&bit, pow)| acc + (bit as u32) * (2 << pow));
|
||||
C::ScalarField::from_canonical_u32(h_u32)
|
||||
}
|
||||
|
||||
pub fn sign_message<F: RichField, C: Curve>(msg: F, sk: ECDSASecretKey<C>) -> ECDSASignature<C> {
|
||||
let h = hash_to_scalar::<F, C>(msg, 32);
|
||||
|
||||
@ -76,16 +74,14 @@ pub fn verify_message<F: RichField, C: Curve>(
|
||||
r == x
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::curve::curve_types::{Curve, CurveScalar};
|
||||
use crate::curve::ecdsa::{sign_message, verify_message, ECDSAPublicKey, ECDSASecretKey};
|
||||
use crate::curve::secp256k1::Secp256K1;
|
||||
use crate::field::field_types::Field;
|
||||
use crate::field::goldilocks_field::GoldilocksField;
|
||||
use crate::field::secp256k1_scalar::Secp256K1Scalar;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
|
||||
#[test]
|
||||
fn test_ecdsa_native() {
|
||||
|
||||
@ -15,7 +15,7 @@ use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NonNativeTarget<FF: Field> {
|
||||
pub(crate) value: BigUintTarget,
|
||||
_phantom: PhantomData<FF>,
|
||||
pub(crate) _phantom: PhantomData<FF>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
@ -1,3 +1,15 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::curve::curve_types::Curve;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field_types::RichField;
|
||||
use crate::gadgets::arithmetic_u32::U32Target;
|
||||
use crate::gadgets::biguint::BigUintTarget;
|
||||
use crate::gadgets::curve::AffinePointTarget;
|
||||
use crate::gadgets::nonnative::NonNativeTarget;
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
|
||||
pub struct ECDSASecretKeyTarget<C: Curve>(NonNativeTarget<C::ScalarField>);
|
||||
pub struct ECDSAPublicKeyTarget<C: Curve>(AffinePointTarget<C>);
|
||||
|
||||
@ -6,48 +18,105 @@ pub struct ECDSASignatureTarget<C: Curve> {
|
||||
pub s: NonNativeTarget<C::ScalarField>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
pub fn hash_to_bits(&mut self, x: Target, num_bits: usize) -> Vec<BoolTarget> {
|
||||
let inputs = vec![x];
|
||||
let hashed = self.hash_n_to_m(inputs, 1, true)[0];
|
||||
self.split_le(hashed, num_bits)
|
||||
}
|
||||
|
||||
pub fn hash_to_scalar<C: Curve>(&mut self, x: Target, num_bits: usize) -> NonNativeTarget<C::ScalarField> {
|
||||
let h_bits = self.hash_to_bits(x, num_bits);
|
||||
|
||||
let two = self.two();
|
||||
let mut rev_bits = h_bits.iter().rev();
|
||||
let mut sum = rev_bits.next().unwrap().target;
|
||||
for &bit in rev_bits {
|
||||
sum = self.mul_add(two, sum, bit.target);
|
||||
}
|
||||
let limbs = vec![U32Target(sum)];
|
||||
let value = BigUintTarget {
|
||||
limbs,
|
||||
};
|
||||
|
||||
NonNativeTarget {
|
||||
value,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_message<C: Curve>(&mut self, msg: Target, sig: ECDSASignatureTarget<C>, pk: ECDSAPublicKeyTarget<C>) {
|
||||
let ECDSASignatureTarget { r, s } = sig;
|
||||
|
||||
let h = self.hash_to_scalar::<C>(msg, 32);
|
||||
|
||||
let c = self.inv_nonnative(&s);
|
||||
let u1 = self.mul_nonnative(&h, &c);
|
||||
let u2 = self.mul_nonnative(&r, &c);
|
||||
|
||||
let g = self.constant_affine_point(C::GENERATOR_AFFINE);
|
||||
let point1 = self.curve_scalar_mul(&g, &u1);
|
||||
let point2 = self.curve_scalar_mul(&pk.0, &u2);
|
||||
let point = self.curve_add(&point1, &point2);
|
||||
|
||||
let x = NonNativeTarget::<C::ScalarField> {
|
||||
value: point.x.value,
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
self.connect_nonnative(&r, &x);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::ops::{Mul, Neg};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar};
|
||||
use crate::curve::curve_types::{Curve, CurveScalar};
|
||||
use crate::curve::ecdsa::{ECDSAPublicKey, ECDSASecretKey, ECDSASignature, sign_message};
|
||||
use crate::curve::secp256k1::Secp256K1;
|
||||
use crate::field::field_types::Field;
|
||||
use crate::field::goldilocks_field::GoldilocksField;
|
||||
use crate::field::secp256k1_base::Secp256K1Base;
|
||||
use crate::field::secp256k1_scalar::Secp256K1Scalar;
|
||||
use crate::gadgets::ecdsa::{ECDSAPublicKeyTarget, ECDSASignatureTarget};
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::verifier::verify;
|
||||
|
||||
/*#[test]
|
||||
fn test_curve_point_is_valid() -> Result<()> {
|
||||
#[test]
|
||||
fn test_ecdsa_circuit() -> Result<()> {
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 4;
|
||||
type C = Secp256K1;
|
||||
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let g = Secp256K1::GENERATOR_AFFINE;
|
||||
let g_target = builder.constant_affine_point(g);
|
||||
let neg_g_target = builder.curve_neg(&g_target);
|
||||
let msg = F::rand();
|
||||
let msg_target = builder.constant(msg);
|
||||
|
||||
let sk = ECDSASecretKey::<C>(Secp256K1Scalar::rand());
|
||||
let pk = ECDSAPublicKey((CurveScalar(sk.0) * C::GENERATOR_PROJECTIVE).to_affine());
|
||||
|
||||
builder.curve_assert_valid(&g_target);
|
||||
builder.curve_assert_valid(&neg_g_target);
|
||||
let pk_target = ECDSAPublicKeyTarget(builder.constant_affine_point(pk.0));
|
||||
|
||||
let sig = sign_message(msg, sk);
|
||||
|
||||
let ECDSASignature { r, s } = sig;
|
||||
let r_target = builder.constant_nonnative(r);
|
||||
let s_target = builder.constant_nonnative(s);
|
||||
let sig_target = ECDSASignatureTarget {
|
||||
r: r_target,
|
||||
s: s_target,
|
||||
};
|
||||
|
||||
builder.verify_message(msg_target, sig_target, pk_target);
|
||||
|
||||
let data = builder.build();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user