Skip to content

Commit

Permalink
chore!: remove eddsa from stdlib (#6591)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Nov 22, 2024
1 parent b934669 commit 8e046af
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 121 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,5 @@ fn bjj_pub_key(priv_key: Field) -> Point
This would come in handy in a Merkle proof.

- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash
function. See
[feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for
the case of Baby Jubjub and the Poseidon hash function.
function. See the [eddsa](https://github.com/noir-lang/eddsa) library an example of eddsa signature verification
over the Baby Jubjub curve.
37 changes: 0 additions & 37 deletions docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx

This file was deleted.

76 changes: 0 additions & 76 deletions noir_stdlib/src/eddsa.nr

This file was deleted.

1 change: 0 additions & 1 deletion noir_stdlib/src/lib.nr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub mod merkle;
pub mod schnorr;
pub mod ecdsa_secp256k1;
pub mod ecdsa_secp256r1;
pub mod eddsa;
pub mod embedded_curve_ops;
pub mod sha256;
pub mod sha512;
Expand Down
55 changes: 52 additions & 3 deletions test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,12 +1,61 @@
use std::eddsa::eddsa_poseidon_verify;
use std::default::Default;
use std::ec::consts::te::baby_jubjub;
use std::ec::tecurve::affine::Point as TEPoint;
use std::hash::Hasher;
use std::hash::poseidon::PoseidonHasher;

fn main(
msg: pub Field,
pub_key_x: Field,
pub_key_y: Field,
r8_x: Field,
r8_y: Field,
s: Field
s: Field,
) -> pub bool {
eddsa_poseidon_verify(pub_key_x, pub_key_y, s, r8_x, r8_y, msg)
eddsa_verify::<PoseidonHasher>(pub_key_x, pub_key_y, s, r8_x, r8_y, msg)
}

pub fn eddsa_verify<H>(
pub_key_x: Field,
pub_key_y: Field,
signature_s: Field,
signature_r8_x: Field,
signature_r8_y: Field,
message: Field,
) -> bool
where
H: Hasher + Default,
{
// Verifies by testing:
// S * B8 = R8 + H(R8, A, m) * A8
let bjj = baby_jubjub();

let pub_key = TEPoint::new(pub_key_x, pub_key_y);
assert(bjj.curve.contains(pub_key));

let signature_r8 = TEPoint::new(signature_r8_x, signature_r8_y);
assert(bjj.curve.contains(signature_r8));
// Ensure S < Subgroup Order
assert(signature_s.lt(bjj.suborder));
// Calculate the h = H(R, A, msg)
let mut hasher = H::default();
hasher.write(signature_r8_x);
hasher.write(signature_r8_y);
hasher.write(pub_key_x);
hasher.write(pub_key_y);
hasher.write(message);
let hash: Field = hasher.finish();
// Calculate second part of the right side: right2 = h*8*A
// Multiply by 8 by doubling 3 times. This also ensures that the result is in the subgroup.
let pub_key_mul_2 = bjj.curve.add(pub_key, pub_key);
let pub_key_mul_4 = bjj.curve.add(pub_key_mul_2, pub_key_mul_2);
let pub_key_mul_8 = bjj.curve.add(pub_key_mul_4, pub_key_mul_4);
// We check that A8 is not zero.
assert(!pub_key_mul_8.is_zero());
// Compute the right side: R8 + h * A8
let right = bjj.curve.add(signature_r8, bjj.curve.mul(hash, pub_key_mul_8));
// Calculate left side of equation left = S * B8
let left = bjj.curve.mul(signature_s, bjj.base8);

left.eq(right)
}
74 changes: 73 additions & 1 deletion test_programs/execution_success/eddsa/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::compat;
use std::ec::consts::te::baby_jubjub;
use std::ec::tecurve::affine::Point as TEPoint;
use std::eddsa::{eddsa_poseidon_verify, eddsa_to_pub, eddsa_verify};
use std::hash::Hasher;
use std::hash::poseidon::PoseidonHasher;
use std::hash::poseidon2::Poseidon2Hasher;

fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) {
Expand Down Expand Up @@ -54,3 +55,74 @@ fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) {
);
}
}

// Returns true if signature is valid
pub fn eddsa_poseidon_verify(
pub_key_x: Field,
pub_key_y: Field,
signature_s: Field,
signature_r8_x: Field,
signature_r8_y: Field,
message: Field,
) -> bool {
eddsa_verify::<PoseidonHasher>(
pub_key_x,
pub_key_y,
signature_s,
signature_r8_x,
signature_r8_y,
message,
)
}

pub fn eddsa_verify<H>(
pub_key_x: Field,
pub_key_y: Field,
signature_s: Field,
signature_r8_x: Field,
signature_r8_y: Field,
message: Field,
) -> bool
where
H: Hasher + Default,
{
// Verifies by testing:
// S * B8 = R8 + H(R8, A, m) * A8
let bjj = baby_jubjub();

let pub_key = TEPoint::new(pub_key_x, pub_key_y);
assert(bjj.curve.contains(pub_key));

let signature_r8 = TEPoint::new(signature_r8_x, signature_r8_y);
assert(bjj.curve.contains(signature_r8));
// Ensure S < Subgroup Order
assert(signature_s.lt(bjj.suborder));
// Calculate the h = H(R, A, msg)
let mut hasher = H::default();
hasher.write(signature_r8_x);
hasher.write(signature_r8_y);
hasher.write(pub_key_x);
hasher.write(pub_key_y);
hasher.write(message);
let hash: Field = hasher.finish();
// Calculate second part of the right side: right2 = h*8*A
// Multiply by 8 by doubling 3 times. This also ensures that the result is in the subgroup.
let pub_key_mul_2 = bjj.curve.add(pub_key, pub_key);
let pub_key_mul_4 = bjj.curve.add(pub_key_mul_2, pub_key_mul_2);
let pub_key_mul_8 = bjj.curve.add(pub_key_mul_4, pub_key_mul_4);
// We check that A8 is not zero.
assert(!pub_key_mul_8.is_zero());
// Compute the right side: R8 + h * A8
let right = bjj.curve.add(signature_r8, bjj.curve.mul(hash, pub_key_mul_8));
// Calculate left side of equation left = S * B8
let left = bjj.curve.mul(signature_s, bjj.base8);

left.eq(right)
}

// Returns the public key of the given secret key as (pub_key_x, pub_key_y)
pub fn eddsa_to_pub(secret: Field) -> (Field, Field) {
let bjj = baby_jubjub();
let pub_key = bjj.curve.mul(secret, bjj.curve.gen);
(pub_key.x, pub_key.y)
}

0 comments on commit 8e046af

Please sign in to comment.