Skip to content

Commit b7d58bd

Browse files
committed
refactor: hash message and scope
1 parent 4d4a31c commit b7d58bd

File tree

7 files changed

+49
-13
lines changed

7 files changed

+49
-13
lines changed

packages/contracts/contracts/Semaphore.sol

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity 0.8.4;
33

44
import "./interfaces/ISemaphore.sol";
55
import "./interfaces/ISemaphoreVerifier.sol";
6-
import "./base/SemaphoreGroups.sol";
6+
import {SemaphoreGroups} from "./base/SemaphoreGroups.sol";
77

88
/// @title Semaphore
99
/// @dev This contract uses the Semaphore base contracts to provide a complete service
@@ -189,7 +189,7 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
189189
[proof[0], proof[1]],
190190
[[proof[2], proof[3]], [proof[4], proof[5]]],
191191
[proof[6], proof[7]],
192-
[merkleTreeRoot, nullifier, message, scope]
192+
[merkleTreeRoot, nullifier, _hash(message), _hash(scope)]
193193
)
194194
) {
195195
revert Semaphore__InvalidProof();
@@ -199,4 +199,11 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
199199

200200
emit ProofVerified(groupId, merkleTreeRoot, nullifier, message, scope, proof);
201201
}
202+
203+
/// @dev Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
204+
/// @param message: Message to be hashed.
205+
/// @return Message digest.
206+
function _hash(uint256 message) private pure returns (uint256) {
207+
return uint256(keccak256(abi.encodePacked(message))) >> 8;
208+
}
202209
}

packages/proof/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"access": "public"
3131
},
3232
"devDependencies": {
33+
"@ethersproject/strings": "^5.7.0",
3334
"@rollup/plugin-commonjs": "^24.1.0",
3435
"@rollup/plugin-json": "^5.0.1",
3536
"@rollup/plugin-node-resolve": "^15.0.2",
@@ -46,6 +47,9 @@
4647
"@semaphore-protocol/identity": "3.15.2"
4748
},
4849
"dependencies": {
50+
"@ethersproject/bignumber": "^5.7.0",
51+
"@ethersproject/bytes": "^5.7.0",
52+
"@ethersproject/keccak256": "^5.7.0",
4953
"@zk-kit/groth16": "0.5.0",
5054
"download": "^8.0.0",
5155
"tmp": "^0.2.1"

packages/proof/src/generate-proof.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import { BigNumber } from "@ethersproject/bignumber"
2+
import { BytesLike, Hexable } from "@ethersproject/bytes"
13
import { Group } from "@semaphore-protocol/group"
24
import type { Identity } from "@semaphore-protocol/identity"
3-
import { prove } from "@zk-kit/groth16"
5+
import { NumericString, prove } from "@zk-kit/groth16"
46
import getSnarkArtifacts from "./get-snark-artifacts.node"
7+
import hash from "./hash"
58
import packProof from "./pack-proof"
6-
import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types"
9+
import { SemaphoreProof, SnarkArtifacts } from "./types"
710

811
/**
912
* Generates a Semaphore proof.
@@ -18,8 +21,8 @@ import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types"
1821
export default async function generateProof(
1922
identity: Identity,
2023
group: Group,
21-
message: BigNumberish,
22-
scope: BigNumberish,
24+
message: BytesLike | Hexable | number | bigint,
25+
scope: BytesLike | Hexable | number | bigint,
2326
treeDepth?: number,
2427
snarkArtifacts?: SnarkArtifacts
2528
): Promise<SemaphoreProof> {
@@ -54,8 +57,8 @@ export default async function generateProof(
5457
treeDepth: merkleProofLength,
5558
treeIndices,
5659
treeSiblings,
57-
scope,
58-
message
60+
scope: hash(scope),
61+
message: hash(message)
5962
},
6063
snarkArtifacts.wasmFilePath,
6164
snarkArtifacts.zkeyFilePath
@@ -64,8 +67,8 @@ export default async function generateProof(
6467
return {
6568
treeRoot: publicSignals[0],
6669
nullifier: publicSignals[1],
67-
message: publicSignals[2],
68-
scope: publicSignals[3],
70+
message: BigNumber.from(message).toString() as NumericString,
71+
scope: BigNumber.from(scope).toString() as NumericString,
6972
proof: packProof(proof)
7073
}
7174
}

packages/proof/src/hash.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { BigNumber } from "@ethersproject/bignumber"
2+
import { BytesLike, Hexable, zeroPad } from "@ethersproject/bytes"
3+
import { keccak256 } from "@ethersproject/keccak256"
4+
import { NumericString } from "@zk-kit/groth16"
5+
6+
/**
7+
* Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
8+
* @param message The message to be hashed.
9+
* @returns The message digest.
10+
*/
11+
export default function hash(message: BytesLike | Hexable | number | bigint): NumericString {
12+
message = BigNumber.from(message).toTwos(256).toHexString()
13+
message = zeroPad(message, 32)
14+
15+
return (BigInt(keccak256(message)) >> BigInt(8)).toString() as NumericString
16+
}

packages/proof/src/index.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { formatBytes32String } from "@ethersproject/strings"
12
import { Group } from "@semaphore-protocol/group"
23
import { Identity } from "@semaphore-protocol/identity"
34
import { getCurveFromName } from "ffjavascript"
@@ -10,8 +11,8 @@ import verifyProof from "./verify-proof"
1011
describe("Proof", () => {
1112
const treeDepth = 10
1213

13-
const message = 1
14-
const scope = 2
14+
const message = formatBytes32String("Hello world")
15+
const scope = formatBytes32String("Scope")
1516

1617
const identity = new Identity(42)
1718

packages/proof/src/verify-proof.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { verify } from "@zk-kit/groth16"
22
import { SemaphoreProof } from "./types"
33
import unpackProof from "./unpack-proof"
44
import verificationKeys from "./verification-keys.json"
5+
import hash from "./hash"
56

67
/**
78
* Verifies a Semaphore proof.
@@ -21,7 +22,7 @@ export default function verifyProof({ treeRoot, nullifier, message, scope, proof
2122
}
2223

2324
return verify(verificationKey, {
24-
publicSignals: [treeRoot, nullifier, message, scope],
25+
publicSignals: [treeRoot, nullifier, hash(message), hash(scope)],
2526
proof: unpackProof(proof)
2627
})
2728
}

yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8499,6 +8499,10 @@ __metadata:
84998499
version: 0.0.0-use.local
85008500
resolution: "@semaphore-protocol/proof@workspace:packages/proof"
85018501
dependencies:
8502+
"@ethersproject/bignumber": ^5.7.0
8503+
"@ethersproject/bytes": ^5.7.0
8504+
"@ethersproject/keccak256": ^5.7.0
8505+
"@ethersproject/strings": ^5.7.0
85028506
"@rollup/plugin-commonjs": ^24.1.0
85038507
"@rollup/plugin-json": ^5.0.1
85048508
"@rollup/plugin-node-resolve": ^15.0.2

0 commit comments

Comments
 (0)