-
Notifications
You must be signed in to change notification settings - Fork 74
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
refactor(eddsa-poseidon)!: restrict message types #318
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import { Point } from "@zk-kit/baby-jubjub" | ||
import type { BigNumberish } from "@zk-kit/utils" | ||
import { type BigNumberish } from "@zk-kit/utils" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I honestly don't know what this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Imports could be values or types. TS can infer what kind of import that is but the |
||
import { bigNumberishToBigInt, bufferToBigInt } from "@zk-kit/utils/conversions" | ||
import { requireTypes } from "@zk-kit/utils/error-handlers" | ||
import { isArray, isBigNumber, isBigNumberish, isObject } from "@zk-kit/utils/type-checks" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import { babyjub, eddsa } from "circomlibjs" | ||
import { Buffer } from "buffer" | ||
import { crypto } from "@zk-kit/utils" | ||
import { bufferToBigInt, crypto } from "@zk-kit/utils" | ||
import { utils } from "ffjavascript" | ||
import { r, packPoint, Point } from "@zk-kit/baby-jubjub" | ||
import { | ||
|
@@ -84,7 +84,7 @@ | |
it("Should sign a message (number)", async () => { | ||
const message = 22 | ||
|
||
const signature = signMessage(privateKey, message) | ||
const signature = signMessage(privateKey, BigInt(message)) | ||
|
||
const circomlibSignature = eddsa.signPoseidon(privateKey, BigInt(message)) | ||
|
||
|
@@ -96,7 +96,7 @@ | |
it("Should sign a message (hexadecimal)", async () => { | ||
const message = "0x12" | ||
|
||
const signature = signMessage(privateKey, message) | ||
const signature = signMessage(privateKey, BigInt(message)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a stringified bigint, so should be accepted as a BigNumber without explicit conversion. I also suggest adding another test case with a decimal string like "123" which should also work. Anything parsable by BigInt(s) should work. |
||
|
||
const circomlibSignature = eddsa.signPoseidon(privateKey, BigInt(message)) | ||
|
||
|
@@ -108,7 +108,7 @@ | |
it("Should sign a message (buffer)", async () => { | ||
const message = Buffer.from("message") | ||
|
||
const signature = signMessage(privateKey, message) | ||
const signature = signMessage(privateKey, bufferToBigInt(message)) | ||
|
||
const circomlibSignature = eddsa.signPoseidon(privateKey, BigInt(`0x${message.toString("hex")}`)) | ||
|
||
|
@@ -117,7 +117,7 @@ | |
expect(signature.S).toBe(circomlibSignature.S) | ||
}) | ||
|
||
it("Should sign a message (string)", async () => { | ||
it("Should sign a message if less than 32 bytes (string)", async () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this case shouldn't be supported without an explicit conversion to bigint |
||
const message = "message" | ||
|
||
const signature = signMessage(privateKey, message) | ||
|
@@ -129,6 +129,13 @@ | |
expect(signature.S).toBe(circomlibSignature.S) | ||
}) | ||
|
||
it("Should fail if message is larger than 32 bytes (string)", async () => { | ||
const message = bufferToBigInt(Buffer.from(crypto.getRandomValues(34))) | ||
|
||
const fun = () => signMessage(privateKey, message) | ||
expect(fun).toThrow("Size 32 is too small, need at least 33 bytes") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test is failing on GitHub |
||
}) | ||
|
||
it("Should throw an error if the message type is not supported", async () => { | ||
const message = true | ||
|
||
|
@@ -346,7 +353,7 @@ | |
expect(fun).toThrow("Invalid packed signature point") | ||
}) | ||
|
||
it("Should still unpack a packed signature with scalar malformed", async () => { | ||
const signature = signMessage(privateKey, message) | ||
|
||
const packedSignature = packSignature(signature) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the intent here is to change not only the types but the handling and checking of the inputs here. A BigNumber is limited to bigint or a stringified bigint (not an arbitrary string, not a buffer). The checkMessage function is the place where you should be checking that and converting to bigint appropriately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also per @cedoor's comment on #230 there should be some documentation above about the fact that the message is a single BabyJub field element, represented as a bigint. Best-practice for users with other types of input is probably to hash it (e.g. with a poseidon hash), or encode their inputs bytes directly if small enough (e.g. using bufferToBigInt()).