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

feat: implement ECDH #8

Merged
merged 29 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0d3b065
ECDH Basics, tsconfig.json - No tests yet
Jul 26, 2024
a6ec58f
feat(ecdh): eCDH Encryption without internal tests
Jul 26, 2024
5bab3bb
feat(ecdh): ds
Jul 29, 2024
3502e23
feat(circuit): ds
Jul 29, 2024
3b4cba8
feat(circuit): ds
Jul 29, 2024
399ced1
feat(circuit): new Improved Circuit
Jul 29, 2024
d1be79c
refactor: noir Tests in JS
Jul 29, 2024
0d957d9
feat(ecdh): yO
Jul 30, 2024
120fd63
feat(ecdh): ds
Jul 30, 2024
ed1c46e
feat(ecdh): eCDH Test
Jul 30, 2024
f8f046f
Basic Unit Test Added
Aug 5, 2024
4d880f1
Formatted yarn fmt
Aug 5, 2024
25068d4
feat(ecdh): hI
Aug 5, 2024
820bb61
feat(ecdh): k
Aug 6, 2024
3c26856
refactor: l
Aug 11, 2024
9960f44
refactor(ecdh): Added two more tests, ECC BabyJubJub
Aug 12, 2024
83878f7
refactor(ecdh): NoirJS
Aug 13, 2024
696fb69
refactor(ecdh): README UPDATED
Aug 17, 2024
6375464
refactor(ecdh): refactor: mocha test files, test file
Aug 23, 2024
1385f9e
refactor(ecdh): refactor: package.json, .toml files
Aug 26, 2024
40dab0e
refactor(ecdh): refactor - .toml, lib.nr and main.nr in ECDH
Aug 26, 2024
fa95ff4
refactor(ecdh): refactor: package.json
Aug 26, 2024
b4c0027
refactor(ecdh): refactor: globals, lib, ecdh.test.ts
Aug 26, 2024
2a6bd28
refactor(ecdh): refactor: ecdh.test.ts
Aug 26, 2024
5d69406
refactor(ecdh): refactor: yarn fmt
Aug 26, 2024
973e3b7
refactor(ecdh): refactor: .gitignore added target
Aug 26, 2024
0ef2486
refactor(ecdh): refactor: removed wait times in test.ts
Aug 26, 2024
115004f
refactor(ecdh): git commit -m "refactor: package.json"
Aug 27, 2024
116894c
refactor(ecdh): refactor: yarn.lock, package.json
Aug 27, 2024
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
1 change: 1 addition & 0 deletions .husky/commit-msg
YashBit marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
. "$(dirname -- "$0")/_/husky.sh"

npx --no-install commitlint --edit $1

3 changes: 2 additions & 1 deletion Nargo.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[workspace]
members = ["packages/merkle-trees"]
compiler_version = ">=0.31.0"
members = ["packages/ecdh"]
YashBit marked this conversation as resolved.
Show resolved Hide resolved
19 changes: 15 additions & 4 deletions package.json
sripwoud marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,23 @@
],
"packageManager": "[email protected]",
"devDependencies": {
"@commitlint/cli": "^18.6.1",
"@commitlint/config-conventional": "^18.6.2",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@types/chai": "^4",
"@types/mocha": "^10",
"changelogithub": "patch:changelogithub@npm%3A0.13.3#~/.yarn/patches/changelogithub-npm-0.13.3-1783949906.patch",
"czg": "^1.9.1",
"dprint": "^0.46.3",
"husky": "^9.0.11",
"lint-staged": "^15.2.2"
"husky": "4",
sripwoud marked this conversation as resolved.
Show resolved Hide resolved
"lint-staged": "^15.2.2",
"ts-node": "^10.9.2",
"typescript": "^5.5.4"
},
"dependencies": {
"@noir-lang/backend_barretenberg": "^0.30.0",
"@noir-lang/noir_js": "^0.30.0",
"@noir-lang/noir_wasm": "^0.32.0",
"chai": "^4.5.0",
"mocha": "^10.7.0"
YashBit marked this conversation as resolved.
Show resolved Hide resolved
}
}
7 changes: 7 additions & 0 deletions packages/ecdh/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "ecdh"
type = "lib"
authors = ["YashBit"]
compiler_version = ">=0.27.0"

[dependencies]
77 changes: 77 additions & 0 deletions packages/ecdh/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use dep::std::ec::tecurve::affine::{Curve, 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
}

/// Generates a public key from a private key using the Baby JubJub curve.
/// # Arguments
/// * `private_key` - A field element representing the private key.
/// * `base_point` - A point on the Baby JubJub curve used as the base point.
/// # Returns
/// A `Point` on the Baby JubJub curve representing the public key.
fn generate_public_key(private_key: Field, base_point: Point) -> Point {
YashBit marked this conversation as resolved.
Show resolved Hide resolved
let baby_jubjub_curve = Curve::new(168700, 168696, base_point);
baby_jubjub_curve.mul(private_key, base_point)
}

// ECDH Circuit
fn main(private_key1: [u8; 32], private_key2: [u8; 32]) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's a bit confusing that this is a lib but has a main function, can this be renamed? Something like generate_shared

Copy link
Member

Choose a reason for hiding this comment

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

I think here we need to have a main function and a package of type bin, don't we @signorecello?
Because we do want to compile something: we need the compilation artifact for the node test.

Or is there another way?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I mean we shouldn't name libraries according to their use in tests... For the node test we would actually write a bin project and compile that one

Copy link
Collaborator

Choose a reason for hiding this comment

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

@YashBit saw you resolved this one, but idk what's your opinion

let base_point = Point::new(
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203,
);
let private_key3 = field_from_bytes(private_key1, true);
let private_key4 = field_from_bytes(private_key2, true);
let public_key1 = generate_public_key(private_key3, base_point);
let public_key2 = generate_public_key(private_key4, base_point);
// Generate Both ECDH Shared Keys - Scalar Multiply
let shared_key1 = generate_public_key(private_key4, public_key1);
let shared_key2 = generate_public_key(private_key3, public_key2);
assert(shared_key1 == shared_key2);
YashBit marked this conversation as resolved.
Show resolved Hide resolved
}

// @@@@@@ UNIT TESTS

// Test -> Generate Public Key
// #[test]
// // fn public_multiply_correct() {
// // let base_point = Point::new(
// // 5299619240641551281634865583518297030282874472190772894086521144482721001553,
// // 16950150798460657717958625567821834550301663161624707787222815936182638968203,
// // );
// // let result = generate_public_key(2, base_point);
// // assert(result == );

// // }
YashBit marked this conversation as resolved.
Show resolved Hide resolved

/// Test that the `field_from_bytes` function correctly converts a 32-byte array of zeroes to a field element with a value of `0`.
///
/// This test ensures that:
/// - The input is a 32-byte array initialized with zeroes.
/// - The `field_from_bytes` function is called with the input and a boolean flag set to `true`.
/// - The output is asserted to be `0`, verifying that the conversion is correct.
#[test]
// Define the test function for `field_from_bytes`
fn field_from_bytes_correct() {
let bytes: [u8; 32] = [0; 32];
let field_result = field_from_bytes(bytes, true);
assert_eq(field_result, 0);
}
39 changes: 39 additions & 0 deletions packages/ecdh/target/ecdh.json
sripwoud marked this conversation as resolved.
Show resolved Hide resolved
YashBit marked this conversation as resolved.
Show resolved Hide resolved

Large diffs are not rendered by default.

85 changes: 85 additions & 0 deletions packages/ecdh/tests/ecdh.tests.ts
YashBit marked this conversation as resolved.
Show resolved Hide resolved
sripwoud marked this conversation as resolved.
Show resolved Hide resolved
YashBit marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'
import { Noir } from '@noir-lang/noir_js'
import { compile } from '@noir-lang/noir_wasm'
import { ProofData } from '@noir-lang/types'
import { expect } from 'chai'
import { randomBytes } from 'crypto'
import { readFileSync } from 'fs'
import { resolve } from 'path'
import 'mocha'
import circuit_ecdh from '../../ecdh/target/ecdh.json'

// RUN: npx mocha -r ts-node/register tests/ecdh.tests.ts
// This will not run with yarn tests

function generatePrivateKey(): Uint8Array {
return randomBytes(32)
}

describe('ECDH Circuit Tests', function() {
let noir: Noir
let backend: BarretenbergBackend
let correctProof: ProofData
beforeEach(async () => {
const circuitFile = readFileSync(resolve(__dirname, '../target/ecdh.json'), 'utf-8')
const circuit = JSON.parse(circuitFile)
backend = new BarretenbergBackend(circuit)
noir = new Noir(circuit, backend)
})
it('Should generate valid proof for correct input', async function() {
this.timeout(20000) // Optional: Increase timeout if needed

let pk1 = generatePrivateKey()
let pk2 = generatePrivateKey()

// Convert Uint8Array to regular arrays
const input = {
private_key1: Array.from(pk1),
private_key2: Array.from(pk2),
}

// Generate proof
let correctProof
try {
correctProof = await noir.generateProof(input)
console.log('Proof generated:', correctProof)
YashBit marked this conversation as resolved.
Show resolved Hide resolved
} catch (error) {
console.error('Error generating proof:', error)
throw error // Ensure errors are not swallowed
}
YashBit marked this conversation as resolved.
Show resolved Hide resolved

// Assert that correctProof is defined and has the expected structure
expect(correctProof).to.not.be.undefined
expect(correctProof.proof instanceof Uint8Array).to.be.true
})
})

// describe("ECDH Circuit Tests", function() {
// let noir: Noir;
// let correctProof: ProofData;
// beforeEach(async () => {
// const circuitFile = readFileSync(resolve('../target/ecdh.json'), 'utf-8');
// const circuit = JSON.parse(circuitFile);
// const backend = new BarretenbergBackend(circuit);
// noir = new Noir(circuit, backend);
// });
// it('Should generate valid proof for correct input', async () => {

// let pk1 = generatePrivateKey();
// let pk2 = generatePrivateKey();
// const input = {
// private_key1: Array.from(pk1),
// private_key2: Array.from(pk2)
// };

// // Generate proof
// correctProof = await noir.generateProof(input);
// expect(correctProof.proof).to.be.true;
// });

// it('Should verify valid proof for correct input', async () => {
// const verification = await noir.verifyProof(correctProof);
// expect(verification).to.be.true;
// });

// });
20 changes: 20 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"outDir": "./dist",
"rootDir": ".",
"module": "commonjs",
"target": "es6",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true, // Add this line
"types": ["mocha", "node"]
},
"include": [
"./src/**/*.ts",
"./tests/**/*.ts"
],
"exclude": [
"./dist"
]
}
Loading
Loading