-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
ptau | ||
src/main | ||
src/test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"extension": ["ts"], | ||
"require": "ts-node/register", | ||
"spec": "./**/*.test.ts", | ||
"timeout": 100000, | ||
"exit": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 Ethereum Foundation | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<p align="center"> | ||
<h1 align="center"> | ||
ECDH | ||
</h1> | ||
<p align="center">A circuit to generate a shared secret from a private key and a public key on the Baby Jubjub curve.</p> | ||
</p> | ||
|
||
<p align="center"> | ||
<a href="https://github.com/privacy-scaling-explorations/zk-kit.circom"> | ||
<img src="https://img.shields.io/badge/project-zk--kit-blue.svg?style=flat-square"> | ||
</a> | ||
<a href="https://github.com/privacy-scaling-explorations/zk-kit.circom/tree/main/packages/ecdh/LICENSE"> | ||
<img alt="NPM license" src="https://img.shields.io/npm/l/%40zk-kit%2Fecdh?style=flat-square"> | ||
</a> | ||
<a href="https://www.npmjs.com/package/@zk-kit/ecdh.circom"> | ||
<img alt="NPM version" src="https://img.shields.io/npm/v/@zk-kit/ecdh.circom?style=flat-square" /> | ||
</a> | ||
<a href="https://npmjs.org/package/@zk-kit/ecdh.circom"> | ||
<img alt="Downloads" src="https://img.shields.io/npm/dm/@zk-kit/ecdh.circom.svg?style=flat-square" /> | ||
</a> | ||
</p> | ||
|
||
<div align="center"> | ||
<h4> | ||
<span> | </span> | ||
<a href="https://github.com/privacy-scaling-explorations/zk-kit.circom/issues/new/choose"> | ||
🔎 Issues | ||
</a> | ||
<span> | </span> | ||
<a href="https://discord.com/invite/sF5CT5rzrR"> | ||
🗣️ Chat & Support | ||
</a> | ||
</h4> | ||
</div> | ||
|
||
> [!WARNING] | ||
> This library has **not** been audited. | ||
## 🛠 Install | ||
|
||
Install the `@zk-kit/ecdh.circom` package with npm: | ||
|
||
```bash | ||
npm i @zk-kit/ecdh.circom --save | ||
``` | ||
|
||
or yarn: | ||
|
||
```bash | ||
yarn add @zk-kit/ecdh.circom | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"protocol": "groth16", | ||
"prime": "bn128", | ||
"version": "2.1.5", | ||
"circuits": "./circuits.json", | ||
"dirPtau": "./ptau", | ||
"dirCircuits": "./src", | ||
"dirInputs": "./inputs", | ||
"dirBuild": "./build", | ||
"optimization": 2, | ||
"inspect": true, | ||
"include": ["../../node_modules/circomlib/circuits"], | ||
"groth16numContributions": 1, | ||
"groth16askForEntropy": false, | ||
"logLevel": "INFO", | ||
"verbose": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"ecdh": { | ||
"file": "ecdh", | ||
"template": "Ecdh", | ||
"pubs": ["publicKey"], | ||
"params": [] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "@zk-kit/ecdh.circom", | ||
"version": "1.0.0-beta", | ||
"description": "A circuit to generate a shared secret from a private key and a public key on the Baby Jubjub curve.", | ||
"license": "MIT", | ||
"files": [ | ||
"src/**/*.circom", | ||
"!src/main", | ||
"!src/test", | ||
"LICENSE", | ||
"README.md" | ||
], | ||
"repository": "[email protected]:privacy-scaling-explorations/zk-kit.circom.git", | ||
"homepage": "https://github.com/privacy-scaling-explorations/zk-kit.circom/tree/main/packages/ecdh", | ||
"scripts": { | ||
"compile": "circomkit compile ecdh", | ||
"setup": "circomkit setup ecdh", | ||
"test": "mocha" | ||
}, | ||
"dependencies": { | ||
"circomlib": "^2.0.5" | ||
}, | ||
"devDependencies": { | ||
"@zk-kit/baby-jubjub": "^1.0.0-beta", | ||
"@zk-kit/eddsa-poseidon": "^1.0.0-beta", | ||
"@zk-kit/utils": "^1.0.0-beta.4", | ||
"circomkit": "^0.1.0", | ||
"mocha": "^10.2.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
pragma circom 2.1.5; | ||
|
||
// circomlib imports | ||
include "./bitify.circom"; | ||
include "./escalarmulany.circom"; | ||
|
||
// ECDH Is a a template which allows to generate a shared secret | ||
// from a private key and a public key | ||
// on the baby jubjub curve | ||
// It is important that the private key is hashed and pruned first | ||
// which can be accomplished using the function | ||
// deriveScalar from @zk-kit/baby-jubjub | ||
template Ecdh() { | ||
// the private key must pass through deriveScalar first | ||
signal input privateKey; | ||
signal input publicKey[2]; | ||
|
||
signal output sharedKey[2]; | ||
|
||
// convert the private key to its bits representation | ||
var out[253]; | ||
out = Num2Bits(253)(privateKey); | ||
|
||
// multiply the public key by the private key | ||
var mulFix[2]; | ||
mulFix = EscalarMulAny(253)(out, publicKey); | ||
|
||
// we can then wire the output to the shared secret signal | ||
sharedKey <== mulFix; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { Point, mulPointEscalar } from "@zk-kit/baby-jubjub" | ||
import { deriveSecretScalar } from "@zk-kit/eddsa-poseidon" | ||
import { Circomkit } from "circomkit" | ||
import { readFileSync } from "fs" | ||
import path from "path" | ||
|
||
const configFilePath = path.join(__dirname, "../circomkit.json") | ||
const config = JSON.parse(readFileSync(configFilePath, "utf-8")) | ||
|
||
// eslint-disable-next-line import/prefer-default-export | ||
export const circomkit = new Circomkit({ | ||
...config, | ||
verbose: false | ||
}) | ||
|
||
/** | ||
* Generates an Elliptic-Curve Diffie–Hellman (ECDH) shared key given a private | ||
* key and a public key. | ||
* @param privKey A private key generated using genPrivKey() | ||
* @param pubKey A public key generated using genPubKey() | ||
* @returns The ECDH shared key. | ||
*/ | ||
export const genEcdhSharedKey = (privKey: Buffer | Uint8Array | string, pubKey: [bigint, bigint]): Point<bigint> => { | ||
const secretScalar = deriveSecretScalar(privKey) | ||
|
||
return mulPointEscalar(pubKey, secretScalar) as Point<bigint> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { derivePublicKey, deriveSecretScalar } from "@zk-kit/eddsa-poseidon" | ||
import { crypto } from "@zk-kit/utils" | ||
import { WitnessTester } from "circomkit" | ||
import { circomkit, genEcdhSharedKey } from "./common" | ||
|
||
describe("ECDH Shared Key derivation circuit", () => { | ||
let circuit: WitnessTester<["privateKey", "publicKey"], ["sharedKey"]> | ||
|
||
before(async () => { | ||
circuit = await circomkit.WitnessTester("ecdh", { | ||
file: "ecdh", | ||
template: "Ecdh" | ||
}) | ||
}) | ||
|
||
it("should correctly compute an ECDH shared key", async () => { | ||
const privateKey1 = crypto.getRandomValues(32) | ||
const privateKey2 = crypto.getRandomValues(32) | ||
|
||
const publicKey2 = derivePublicKey(privateKey2) | ||
|
||
// generate a shared key between the first private key and the second public key | ||
const ecdhSharedKey = genEcdhSharedKey(privateKey1, publicKey2) | ||
|
||
const circuitInputs = { | ||
privateKey: deriveSecretScalar(privateKey1), | ||
publicKey: publicKey2 | ||
} | ||
|
||
await circuit.expectPass(circuitInputs, { sharedKey: [ecdhSharedKey[0], ecdhSharedKey[1]] }) | ||
}) | ||
|
||
it("should generate the same shared key from the same keypairs", async () => { | ||
const privateKey1 = crypto.getRandomValues(32) | ||
const privateKey2 = crypto.getRandomValues(32) | ||
const publicKey1 = derivePublicKey(privateKey1) | ||
const publicKey2 = derivePublicKey(privateKey2) | ||
|
||
// generate a shared key between the first private key and the second public key | ||
const ecdhSharedKey = genEcdhSharedKey(privateKey1, publicKey2) | ||
const ecdhSharedKey2 = genEcdhSharedKey(privateKey2, publicKey1) | ||
|
||
const circuitInputs = { | ||
privateKey: deriveSecretScalar(privateKey1), | ||
publicKey: publicKey2 | ||
} | ||
|
||
const circuitInputs2 = { | ||
privateKey: deriveSecretScalar(privateKey2), | ||
publicKey: publicKey1 | ||
} | ||
|
||
// calculate first time witness and check contraints | ||
const witness = await circuit.calculateWitness(circuitInputs) | ||
await circuit.expectConstraintPass(witness) | ||
|
||
const out = await circuit.readWitnessSignals(witness, ["sharedKey"]) | ||
await circuit.expectPass(circuitInputs, { sharedKey: ecdhSharedKey }) | ||
await circuit.expectPass(circuitInputs2, { sharedKey: out.sharedKey }) | ||
await circuit.expectPass(circuitInputs2, { sharedKey: ecdhSharedKey2 }) | ||
}) | ||
|
||
it("should generate the same ECDH key consistently for the same inputs", async () => { | ||
const secretScalar = deriveSecretScalar(crypto.getRandomValues(32)) | ||
const publicKey = derivePublicKey(crypto.getRandomValues(32)) | ||
|
||
const circuitInputs = { | ||
privateKey: secretScalar, | ||
publicKey | ||
} | ||
|
||
// calculate first time witness and check contraints | ||
const witness = await circuit.calculateWitness(circuitInputs) | ||
await circuit.expectConstraintPass(witness) | ||
|
||
// read out | ||
const out = await circuit.readWitnessSignals(witness, ["sharedKey"]) | ||
|
||
// calculate again | ||
await circuit.expectPass(circuitInputs, { sharedKey: out.sharedKey }) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters