mirror of
https://github.com/selfxyz/self.git
synced 2026-01-08 22:28:11 -05:00
fix: added missing range checks in ShaBytesDynamic (#579)
* fix: added missing range checks for Sha1Bytes * more descriptive comments around range checks * added range assumption of Sha1Bytes * added range assumption of Sha1General --------- Co-authored-by: nicoshark <i.am.nicoshark@gmail.com> Co-authored-by: turnoffthiscomputer <98749896+remicolin@users.noreply.github.com>
This commit is contained in:
@@ -6,6 +6,9 @@ include "@openpassport/zk-email-circuits/utils/array.circom";
|
||||
include "circomlib/circuits/bitify.circom";
|
||||
|
||||
//Adapted from @openpassport/zk-email-circuits/helpers/sha.circom
|
||||
// Assumption: The value `in_len_padded_bytes * 8` must fit within `ceil(log2(max_num_bytes * 8))` bits.
|
||||
// This range constraint is assumed (but not enforced) by the underlying `Sha1General` template.
|
||||
// It must be enforced externally, via a Num2Bits check, to prevent incorrect hash outputs.
|
||||
template Sha1Bytes(max_num_bytes) {
|
||||
signal input in_padded[max_num_bytes];
|
||||
signal input in_len_padded_bytes;
|
||||
@@ -33,6 +36,9 @@ template Sha1Bytes(max_num_bytes) {
|
||||
|
||||
//Adapted from @openpassport/zk-email-circuits/helpers/sha256general.circom
|
||||
//Sha1 template from https://github.com/dmpierre/sha1-circom/blob/fe18319cf72b9f3b83d0cea8f49a1f04482c125b/circuits/sha1.circom
|
||||
// Assumption: The value of `in_len_padded_bits` must fit within `ceil(log2(maxBitsPadded))` bits.
|
||||
// This constraint is required to ensure soundness of the LessEqThan comparator.
|
||||
// It is not enforced here: it must be guaranteed by the "caller", via a Num2Bits check!
|
||||
template Sha1General(maxBitsPadded) {
|
||||
assert(maxBitsPadded % 512 == 0);
|
||||
var maxBitsPaddedBits = log2Ceil(maxBitsPadded);
|
||||
|
||||
@@ -5,6 +5,7 @@ include "./dynamic/sha224Bytes.circom";
|
||||
include "@openpassport/zk-email-circuits/lib/sha.circom";
|
||||
include "./dynamic/sha384Bytes.circom";
|
||||
include "./dynamic/sha512Bytes.circom";
|
||||
include "circomlib/circuits/bitify.circom"; // needed for Num2Bits
|
||||
|
||||
/// @title ShaBytesDynamic
|
||||
/// @notice Computes the hash of an input message using a specified hash length and padded input
|
||||
@@ -26,12 +27,38 @@ template ShaBytesDynamic(hashLen, max_num_bytes) {
|
||||
hash_bits <== Sha384Bytes(max_num_bytes)(in_padded, in_len_padded_bytes);
|
||||
}
|
||||
if (hashLen == 256) {
|
||||
|
||||
// Range check for the padded input length (in_len_padded_bytes).
|
||||
// This check enforces that `in_len_padded_bytes * 8` can be represented using
|
||||
// `ceil(log2(max_num_bytes * 8))` bits, which is a requirement assumed by the
|
||||
// underlying SHA templates. Without this check, out-of-range values could
|
||||
// silently bypass internal constraints, leading to incorrect hash outputs.
|
||||
// For more information, see:
|
||||
// https://github.com/zkemail/zk-email-verify/blob/b193cf0c760456b837b2bbcf7b2c72d5bb3f43c3/packages/circuits/lib/sha.circom#L87
|
||||
var maxBitsPadded = max_num_bytes * 8;
|
||||
var maxBitsPaddedBits = ceil(log2(maxBitsPadded));
|
||||
component rangeCheck = Num2Bits(maxBitsPaddedBits);
|
||||
rangeCheck.in <== in_len_padded_bytes * 8;
|
||||
|
||||
hash_bits <== Sha256Bytes(max_num_bytes)(in_padded, in_len_padded_bytes);
|
||||
}
|
||||
if (hashLen == 224) {
|
||||
hash_bits <== Sha224Bytes(max_num_bytes)(in_padded, in_len_padded_bytes);
|
||||
}
|
||||
if (hashLen == 160) {
|
||||
|
||||
// Range check for the padded input length (in_len_padded_bytes).
|
||||
// This check enforces that `in_len_padded_bytes * 8` can be represented using
|
||||
// `ceil(log2(max_num_bytes * 8))` bits, which is a requirement assumed by the
|
||||
// underlying SHA templates. Without this check, out-of-range values could
|
||||
// silently bypass internal constraints, leading to incorrect hash outputs.
|
||||
// For more information, see:
|
||||
// https://github.com/selfxyz/self/pull/579#issuecomment-2922842294
|
||||
var maxBitsPadded = max_num_bytes * 8;
|
||||
var maxBitsPaddedBits = ceil(log2(maxBitsPadded));
|
||||
component rangeCheck = Num2Bits(maxBitsPaddedBits);
|
||||
rangeCheck.in <== in_len_padded_bytes * 8;
|
||||
|
||||
hash_bits <== Sha1Bytes(max_num_bytes)(in_padded, in_len_padded_bytes);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user