Skip to content

Commit

Permalink
Fix shift malleability attack. (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
SoraSuegami authored Oct 26, 2023
1 parent 1d65a2d commit 8a37dba
Show file tree
Hide file tree
Showing 9 changed files with 453 additions and 275 deletions.
2 changes: 1 addition & 1 deletion packages/circuits/email-verifier.circom
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ template EmailVerifier(max_header_bytes, max_body_bytes, n, k, ignore_body_hash_
// which is used to verify the body text matches this signed hash + the signature verifies this hash is legit
signal (bh_regex_out, bh_reveal[max_header_bytes]) <== BodyHashRegex(max_header_bytes)(in_padded);
bh_regex_out === 1;
signal shifted_bh_out[LEN_SHA_B64] <== VarShiftLeft(max_header_bytes, LEN_SHA_B64)(bh_reveal, body_hash_idx);
signal shifted_bh_out[LEN_SHA_B64] <== VarShiftMaskedStr(max_header_bytes, LEN_SHA_B64)(bh_reveal, body_hash_idx);
// log(body_hash_regex.out);


Expand Down
52 changes: 52 additions & 0 deletions packages/circuits/helpers/extract.circom
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ template PackBytes(max_in_signals, max_out_signals, pack_size) {
}
}

// Shift the input left by variable size of bytes.
// From https://demo.hedgedoc.org/s/Le0R3xUhB
// Note that if len_bits < max_substr * C, C around 1, then
// it's more efficient to use Sampriti's O(nk) solution instead
Expand Down Expand Up @@ -74,6 +75,31 @@ template VarShiftLeft(in_array_len, out_array_len) {
}
}

// Shift the input left by variable size of bytes.
// Its input and output are the same as those of VarShiftLeft.
// However, it assumes the input is the masked bytes and checks that shift is the first index of the non-masked bytes.
template VarShiftMaskedStr(in_array_len, out_array_len) {
signal input in[in_array_len]; // x
signal input shift; // k
signal output out[out_array_len] <== VarShiftLeft(in_array_len, out_array_len)(in, shift);

signal is_target_idx[in_array_len];
signal prev_byte[in_array_len];
signal is_this_zero[in_array_len];
signal is_prev_zero[in_array_len];
for(var i = 0; i < in_array_len; i++) {
is_target_idx[i] <== IsEqual()([i, shift]);
is_this_zero[i] <== IsZero()(in[i]);
is_target_idx[i] * is_this_zero[i] === 0;
if(i == 0) {
is_prev_zero[i] <== 1;
} else {
is_prev_zero[i] <== IsZero()(in[i-1]);
}
is_target_idx[i] * (1 - is_prev_zero[i]) === 0;
}
}

// From https://demo.hedgedoc.org/s/Le0R3xUhB -- unused
template ClearSubarrayAfterEndIndex(n, nBits) {
signal input in[n]; // x
Expand Down Expand Up @@ -119,3 +145,29 @@ template ShiftAndPack(in_array_len, max_substr_len, pack_size) {
out[i] <== packer.out[i];
}
}

// Shift the input left by variable size of bytes and pack the shifted bytes into fields under pack_size.
// Its input and output are the same as those of ShiftAndPack.
// However, it assumes the input is the masked bytes and checks that shift is the first index of the non-masked bytes.
template ShiftAndPackMaskedStr(in_array_len, max_substr_len, pack_size) {
var max_substr_len_packed = ((max_substr_len - 1) \ pack_size + 1);

component shifter = VarShiftMaskedStr(in_array_len, max_substr_len);
component packer = PackBytes(max_substr_len, max_substr_len_packed, pack_size);

signal input in[in_array_len];
signal input shift;
signal output out[max_substr_len_packed];

for (var i = 0; i < in_array_len; i++) {
shifter.in[i] <== in[i];
}
shifter.shift <== shift;

for (var i = 0; i < max_substr_len; i++) {
packer.in[i] <== shifter.out[i];
}
for (var i = 0; i < max_substr_len_packed; i++) {
out[i] <== packer.out[i];
}
}
2 changes: 1 addition & 1 deletion packages/circuits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
"jest": "^29.5.0"
},
"dependencies": {
"@zk-email/zk-regex-circom": "^1.1.0"
"@zk-email/zk-regex-circom": "^1.1.1"
}
}
12 changes: 12 additions & 0 deletions packages/twitter-verifier-circuits/components/twitter_reset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"parts": [
{
"is_public": false,
"regex_def": "email was meant for @"
},
{
"is_public": true,
"regex_def": "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_)+"
}
]
}
Loading

0 comments on commit 8a37dba

Please sign in to comment.