semaphore
semaphore copied to clipboard
Consider not hashing `message` and `scope` before generating proofs
Describe the improvement you're thinking about
Semaphore circuit inputs (i.e. message and scope) passed directly by devs are hashed with keccak and right-shifted to fit within the SNARK scalar field size in the generateProof function. The following function is what has been used so far:
export default function hash(message: BigNumberish): NumericString {
return (BigInt(keccak256(toBeHex(message, 32))) >> BigInt(8)).toString()
}
The message and scope values returned by generateProof are the pre-images though (the values passed by devs). Thus, the same hash is calculated on-chain before verification and in the JavaScript function verifyProof, so that devs do not have to worry about this.
The main reason for this is that it has allowed devs to not convert a 256-bit value to the scalar field themselves.
It might make sense to check whether in terms of security there is a difference between right-shifting (or applying a modulo to) the hash digest or the pre-image directly. Removing the hash would allow the on-chain verification function to be lighter.
Additional context
The calculation of this hash comes from the first version of Semaphore, where it was actually used to calculate the hash of signals in a string format of arbitrary length. The external nullifier was not hashed and it needed to be smaller than 256 bits.
Can you add more context here? @cedoor Please and thank you 🙏
Can you add more context here? @cedoor Please and thank you 🙏
Yes! Please, let me know if it's clear. We can discuss this issue here, and eventually ask the security team for some feedback.
it is fine as it is.
After feedback from the security team, we can close it and mark it as unplanned.