Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring ecdh to work properly as a lib, extending it to use with other curves #29

Merged
merged 5 commits into from
Feb 20, 2025
Merged
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
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
bun-version: latest
- uses: noir-lang/noirup@v0.1.3
with:
toolchain: 0.39.0
toolchain: 1.0.0-beta.1
- run: bun i
- run: bun fmt

Expand All @@ -44,5 +44,5 @@ jobs:
- uses: actions/checkout@v4
- uses: noir-lang/noirup@v0.1.3
with:
toolchain: 0.39.0
toolchain: 1.0.0-beta.1
- run: nargo test
7 changes: 3 additions & 4 deletions packages/ecdh/Nargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
[package]
name = "ecdh"
type = "bin"
authors = ["YashBit"]
compiler_version = ">=0.39.0"
type = "lib"
authors = ["YashBit", "signorecello"]

[dependencies]
ec = { tag = "v0.1.2", git = "https://github.com/noir-lang/ec" }
ec = { tag = "master", git = "https://github.com/noir-lang/ec" }
68 changes: 0 additions & 68 deletions packages/ecdh/Prover.toml

This file was deleted.

39 changes: 16 additions & 23 deletions packages/ecdh/README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,28 @@
# ECDH Library using Baby JubJub Curve
# ECDH Library

This repository introduces a set of functions and utilities for elliptic curve cryptography using the Baby JubJub curve. The library provides essential operations for the Elliptic Curve Diffie-Hellman (ECDH) protocol, along with utility functions for key generation, field element conversion, and shared key computation.
This repository introduces a set of functions and utilities for elliptic curve cryptography using. The library provides essential operations for the Elliptic Curve Diffie-Hellman (ECDH) protocol, along with utility functions for key generation, field element conversion, and shared key computation.

## Features

- **Byte Array to Field Element Conversion:** Utility functions to convert byte arrays into field elements for use in elliptic curve operations.
- **Public Key Generation:** Generate public keys from private keys using the Baby JubJub curve, with both standard and optimized methods.
- **Shared Key Computation:** Compute shared keys for secure communication using the ECDH protocol.
- **Main Function:** A main function to generate ECDH shared keys, demonstrating the usage of the library.
- **Testing:** Comprehensive tests to verify the correctness of key derivation and field conversion functions.

## Compiling the Circuit
At the moment only Baby JubJub is supported, feel free to contribute with more curves.

To compile the circuit, navigate one directory above the source code and run the following command:
## Features

```bash
nargo compile
```
- **Public Key Generation:** Generate public keys from private keys.
- **Shared Key Computation:** Compute shared keys for secure communication.

## Running Tests
## Usage

To run the tests for this library, use the following command:
To use this library, add the dependency to your `Nargo.toml`:

```bash
bun run test
```toml
ecdh = { git = "https://github.com/privacy-scaling-explorations/zk-kit.noir", tag = "main", directory = "packages/ecdh" }
```

## Running Tests with Mocha
You can then import the ECDH implementation for the curve you're working with, like so:

To run the tests using Mocha with TypeScript, use the following command:
```rust
use ecdh::bjj::BJJ; // only Baby JubJub is supported at the moment
let ecdh = BJJ::new(your_private_key);
let public_key = ecdh.derive_public_key();

```bash
npx mocha -r ts-node/register tests/ecdh.tests.ts
let shared_key = ecdh.derive_shared_key(someone_elses_public_key);
```
24 changes: 24 additions & 0 deletions packages/ecdh/src/bjj.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::ECDHTrait;
use ec::consts::te::{baby_jubjub, BabyJubjub};
use ec::tecurve::affine::Point;

pub struct BJJ {
pub private_key: Field,
pub bjj: BabyJubjub,
}

impl ECDHTrait for BJJ {
fn new(private_key: Field) -> Self {
let bjj = baby_jubjub();
Self { bjj, private_key }
}

fn derive_public_key(self) -> Point {
self.bjj.curve.mul(self.private_key, self.bjj.base8)
}

fn derive_shared_key(self, public_key: Point) -> Field {
let shared_key = self.bjj.curve.mul(self.private_key, public_key);
shared_key.x
}
}
6 changes: 0 additions & 6 deletions packages/ecdh/src/globals.nr

This file was deleted.

62 changes: 6 additions & 56 deletions packages/ecdh/src/lib.nr
Original file line number Diff line number Diff line change
@@ -1,58 +1,8 @@
mod globals;
use ec::tecurve::affine::{Curve, Point};
mod bjj;
use ec::tecurve::affine::Point;

// @@@@@@ Core ECDH Implementation

/// Converts a byte array to a field element.
/// # Arguments
/// * `bytes` - A fixed-size array of 32 bytes.
/// * `big_endian` - A boolean indicating if the byte array is in big-endian format.
/// # Returns
/// A `Field` element representing the converted byte array.
pub fn field_from_bytes(bytes: [u8; 32], big_endian: bool) -> Field {
let mut as_field: Field = 0;
let mut offset: Field = 1;

for i in 0..32 {
let index = if big_endian { 31 - i } else { i };
as_field += (bytes[index] as Field) * offset;
offset *= 256;
}

as_field
}

/// Computes a public key from a private key using the Baby JubJub curve.
/// # Arguments
/// * `private_key` - The private key as a `Field` element.
/// # Returns
/// The corresponding `Point` on the Baby JubJub curve.
pub fn derive_public_key(private_key: Field) -> Point {
let base_point = Point::new(
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203,
);
let baby_jubjub_curve = Curve::new(168700, 168696, base_point);
baby_jubjub_curve.mul(private_key, base_point)
}

/// Optimized public key derivation using Baby JubJub curve.
/// # Arguments
/// * `private_key` - The private key as a `Field` element.
/// # Returns
/// The public key as a `Point` on the Baby JubJub curve.
pub fn derive_public_key_optimized(private_key: Field) -> Point {
let X = globals::BJJ.curve.mul(private_key, globals::G);
X
}

/// Computes a shared secret key using ECDH with the Baby JubJub curve.
/// # Arguments
/// * `private_key` - The private key as a `Field` element.
/// * `public_key` - The public key as a `Point` on the Baby JubJub curve.
/// # Returns
/// The shared secret key as a `Field` element.
pub fn derive_shared_key(private_key: Field, public_key: Point) -> Field {
let shared_key = globals::BJJ.curve.mul(private_key, public_key);
shared_key.x
pub trait ECDHTrait {
fn new(private_key: Field) -> Self;
fn derive_public_key(self) -> Point;
fn derive_shared_key(self, public_key: Point) -> Field;
}
45 changes: 0 additions & 45 deletions packages/ecdh/src/main.nr

This file was deleted.

47 changes: 0 additions & 47 deletions packages/ecdh/tests/ecdh.test.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/merkle-trees/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@
name = "merkle_trees"
type = "lib"
authors = ["fabianschu", "signorecello"]
compiler_version = ">=0.39.0"
9 changes: 5 additions & 4 deletions tests/Nargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
[package]
name = "merkle_trees"
name = "zk_kit_tests"
type = "lib"
authors = ["fabianschu", "signorecello"]
compiler_version = ">=0.39.0"
authors = ["signorecello"]

[dependencies]
bignum = { git = "https://github.com/noir-lang/noir-bignum", tag = "zpedro/default_trait" }
bignum = { git = "https://github.com/noir-lang/noir-bignum", tag = "main" }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi, this will break pretty much immediately. Pulling whatever is latest on master seems like a really bad idea.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah should've picked a version. Let's see what happens

trees = { path = "../packages/merkle-trees" }
ecdh = { path = "../packages/ecdh" }
ec = { tag = "master", git = "https://github.com/noir-lang/ec" }
30 changes: 30 additions & 0 deletions tests/src/ecdh/mod.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use ec::tecurve::affine::Point;
use ecdh::bjj::BJJ;

global alice_sk: Field = 0x60c0102756aac2cf5d7277792a469bff83dfe3d3e7e50ad5a55383f3a89283e;
global bob_sk: Field = 0x86cdaad8886954a2eb20142fb98468d476a2d6c7b2c571af42cdc041b1a923c;

#[test]
fn test_pk() {
let ecdh = BJJ::new(alice_sk);
let expected_pk = Point::new(
0x17d6ff45a37eee4ca071bb451c09b47184ed67492c6bac9279fb0a7d2d4ad1dc,
0x02d3a6338eee1ae8a38b278ce6c13179889c780f5e0d7294b904b0fa52c7dc3e,
);
let pk = ecdh.derive_public_key();
assert(pk == expected_pk);
}

#[test]
fn test_shared_k() {
let alice_ecdh = BJJ::new(alice_sk);
let bob_ecdh = BJJ::new(bob_sk);

let alice_pk: Point = alice_ecdh.derive_public_key();
let bob_pk: Point = bob_ecdh.derive_public_key();

let shared_key_with_bob = alice_ecdh.derive_shared_key(bob_pk);
let shared_key_with_alice = bob_ecdh.derive_shared_key(alice_pk);

assert(shared_key_with_bob == shared_key_with_alice);
}
1 change: 1 addition & 0 deletions tests/src/lib.nr
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
mod mt;
mod smt;
mod ecdh;
Loading