Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/nargo_cli/tests/test_data/eddsa/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.3.2"

[dependencies]
3 changes: 3 additions & 0 deletions crates/nargo_cli/tests/test_data/eddsa/Prover.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
_priv_key_a = 123
_priv_key_b = 456
msg = 789
69 changes: 69 additions & 0 deletions crates/nargo_cli/tests/test_data/eddsa/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use dep::std::compat;
use dep::std::ec::consts::te::baby_jubjub;
use dep::std::hash;
use dep::std::eddsa::eddsa_poseidon_verify;
use dep::std;

fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) {
// Skip this test for non-bn254 backends
if compat::is_bn254() {
// let bjj = baby_jubjub();

// let pub_key_a = bjj.curve.mul(priv_key_a, bjj.curve.gen);
let pub_key_a_x = 5958787406588418500595239545974275039455545059833263445973445578199987122248;
let pub_key_a_y = 6291453822075498887551694851992571215511219854100590306020486222643399599966;
// let pub_key_b = bjj.curve.mul(priv_key_b, bjj.curve.gen);
// let pub_key_b_x = 19522885864221102065733517599414632594441624981666469001809339503157461222552;
// let pub_key_b_y = 17652333933129211461240983013989988903130120700742832943186712581416334147739;

// Manually computed as fields can't use modulo. Importantantly the commitment is within
// the subgroup order. Note that choice of hash is flexible for this step.
// let r_a = hash::pedersen([priv_key_a, msg])[0] % bjj.suborder; // modulus computed manually
// let r_a = 161490627844314967434218537112044327531827991364156693670922373984031106453;
// let r_b = hash::pedersen([priv_key_b, msg])[0] % bjj.suborder; // modulus computed manually
// let r_b = 2365791308032549643506220161686150043336029213998559307390193647484103923348;

// let r8_a = bjj.curve.mul(r_a, bjj.base8);
let r8_a_x = 12701037151626467441858303530846040756656970729849074442899237454651294526343;
let r8_a_y = 167159699056112791619442377873552194056131231335147805875057144366514712633;
// let r8_b = bjj.curve.mul(r_b, bjj.base8);
let r8_b_x = 1673844937671191161222451342456048355167330081367086809349241319413342408558;
let r8_b_y = 6202873177260205770199785557298715091502981852957429177245493218486919053107;

// let perm_a: [Field; 6] = hash::poseidon::bn254::perm::x5_6([
// 0,
// r8_a.x,
// r8_a.y,
// pub_key_a.x,
// pub_key_a.y,
// msg,
// ]);
// let h_a = perm_a[0];
// let h_a = 21371027913064755721489810138902574499031056361794273463577587174578008711057;

// let perm_b: [Field; 6] = hash::poseidon::bn254::perm::x5_6([
// 0,
// r8_b.x,
// r8_b.y,
// pub_key_b.x,
// pub_key_b.y,
// msg,
// ]);
// let h_b = perm_b[0];
// let h_b = 15015879520414293281817167314697737785772315344690416596928480331452621620489;

// let s_a = (r_a + priv_key_a * h_a) % bjj.suborder; // modulus computed manually
let s_a = 960;
// let s_b = (r_b + priv_key_b * h_b) % bjj.suborder; // modulus computed manually
let s_b = 3562;

// User A verifies their signature over the message
constrain eddsa_poseidon_verify(pub_key_a_x, pub_key_a_y, s_a, r8_a_x, r8_a_y, msg);

// User B's signature over the message can't be used with user A's pub key
constrain !eddsa_poseidon_verify(pub_key_a_x, pub_key_a_y, s_b, r8_b_x, r8_b_y, msg);

// User A's signature over the message can't be used with another message
constrain !eddsa_poseidon_verify(pub_key_a_x, pub_key_a_y, s_a, r8_a_x, r8_a_y, msg + 1);
}
}
4 changes: 4 additions & 0 deletions noir_stdlib/src/compat.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn is_bn254() -> bool {
// bn254 truncates its curve order to 0
21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0
}
1 change: 1 addition & 0 deletions noir_stdlib/src/ec.nr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
mod tecurve; // Twisted Edwards curves
mod swcurve; // Elliptic curves in Short Weierstraß form
mod montcurve; // Montgomery curves
mod consts; // Commonly used curve presets
//
// Note that Twisted Edwards and Montgomery curves are (birationally) equivalent, so that
// they may be freely converted between one another, whereas Short Weierstraß curves are
Expand Down
1 change: 1 addition & 0 deletions noir_stdlib/src/ec/consts.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod te;
32 changes: 32 additions & 0 deletions noir_stdlib/src/ec/consts/te.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use crate::compat;
use crate::ec::tecurve::affine::Point as TEPoint;
use crate::ec::tecurve::affine::Curve as TECurve;

struct BabyJubjub {
curve: TECurve,
base8: TEPoint,
suborder: Field,
}

fn baby_jubjub() -> BabyJubjub {
constrain compat::is_bn254();

BabyJubjub {
// Baby Jubjub (ERC-2494) parameters in affine representation
curve: TECurve::new(
168700,
168696,
TEPoint::new(
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203,
),
),
// [8]G precalculated
base8: TEPoint::new(
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203,
),
// The size of the group formed from multiplying the base field by 8.
suborder: 2736030358979909402780800718157159386076813972158567259200215660948447373041,
}
}
56 changes: 56 additions & 0 deletions noir_stdlib/src/eddsa.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::hash::poseidon;
use crate::ec::consts::te::baby_jubjub;
use crate::ec::tecurve::affine::Point as TEPoint;
use crate::field;

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 {
// 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);
constrain bjj.curve.contains(pub_key);

let signature_r8 = TEPoint::new(signature_r8_x, signature_r8_y);
constrain bjj.curve.contains(signature_r8);

// Ensure S < Subgroup Order
constrain field::lt_bytes32(signature_s, bjj.suborder);

// Calculate the h = H(R,A, msg)
let perm: [Field; 6] = poseidon::bn254::perm::x5_6([
0,
signature_r8_x,
signature_r8_y,
pub_key_x,
pub_key_y,
message,
]);
let hash = perm[0];

// 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.
constrain !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)
}
21 changes: 21 additions & 0 deletions noir_stdlib/src/field.nr
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,24 @@ fn modulus_be_bytes() -> [u8] {}

#[builtin(modulus_le_bytes)]
fn modulus_le_bytes() -> [u8] {}

// Returns true if x is less than y
// TODO: consider sftey of final few bits
fn lt_bytes32(x: Field, y: Field) -> bool {
let x_bytes = x.to_le_bytes(32);
let y_bytes = y.to_le_bytes(32);
let mut x_is_lt = false;
let mut done = false;
for i in 0..32 {
if (!done) {
let x_byte = x_bytes[31 - i];
let y_byte = y_bytes[31 - i];
let bytes_match = x_byte == y_byte;
if !bytes_match {
x_is_lt = x_byte < y_byte;
done = true;
}
}
}
x_is_lt
}
2 changes: 2 additions & 0 deletions noir_stdlib/src/lib.nr
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ mod array;
mod merkle;
mod schnorr;
mod ecdsa_secp256k1;
mod eddsa;
mod scalar_mul;
mod sha256;
mod sha512;
mod field;
mod ec;
mod unsafe;
mod collections;
mod compat;

#[builtin(println)]
fn println<T>(_input : T) {}