mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-05-22 09:49:26 +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 itertools::unfold;
|
||||||
|
|
||||||
use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar};
|
use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar};
|
||||||
@ -11,8 +9,8 @@ pub struct ECDSASignature<C: Curve> {
|
|||||||
pub s: C::ScalarField,
|
pub s: C::ScalarField,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ECDSASecretKey<C: Curve>(C::ScalarField);
|
pub struct ECDSASecretKey<C: Curve>(pub C::ScalarField);
|
||||||
pub struct ECDSAPublicKey<C: Curve>(AffinePoint<C>);
|
pub struct ECDSAPublicKey<C: Curve>(pub AffinePoint<C>);
|
||||||
|
|
||||||
pub fn base_to_scalar<C: Curve>(x: C::BaseField) -> C::ScalarField {
|
pub fn base_to_scalar<C: Curve>(x: C::BaseField) -> C::ScalarField {
|
||||||
C::ScalarField::from_biguint(x.to_biguint())
|
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())
|
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> {
|
pub fn hash_to_bits<F: RichField>(x: F, num_bits: usize) -> Vec<bool> {
|
||||||
let hashed = hash_n_to_1(vec![x], true);
|
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()
|
.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> {
|
pub fn sign_message<F: RichField, C: Curve>(msg: F, sk: ECDSASecretKey<C>) -> ECDSASignature<C> {
|
||||||
let h = hash_to_scalar::<F, C>(msg, 32);
|
let h = hash_to_scalar::<F, C>(msg, 32);
|
||||||
|
|
||||||
@ -76,16 +74,14 @@ pub fn verify_message<F: RichField, C: Curve>(
|
|||||||
r == x
|
r == x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
use crate::curve::curve_types::{Curve, CurveScalar};
|
use crate::curve::curve_types::{Curve, CurveScalar};
|
||||||
use crate::curve::ecdsa::{sign_message, verify_message, ECDSAPublicKey, ECDSASecretKey};
|
use crate::curve::ecdsa::{sign_message, verify_message, ECDSAPublicKey, ECDSASecretKey};
|
||||||
use crate::curve::secp256k1::Secp256K1;
|
use crate::curve::secp256k1::Secp256K1;
|
||||||
use crate::field::field_types::Field;
|
use crate::field::field_types::Field;
|
||||||
use crate::field::goldilocks_field::GoldilocksField;
|
use crate::field::goldilocks_field::GoldilocksField;
|
||||||
use crate::field::secp256k1_scalar::Secp256K1Scalar;
|
use crate::field::secp256k1_scalar::Secp256K1Scalar;
|
||||||
use crate::plonk::circuit_data::CircuitConfig;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ecdsa_native() {
|
fn test_ecdsa_native() {
|
||||||
|
|||||||
@ -15,7 +15,7 @@ use crate::plonk::circuit_builder::CircuitBuilder;
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NonNativeTarget<FF: Field> {
|
pub struct NonNativeTarget<FF: Field> {
|
||||||
pub(crate) value: BigUintTarget,
|
pub(crate) value: BigUintTarget,
|
||||||
_phantom: PhantomData<FF>,
|
pub(crate) _phantom: PhantomData<FF>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
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 ECDSASecretKeyTarget<C: Curve>(NonNativeTarget<C::ScalarField>);
|
||||||
pub struct ECDSAPublicKeyTarget<C: Curve>(AffinePointTarget<C>);
|
pub struct ECDSAPublicKeyTarget<C: Curve>(AffinePointTarget<C>);
|
||||||
|
|
||||||
@ -6,48 +18,105 @@ pub struct ECDSASignatureTarget<C: Curve> {
|
|||||||
pub s: NonNativeTarget<C::ScalarField>,
|
pub s: NonNativeTarget<C::ScalarField>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
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 {
|
mod tests {
|
||||||
use std::ops::{Mul, Neg};
|
|
||||||
|
|
||||||
use anyhow::Result;
|
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::curve::secp256k1::Secp256K1;
|
||||||
use crate::field::field_types::Field;
|
use crate::field::field_types::Field;
|
||||||
use crate::field::goldilocks_field::GoldilocksField;
|
use crate::field::goldilocks_field::GoldilocksField;
|
||||||
use crate::field::secp256k1_base::Secp256K1Base;
|
|
||||||
use crate::field::secp256k1_scalar::Secp256K1Scalar;
|
use crate::field::secp256k1_scalar::Secp256K1Scalar;
|
||||||
|
use crate::gadgets::ecdsa::{ECDSAPublicKeyTarget, ECDSASignatureTarget};
|
||||||
use crate::iop::witness::PartialWitness;
|
use crate::iop::witness::PartialWitness;
|
||||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||||
use crate::plonk::circuit_data::CircuitConfig;
|
use crate::plonk::circuit_data::CircuitConfig;
|
||||||
use crate::plonk::verifier::verify;
|
use crate::plonk::verifier::verify;
|
||||||
|
|
||||||
/*#[test]
|
#[test]
|
||||||
fn test_curve_point_is_valid() -> Result<()> {
|
fn test_ecdsa_circuit() -> Result<()> {
|
||||||
type F = GoldilocksField;
|
type F = GoldilocksField;
|
||||||
const D: usize = 4;
|
const D: usize = 4;
|
||||||
|
type C = Secp256K1;
|
||||||
|
|
||||||
let config = CircuitConfig::standard_recursion_config();
|
let config = CircuitConfig::standard_recursion_config();
|
||||||
|
|
||||||
let pw = PartialWitness::new();
|
let pw = PartialWitness::new();
|
||||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||||
|
|
||||||
let g = Secp256K1::GENERATOR_AFFINE;
|
let msg = F::rand();
|
||||||
let g_target = builder.constant_affine_point(g);
|
let msg_target = builder.constant(msg);
|
||||||
let neg_g_target = builder.curve_neg(&g_target);
|
|
||||||
|
let sk = ECDSASecretKey::<C>(Secp256K1Scalar::rand());
|
||||||
|
let pk = ECDSAPublicKey((CurveScalar(sk.0) * C::GENERATOR_PROJECTIVE).to_affine());
|
||||||
|
|
||||||
builder.curve_assert_valid(&g_target);
|
let pk_target = ECDSAPublicKeyTarget(builder.constant_affine_point(pk.0));
|
||||||
builder.curve_assert_valid(&neg_g_target);
|
|
||||||
|
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 data = builder.build();
|
||||||
let proof = data.prove(pw).unwrap();
|
let proof = data.prove(pw).unwrap();
|
||||||
|
|
||||||
verify(proof, &data.verifier_only, &data.common)
|
verify(proof, &data.verifier_only, &data.common)
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user