Skip to content

Commit

Permalink
feat(eddsa-poseidon)!: make EdDSAPoseidon return bigints not strings
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Return type changes will require users to update their code.

re Fixes privacy-scaling-explorations#199
  • Loading branch information
artwyman committed Mar 15, 2024
1 parent 799884d commit 6d81cfb
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 153 deletions.
6 changes: 3 additions & 3 deletions packages/circuits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
},
"devDependencies": {
"@types/mocha": "^10.0.6",
"@zk-kit/baby-jubjub": "0.1.1",
"@zk-kit/eddsa-poseidon": "0.5.1",
"@zk-kit/poseidon-cipher": "0.1.1",
"@zk-kit/baby-jubjub": "0.3.0",
"@zk-kit/eddsa-poseidon": "0.9.0",
"@zk-kit/poseidon-cipher": "0.3.0",
"@zk-kit/smt": "1.0.0",
"@zk-kit/utils": "0.8.0",
"circomkit": "0.0.24",
Expand Down
8 changes: 2 additions & 6 deletions packages/circuits/tests/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ export const circomkit = new Circomkit({
* @param privateKey the private key to generate a public key from
* @returns the public key
*/
export const genPublicKey = (privateKey: bigint): [bigint, bigint] => {
const key = derivePublicKey(privateKey)

return key.map((x: string) => BigInt(x)) as [bigint, bigint]
}
export const genPublicKey = (privateKey: bigint): [bigint, bigint] => derivePublicKey(privateKey)

/**
* Generates an Elliptic-Curve Diffie–Hellman (ECDH) shared key given a private
Expand All @@ -54,7 +50,7 @@ export const genPublicKey = (privateKey: bigint): [bigint, bigint] => {
export const genEcdhSharedKey = (privKey: bigint, pubKey: [bigint, bigint]): Point<bigint> => {
const secretScalar = deriveSecretScalar(privKey)

return mulPointEscalar(pubKey, BigInt(secretScalar)) as Point<bigint>
return mulPointEscalar(pubKey, secretScalar) as Point<bigint>
}

/**
Expand Down
8 changes: 4 additions & 4 deletions packages/circuits/tests/ecdh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe("ECDH Shared Key derivation circuit", () => {
const ecdhSharedKey = genEcdhSharedKey(bgPrivateKey1, publicKey2)

const circuitInputs = {
privateKey: BigInt(deriveSecretScalar(bgPrivateKey1)),
privateKey: deriveSecretScalar(bgPrivateKey1),
publicKey: publicKey2
}

Expand All @@ -45,12 +45,12 @@ describe("ECDH Shared Key derivation circuit", () => {
const ecdhSharedKey2 = genEcdhSharedKey(bgPrivateKey2, publicKey1)

const circuitInputs = {
privateKey: BigInt(deriveSecretScalar(bgPrivateKey1)),
privateKey: deriveSecretScalar(bgPrivateKey1),
publicKey: publicKey2
}

const circuitInputs2 = {
privateKey: BigInt(deriveSecretScalar(bgPrivateKey2)),
privateKey: deriveSecretScalar(bgPrivateKey2),
publicKey: publicKey1
}

Expand All @@ -65,7 +65,7 @@ describe("ECDH Shared Key derivation circuit", () => {
})

it("should generate the same ECDH key consistently for the same inputs", async () => {
const privateKey1 = BigInt(deriveSecretScalar(Buffer.from(crypto.getRandomValues(32))))
const privateKey1 = deriveSecretScalar(Buffer.from(crypto.getRandomValues(32)))
const privateKey2 = crypto.getRandomValues(32)
const publicKey2 = genPublicKey(beBufferToBigInt(Buffer.from(privateKey2)))

Expand Down
2 changes: 1 addition & 1 deletion packages/circuits/tests/eddsa-proof.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe("eddsa-proof", () => {
const commitment = poseidon2(publicKey)

const INPUT = {
secret: BigInt(deriveSecretScalar(secret)),
secret: deriveSecretScalar(secret),
scope
}

Expand Down
14 changes: 7 additions & 7 deletions packages/eddsa-poseidon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ const publicKey = derivePublicKey(privateKey)

/*
[
'17191193026255111087474416516591393721975640005415762645730433950079177536248',
'13751717961795090314625781035919035073474308127816403910435238282697898234143'
17191193026255111087474416516591393721975640005415762645730433950079177536248,
13751717961795090314625781035919035073474308127816403910435238282697898234143
]
*/
console.log(publicKey)
Expand All @@ -124,10 +124,10 @@ const signature = signMessage(privateKey, message)
/*
{
R8: [
'12949573675545142400102669657964360005184873166024880859462384824349649539693',
'18253636630408169174294927826710424418689461166073329946402765380454102840608'
12949573675545142400102669657964360005184873166024880859462384824349649539693,
18253636630408169174294927826710424418689461166073329946402765380454102840608
],
S: '701803947557694254685424075312408605924670918868054593580245088593184746870'
S: 701803947557694254685424075312408605924670918868054593580245088593184746870
}
*/
console.log(signature)
Expand Down Expand Up @@ -157,8 +157,8 @@ const unpackedPublicKey = unpackPublicKey(packedPublicKey)

/*
[
'17191193026255111087474416516591393721975640005415762645730433950079177536248',
'13751717961795090314625781035919035073474308127816403910435238282697898234143'
17191193026255111087474416516591393721975640005415762645730433950079177536248,
13751717961795090314625781035919035073474308127816403910435238282697898234143
]
*/
console.log(unpackedPublicKey)
Expand Down
41 changes: 19 additions & 22 deletions packages/eddsa-poseidon/src/eddsa-poseidon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { hash as blake, checkMessage, checkPrivateKey, isPoint, isSignature, pru
* @param privateKey The EdDSA private key for generating the associated public key.
* @returns The derived secret scalar to be used to calculate public key and optimized for circuit calculations.
*/
export function deriveSecretScalar(privateKey: BigNumberish): string {
export function deriveSecretScalar(privateKey: BigNumberish): bigint {
// Convert the private key to buffer.
privateKey = checkPrivateKey(privateKey)

Expand All @@ -40,7 +40,7 @@ export function deriveSecretScalar(privateKey: BigNumberish): string {
hash = hash.slice(0, 32)
hash = pruneBuffer(hash)

return scalar.shiftRight(leBufferToBigInt(hash), BigInt(3)).toString()
return scalar.shiftRight(leBufferToBigInt(hash), BigInt(3))
}

/**
Expand All @@ -52,13 +52,13 @@ export function deriveSecretScalar(privateKey: BigNumberish): string {
* @param privateKey The private key used for generating the public key.
* @returns The derived public key.
*/
export function derivePublicKey(privateKey: BigNumberish): Point<string> {
export function derivePublicKey(privateKey: BigNumberish): Point<bigint> {
const s = deriveSecretScalar(privateKey)

const publicKey = mulPointEscalar(Base8, BigInt(s))
const publicKey = mulPointEscalar(Base8, s)

// Convert the public key values to strings so that it can easily be exported as a JSON.
return [publicKey[0].toString(), publicKey[1].toString()]
return [publicKey[0], publicKey[1]]
}

/**
Expand All @@ -68,7 +68,7 @@ export function derivePublicKey(privateKey: BigNumberish): Point<string> {
* @param message The message to be signed.
* @returns The signature object, containing properties relevant to EdDSA signatures, such as 'R8' and 'S' values.
*/
export function signMessage(privateKey: BigNumberish, message: BigNumberish): Signature<string> {
export function signMessage(privateKey: BigNumberish, message: BigNumberish): Signature<bigint> {
// Convert the private key to buffer.
privateKey = checkPrivateKey(privateKey)

Expand All @@ -93,10 +93,7 @@ export function signMessage(privateKey: BigNumberish, message: BigNumberish): Si
const S = Fr.add(r, Fr.mul(hm, s))

// Convert the signature values to strings so that it can easily be exported as a JSON.
return {
R8: [R8[0].toString(), R8[1].toString()],
S: S.toString()
}
return { R8, S }
}

/**
Expand Down Expand Up @@ -145,15 +142,15 @@ export function verifySignature(message: BigNumberish, signature: Signature, pub
* @param publicKey The public key to be packed.
* @returns A string representation of the packed public key.
*/
export function packPublicKey(publicKey: Point): string {
export function packPublicKey(publicKey: Point): bigint {
if (!isPoint(publicKey) || !inCurve(publicKey)) {
throw new Error("Invalid public key")
}

// Convert the public key values to big integers for calculations.
const _publicKey: Point<bigint> = [BigInt(publicKey[0]), BigInt(publicKey[1])]

return packPoint(_publicKey).toString()
return packPoint(_publicKey)
}

/**
Expand All @@ -162,7 +159,7 @@ export function packPublicKey(publicKey: Point): string {
* @param publicKey The packed public key as a bignumberish.
* @returns The unpacked public key as a point.
*/
export function unpackPublicKey(publicKey: BigNumberish): Point<string> {
export function unpackPublicKey(publicKey: BigNumberish): Point<bigint> {
requireBigNumberish(publicKey, "publicKey")

const unpackedPublicKey = unpackPoint(bigNumberishToBigInt(publicKey))
Expand All @@ -171,7 +168,7 @@ export function unpackPublicKey(publicKey: BigNumberish): Point<string> {
throw new Error("Invalid public key")
}

return [unpackedPublicKey[0].toString(), unpackedPublicKey[1].toString()]
return [unpackedPublicKey[0], unpackedPublicKey[1]]
}

/**
Expand Down Expand Up @@ -210,7 +207,7 @@ export function packSignature(signature: Signature): Buffer {
* @param packedSignature the 64 byte buffer to unpack
* @returns a Signature with numbers in string form
*/
export function unpackSignature(packedSignature: Buffer): Signature<string> {
export function unpackSignature(packedSignature: Buffer): Signature<bigint> {
requireBuffer(packedSignature, "packedSignature")
if (packedSignature.length !== 64) {
throw new Error("Packed signature must be 64 bytes")
Expand All @@ -223,8 +220,8 @@ export function unpackSignature(packedSignature: Buffer): Signature<string> {
throw new Error(`Invalid packed signature point ${sliceS.toString("hex")}.`)
}
return {
R8: [unpackedR8[0].toString(), unpackedR8[1].toString()],
S: leBufferToBigInt(sliceS).toString()
R8: [unpackedR8[0], unpackedR8[1]],
S: leBufferToBigInt(sliceS)
}
}

Expand All @@ -236,11 +233,11 @@ export class EdDSAPoseidon {
// Private key for signing, stored securely.
privateKey: BigNumberish
// The secret scalar derived from the private key to compute the public key.
secretScalar: string
secretScalar: bigint
// The public key corresponding to the private key.
publicKey: Point
publicKey: Point<bigint>
// A packed (compressed) representation of the public key for efficient operations.
packedPublicKey: string
packedPublicKey: bigint

/**
* Initializes a new instance, deriving necessary cryptographic parameters from the provided private key.
Expand All @@ -251,15 +248,15 @@ export class EdDSAPoseidon {
this.privateKey = privateKey
this.secretScalar = deriveSecretScalar(privateKey)
this.publicKey = derivePublicKey(privateKey)
this.packedPublicKey = packPublicKey(this.publicKey) as string
this.packedPublicKey = packPublicKey(this.publicKey)
}

/**
* Signs a given message using the private key and returns the signature.
* @param message The message to be signed.
* @returns The signature of the message.
*/
signMessage(message: BigNumberish): Signature<string> {
signMessage(message: BigNumberish): Signature<bigint> {
return signMessage(this.privateKey, message)
}

Expand Down
Loading

0 comments on commit 6d81cfb

Please sign in to comment.