diff --git a/packages/circuits/README.md b/packages/circuits/README.md
index 232f94a6..af39cdbe 100644
--- a/packages/circuits/README.md
+++ b/packages/circuits/README.md
@@ -29,6 +29,9 @@ include "@zk-email/circuits/email-verifier.circom";
- `n`: Number of bits per chunk the RSA key is split into. Recommended to be 121.
- `k`: Number of chunks the RSA key is split into. Recommended to be 17.
- `ignoreBodyHashCheck`: Set 1 to skip body hash check in case data to prove/extract is only in the headers.
+ - `enableHeaderMasking`: Set 1 to turn on header masking.
+ - `enableBodyMasking`: Set 1 to turn on body masking.
+ - `removeSoftLineBreaks`: Set 1 to remove soft line breaks (`=\r\n`) from the email body.
`Note`: We use these values for n and k because their product (n * k) needs to be more than 2048 (RSA constraint) and n has to be less than half of 255 to fit in a circom signal.
@@ -41,10 +44,14 @@ include "@zk-email/circuits/email-verifier.circom";
- `emailBodyLength`: Length of the email body including the SHA-256 padding.
- `bodyHashIndex`: Index of the body hash `bh` in the `emailHeader`.
- `precomputedSHA[32]`: Precomputed SHA-256 hash of the email body till the bodyHashIndex.
+ - `headerMask[maxHeadersLength]`: Mask to be applied on the `emailHeader`.
+ - `bodyMask[maxBodyLength]`: Mask to be applied on the `emailBody`.
+ - `decodedEmailBody[maxBodyLength]`: Decoded email body after removing soft line breaks.
**Output Signal**
- `pubkeyHash`: Poseidon hash of the pubkey - Poseidon(n/2)(n/2 chunks of pubkey with k*2 bits per chunk).
-
+ - `maskedHeader[maxHeadersLength]`: Masked email header.
+ - `maskedBody[maxBodyLength]`: Masked email body.
## **Libraries**
@@ -257,6 +264,33 @@ DigitBytesToInt: Converts a byte array representing digits to an integer.
- `out`: The output integer after conversion.
+
+
+AssertBit: Asserts that a given input is binary.
+
+
+- **[Source](utils/bytes.circom#L1-L7)**
+- **Inputs**:
+ - `in`: An input signal, expected to be 0 or 1.
+- **Outputs**:
+ - None. This template will throw an assertion error if the input is not binary.
+
+
+
+
+
+ByteMask: Masks an input array using a binary mask array.
+
+
+- **[Source](utils/bytes.circom#L9-L25)**
+- **Parameters**:
+ - `maxLength`: The maximum length of the input and mask arrays.
+- **Inputs**:
+ - `in`: An array of signals representing the body to be masked.
+ - `mask`: An array of signals representing the binary mask.
+- **Outputs**:
+ - `out`: An array of signals representing the masked input.
+
### `utils/constants.circom`
@@ -359,5 +393,20 @@ EmailNullifier: Calculates the email nullifier using Poseidon hash.
- `out`: The email nullifier.
+### `helpers/remove-soft-line-breaks.circom`
+
+
+
+RemoveSoftLineBreaks: Verifies the removal of soft line breaks from an encoded input string.
+
+- **[Source](helpers/remove-soft-line-breaks.circom)**
+- **Parameters**:
+ - `maxLength`: The maximum length of the input strings.
+- **Inputs**:
+ - `encoded[maxLength]`: An array of ASCII values representing the input string with potential soft line breaks.
+ - `decoded[maxLength]`: An array of ASCII values representing the expected output after removing soft line breaks.
+- **Outputs**:
+ - `isValid`: A signal that is 1 if the decoded input correctly represents the encoded input with soft line breaks removed, 0 otherwise.
+
\ No newline at end of file
diff --git a/packages/circuits/email-verifier.circom b/packages/circuits/email-verifier.circom
index 51a495b9..5315b9ff 100644
--- a/packages/circuits/email-verifier.circom
+++ b/packages/circuits/email-verifier.circom
@@ -22,8 +22,9 @@ include "./helpers/remove-soft-line-breaks.circom";
/// @param n Number of bits per chunk the RSA key is split into. Recommended to be 121.
/// @param k Number of chunks the RSA key is split into. Recommended to be 17.
/// @param ignoreBodyHashCheck Set 1 to skip body hash check in case data to prove/extract is only in the headers.
-/// @param removeSoftLineBreaks Set 1 to remove soft line breaks from the email body.
+/// @param enableHeaderMasking Set 1 to turn on header masking.
/// @param enableBodyMasking Set 1 to turn on body masking.
+/// @param removeSoftLineBreaks Set 1 to remove soft line breaks from the email body.
/// @input emailHeader[maxHeadersLength] Email headers that are signed (ones in `DKIM-Signature` header) as ASCII int[], padded as per SHA-256 block size.
/// @input emailHeaderLength Length of the email header including the SHA-256 padding.
/// @input pubkey[k] RSA public key split into k chunks of n bits each.
@@ -36,8 +37,9 @@ include "./helpers/remove-soft-line-breaks.circom";
/// @input mask[maxBodyLength] Mask for the email body.
/// @output pubkeyHash Poseidon hash of the pubkey - Poseidon(n/2)(n/2 chunks of pubkey with k*2 bits per chunk).
/// @output decodedEmailBodyOut[maxBodyLength] Decoded email body with soft line breaks removed.
+/// @output maskedHeader[maxHeadersLength] Masked email header.
/// @output maskedBody[maxBodyLength] Masked email body.
-template EmailVerifier(maxHeadersLength, maxBodyLength, n, k, ignoreBodyHashCheck, removeSoftLineBreaks, enableBodyMasking) {
+template EmailVerifier(maxHeadersLength, maxBodyLength, n, k, ignoreBodyHashCheck, enableHeaderMasking, enableBodyMasking, removeSoftLineBreaks) {
assert(maxHeadersLength % 64 == 0);
assert(maxBodyLength % 64 == 0);
assert(n * k > 2048); // to support 2048 bit RSA
@@ -89,6 +91,15 @@ template EmailVerifier(maxHeadersLength, maxBodyLength, n, k, ignoreBodyHashChec
rsaVerifier.modulus <== pubkey;
rsaVerifier.signature <== signature;
+ if (enableHeaderMasking == 1) {
+ signal input headerMask[maxHeadersLength];
+ signal output maskedHeader[maxHeadersLength];
+ component byteMask = ByteMask(maxHeadersLength);
+
+ byteMask.in <== emailHeader;
+ byteMask.mask <== headerMask;
+ maskedHeader <== byteMask.out;
+ }
// Calculate the SHA256 hash of the body and verify it matches the hash in the header
if (ignoreBodyHashCheck != 1) {
@@ -133,25 +144,22 @@ template EmailVerifier(maxHeadersLength, maxBodyLength, n, k, ignoreBodyHashChec
if (removeSoftLineBreaks == 1) {
signal input decodedEmailBodyIn[maxBodyLength];
- signal output decodedEmailBodyOut[maxBodyLength];
component qpEncodingChecker = RemoveSoftLineBreaks(maxBodyLength);
qpEncodingChecker.encoded <== emailBody;
qpEncodingChecker.decoded <== decodedEmailBodyIn;
qpEncodingChecker.isValid === 1;
-
- decodedEmailBodyOut <== qpEncodingChecker.decoded;
}
if (enableBodyMasking == 1) {
- signal input mask[maxBodyLength];
+ signal input bodyMask[maxBodyLength];
signal output maskedBody[maxBodyLength];
component byteMask = ByteMask(maxBodyLength);
- byteMask.body <== emailBody;
- byteMask.mask <== mask;
- maskedBody <== byteMask.maskedBody;
+ byteMask.in <== emailBody;
+ byteMask.mask <== bodyMask;
+ maskedBody <== byteMask.out;
}
}
diff --git a/packages/circuits/package.json b/packages/circuits/package.json
index 3abef34d..a8f2f5a6 100644
--- a/packages/circuits/package.json
+++ b/packages/circuits/package.json
@@ -4,7 +4,7 @@
"license": "MIT",
"scripts": {
"publish": "yarn npm publish --access=public",
- "test": "NODE_OPTIONS=--max_old_space_size=8192 jest tests"
+ "test": "NODE_OPTIONS=--max_old_space_size=8192 jest --runInBand --detectOpenHandles --forceExit --verbose tests"
},
"dependencies": {
"@zk-email/zk-regex-circom": "^2.1.0",
diff --git a/packages/circuits/tests/base64.test.ts b/packages/circuits/tests/base64.test.ts
index b4711c46..4088741e 100644
--- a/packages/circuits/tests/base64.test.ts
+++ b/packages/circuits/tests/base64.test.ts
@@ -1,58 +1,57 @@
import { wasm } from "circom_tester";
import path from "path";
-
describe("Base64 Lookup", () => {
- jest.setTimeout(10 * 60 * 1000); // 10 minutes
-
- let circuit: any;
-
- beforeAll(async () => {
- circuit = await wasm(
- path.join(__dirname, "./test-circuits/base64-test.circom"),
- {
- recompile: true,
- include: path.join(__dirname, "../../../node_modules"),
- // output: path.join(__dirname, "./compiled-test-circuits"),
- }
- );
- });
-
- it("should decode valid base64 chars", async function () {
- const inputs = [
- [65, 0], // A
- [90, 25], // Z
- [97, 26], // a
- [122, 51], // z
- [48, 52], // 0
- [57, 61], // 9
- [43, 62], // +
- [47, 63], // /
- [61, 0], // =
- ]
-
- for (const [input, output] of inputs) {
- const witness = await circuit.calculateWitness({
- in: input
- });
- await circuit.checkConstraints(witness);
- await circuit.assertOut(witness, { out: output })
- }
- });
-
- it("should fail with invalid chars", async function () {
- const inputs = [34, 64, 91, 44];
-
- expect.assertions(inputs.length);
- for (const input of inputs) {
- try {
- const witness = await circuit.calculateWitness({
- in: input
- });
- await circuit.checkConstraints(witness);
- } catch (error) {
- expect((error as Error).message).toMatch("Assert Failed");
- }
- }
- });
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
+
+ let circuit: any;
+
+ beforeAll(async () => {
+ circuit = await wasm(
+ path.join(__dirname, "./test-circuits/base64-test.circom"),
+ {
+ recompile: true,
+ include: path.join(__dirname, "../../../node_modules"),
+ // output: path.join(__dirname, "./compiled-test-circuits"),
+ }
+ );
+ });
+
+ it("should decode valid base64 chars", async function () {
+ const inputs = [
+ [65, 0], // A
+ [90, 25], // Z
+ [97, 26], // a
+ [122, 51], // z
+ [48, 52], // 0
+ [57, 61], // 9
+ [43, 62], // +
+ [47, 63], // /
+ [61, 0], // =
+ ];
+
+ for (const [input, output] of inputs) {
+ const witness = await circuit.calculateWitness({
+ in: input,
+ });
+ await circuit.checkConstraints(witness);
+ await circuit.assertOut(witness, { out: output });
+ }
+ });
+
+ it("should fail with invalid chars", async function () {
+ const inputs = [34, 64, 91, 44];
+
+ expect.assertions(inputs.length);
+ for (const input of inputs) {
+ try {
+ const witness = await circuit.calculateWitness({
+ in: input,
+ });
+ await circuit.checkConstraints(witness);
+ } catch (error) {
+ expect((error as Error).message).toMatch("Assert Failed");
+ }
+ }
+ });
});
diff --git a/packages/circuits/tests/body-masker.test.ts b/packages/circuits/tests/byte-mask.test.ts
similarity index 87%
rename from packages/circuits/tests/body-masker.test.ts
rename to packages/circuits/tests/byte-mask.test.ts
index c1fd513b..bafbfc4e 100644
--- a/packages/circuits/tests/body-masker.test.ts
+++ b/packages/circuits/tests/byte-mask.test.ts
@@ -6,7 +6,7 @@ describe("ByteMask Circuit", () => {
beforeAll(async () => {
circuit = await wasm_tester(
- path.join(__dirname, "./test-circuits/body-masker-test.circom"),
+ path.join(__dirname, "./test-circuits/byte-mask-test.circom"),
{
recompile: true,
include: path.join(__dirname, "../../../node_modules"),
@@ -17,14 +17,14 @@ describe("ByteMask Circuit", () => {
it("should mask the body correctly", async () => {
const input = {
- body: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+ in: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
mask: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
};
const witness = await circuit.calculateWitness(input);
await circuit.checkConstraints(witness);
await circuit.assertOut(witness, {
- maskedBody: [1, 0, 3, 0, 5, 0, 7, 0, 9, 0],
+ out: [1, 0, 3, 0, 5, 0, 7, 0, 9, 0],
});
});
diff --git a/packages/circuits/tests/email-verifier-no-body.test.ts b/packages/circuits/tests/email-verifier-no-body.test.ts
new file mode 100644
index 00000000..10262130
--- /dev/null
+++ b/packages/circuits/tests/email-verifier-no-body.test.ts
@@ -0,0 +1,48 @@
+import fs from "fs";
+import { wasm as wasm_tester } from "circom_tester";
+import path from "path";
+import { DKIMVerificationResult } from "@zk-email/helpers/src/dkim";
+import { generateEmailVerifierInputsFromDKIMResult } from "@zk-email/helpers/src/input-generators";
+import { verifyDKIMSignature } from "@zk-email/helpers/src/dkim";
+
+describe("EmailVerifier : Without body check", () => {
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
+
+ let dkimResult: DKIMVerificationResult;
+ let circuit: any;
+
+ beforeAll(async () => {
+ const rawEmail = fs.readFileSync(
+ path.join(__dirname, "./test-emails/test.eml"),
+ "utf8"
+ );
+ dkimResult = await verifyDKIMSignature(rawEmail);
+
+ circuit = await wasm_tester(
+ path.join(
+ __dirname,
+ "./test-circuits/email-verifier-no-body-test.circom"
+ ),
+ {
+ recompile: true,
+ include: path.join(__dirname, "../../../node_modules"),
+ // output: path.join(__dirname, "./compiled-test-circuits"),
+ }
+ );
+ });
+
+ it("should verify email when ignore_body_hash_check is true", async function () {
+ // The result wont have shaPrecomputeSelector, maxHeadersLength, maxBodyLength, ignoreBodyHashCheck
+ const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(
+ dkimResult,
+ {
+ maxHeadersLength: 640,
+ maxBodyLength: 768,
+ ignoreBodyHashCheck: true,
+ }
+ );
+
+ const witness = await circuit.calculateWitness(emailVerifierInputs);
+ await circuit.checkConstraints(witness);
+ });
+});
diff --git a/packages/circuits/tests/email-verifier-with-body-mask.test.ts b/packages/circuits/tests/email-verifier-with-body-mask.test.ts
new file mode 100644
index 00000000..f6c525c8
--- /dev/null
+++ b/packages/circuits/tests/email-verifier-with-body-mask.test.ts
@@ -0,0 +1,59 @@
+import fs from "fs";
+import { wasm as wasm_tester } from "circom_tester";
+import path from "path";
+import { DKIMVerificationResult } from "@zk-email/helpers/src/dkim";
+import { generateEmailVerifierInputsFromDKIMResult } from "@zk-email/helpers/src/input-generators";
+import { verifyDKIMSignature } from "@zk-email/helpers/src/dkim";
+
+describe("EmailVerifier : With body masking", () => {
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
+
+ let dkimResult: DKIMVerificationResult;
+ let circuit: any;
+
+ beforeAll(async () => {
+ const rawEmail = fs.readFileSync(
+ path.join(__dirname, "./test-emails/test.eml")
+ );
+ dkimResult = await verifyDKIMSignature(rawEmail);
+
+ circuit = await wasm_tester(
+ path.join(
+ __dirname,
+ "./test-circuits/email-verifier-with-body-mask-test.circom"
+ ),
+ {
+ recompile: true,
+ include: path.join(__dirname, "../../../node_modules"),
+ output: path.join(__dirname, "./compiled-test-circuits"),
+ }
+ );
+ });
+
+ it("should verify email with body masking", async function () {
+ const mask = Array.from({ length: 768 }, (_, i) =>
+ i > 25 && i < 50 ? 1 : 0
+ );
+
+ const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(
+ dkimResult,
+ {
+ maxHeadersLength: 640,
+ maxBodyLength: 768,
+ ignoreBodyHashCheck: false,
+ enableBodyMasking: true,
+ bodyMask: mask.map((value) => (value ? 1 : 0)),
+ }
+ );
+
+ const expectedMaskedBody = emailVerifierInputs.emailBody!.map(
+ (byte, i) => (mask[i] === 1 ? byte : 0)
+ );
+
+ const witness = await circuit.calculateWitness(emailVerifierInputs);
+ await circuit.checkConstraints(witness);
+ await circuit.assertOut(witness, {
+ maskedBody: expectedMaskedBody,
+ });
+ });
+});
diff --git a/packages/circuits/tests/email-verifier-with-header-mask.test.ts b/packages/circuits/tests/email-verifier-with-header-mask.test.ts
new file mode 100644
index 00000000..04f4d567
--- /dev/null
+++ b/packages/circuits/tests/email-verifier-with-header-mask.test.ts
@@ -0,0 +1,59 @@
+import fs from "fs";
+import { wasm as wasm_tester } from "circom_tester";
+import path from "path";
+import { DKIMVerificationResult } from "@zk-email/helpers/src/dkim";
+import { generateEmailVerifierInputsFromDKIMResult } from "@zk-email/helpers/src/input-generators";
+import { verifyDKIMSignature } from "@zk-email/helpers/src/dkim";
+
+describe("EmailVerifier : With header masking", () => {
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
+
+ let dkimResult: DKIMVerificationResult;
+ let circuit: any;
+
+ beforeAll(async () => {
+ const rawEmail = fs.readFileSync(
+ path.join(__dirname, "./test-emails/test.eml")
+ );
+ dkimResult = await verifyDKIMSignature(rawEmail);
+
+ circuit = await wasm_tester(
+ path.join(
+ __dirname,
+ "./test-circuits/email-verifier-with-header-mask-test.circom"
+ ),
+ {
+ recompile: true,
+ include: path.join(__dirname, "../../../node_modules"),
+ output: path.join(__dirname, "./compiled-test-circuits"),
+ }
+ );
+ });
+
+ it("should verify email with header masking", async function () {
+ const mask = Array.from({ length: 640 }, (_, i) =>
+ i > 25 && i < 50 ? 1 : 0
+ );
+
+ const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(
+ dkimResult,
+ {
+ maxHeadersLength: 640,
+ maxBodyLength: 768,
+ ignoreBodyHashCheck: false,
+ enableHeaderMasking: true,
+ headerMask: mask.map((value) => (value ? 1 : 0)),
+ }
+ );
+
+ const expectedMaskedHeader = emailVerifierInputs.emailHeader!.map(
+ (byte, i) => (mask[i] === 1 ? byte : 0)
+ );
+
+ const witness = await circuit.calculateWitness(emailVerifierInputs);
+ await circuit.checkConstraints(witness);
+ await circuit.assertOut(witness, {
+ maskedHeader: expectedMaskedHeader,
+ });
+ });
+});
diff --git a/packages/circuits/tests/email-verifier-with-soft-line-breaks.test.ts b/packages/circuits/tests/email-verifier-with-soft-line-breaks.test.ts
new file mode 100644
index 00000000..106eb954
--- /dev/null
+++ b/packages/circuits/tests/email-verifier-with-soft-line-breaks.test.ts
@@ -0,0 +1,48 @@
+import fs from "fs";
+import { wasm as wasm_tester } from "circom_tester";
+import path from "path";
+import { DKIMVerificationResult } from "@zk-email/helpers/src/dkim";
+import { generateEmailVerifierInputsFromDKIMResult } from "@zk-email/helpers/src/input-generators";
+import { verifyDKIMSignature } from "@zk-email/helpers/src/dkim";
+
+describe("EmailVerifier : With soft line breaks", () => {
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
+
+ let dkimResult: DKIMVerificationResult;
+ let circuit: any;
+
+ beforeAll(async () => {
+ const rawEmail = fs.readFileSync(
+ path.join(__dirname, "./test-emails/lorem_ipsum.eml"),
+ "utf8"
+ );
+ dkimResult = await verifyDKIMSignature(rawEmail);
+
+ circuit = await wasm_tester(
+ path.join(
+ __dirname,
+ "./test-circuits/email-verifier-with-soft-line-breaks-test.circom"
+ ),
+ {
+ recompile: true,
+ include: path.join(__dirname, "../../../node_modules"),
+ output: path.join(__dirname, "./compiled-test-circuits"),
+ }
+ );
+ });
+
+ it("should verify email when removeSoftLineBreaks is true", async function () {
+ const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(
+ dkimResult,
+ {
+ maxHeadersLength: 640,
+ maxBodyLength: 1408,
+ ignoreBodyHashCheck: false,
+ removeSoftLineBreaks: true,
+ }
+ );
+
+ const witness = await circuit.calculateWitness(emailVerifierInputs);
+ await circuit.checkConstraints(witness);
+ });
+});
diff --git a/packages/circuits/tests/email-verifier.test.ts b/packages/circuits/tests/email-verifier.test.ts
index e5a26bf9..3221f9b6 100644
--- a/packages/circuits/tests/email-verifier.test.ts
+++ b/packages/circuits/tests/email-verifier.test.ts
@@ -1,5 +1,4 @@
import fs from "fs";
-import { buildPoseidon } from "circomlibjs";
import { wasm as wasm_tester } from "circom_tester";
import path from "path";
import { DKIMVerificationResult } from "@zk-email/helpers/src/dkim";
@@ -8,7 +7,7 @@ import { verifyDKIMSignature } from "@zk-email/helpers/src/dkim";
import { poseidonLarge } from "@zk-email/helpers/src/hash";
describe("EmailVerifier", () => {
- jest.setTimeout(10 * 60 * 1000); // 10 minutes
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
let dkimResult: DKIMVerificationResult;
let circuit: any;
@@ -207,140 +206,3 @@ describe("EmailVerifier", () => {
});
});
});
-
-describe("EmailVerifier : Without body check", () => {
- jest.setTimeout(10 * 60 * 1000); // 10 minutes
-
- let dkimResult: DKIMVerificationResult;
- let circuit: any;
-
- beforeAll(async () => {
- const rawEmail = fs.readFileSync(
- path.join(__dirname, "./test-emails/test.eml"),
- "utf8"
- );
- dkimResult = await verifyDKIMSignature(rawEmail);
-
- circuit = await wasm_tester(
- path.join(
- __dirname,
- "./test-circuits/email-verifier-no-body-test.circom"
- ),
- {
- recompile: true,
- include: path.join(__dirname, "../../../node_modules"),
- // output: path.join(__dirname, "./compiled-test-circuits"),
- }
- );
- });
-
- it("should verify email when ignore_body_hash_check is true", async function () {
- // The result wont have shaPrecomputeSelector, maxHeadersLength, maxBodyLength, ignoreBodyHashCheck
- const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(
- dkimResult,
- {
- maxHeadersLength: 640,
- maxBodyLength: 768,
- ignoreBodyHashCheck: true,
- }
- );
-
- const witness = await circuit.calculateWitness(emailVerifierInputs);
- await circuit.checkConstraints(witness);
- });
-});
-
-describe("EmailVerifier : With body masking", () => {
- jest.setTimeout(10 * 60 * 1000); // 10 minutes
-
- let dkimResult: DKIMVerificationResult;
- let circuit: any;
-
- beforeAll(async () => {
- const rawEmail = fs.readFileSync(
- path.join(__dirname, "./test-emails/test.eml")
- );
- dkimResult = await verifyDKIMSignature(rawEmail);
-
- circuit = await wasm_tester(
- path.join(
- __dirname,
- "./test-circuits/email-verifier-with-mask-test.circom"
- ),
- {
- recompile: true,
- include: path.join(__dirname, "../../../node_modules"),
- output: path.join(__dirname, "./compiled-test-circuits"),
- }
- );
- });
-
- it("should verify email with body masking", async function () {
- const mask = Array.from({ length: 768 }, (_, i) =>
- i > 25 && i < 50 ? 1 : 0
- );
-
- const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(
- dkimResult,
- {
- maxHeadersLength: 640,
- maxBodyLength: 768,
- ignoreBodyHashCheck: false,
- enableBodyMasking: true,
- mask: mask.map((value) => (value ? 1 : 0)),
- }
- );
-
- const expectedMaskedBody = emailVerifierInputs.emailBody!.map(
- (byte, i) => (mask[i] === 1 ? byte : 0)
- );
-
- const witness = await circuit.calculateWitness(emailVerifierInputs);
- await circuit.checkConstraints(witness);
- await circuit.assertOut(witness, {
- maskedBody: expectedMaskedBody,
- });
- });
-});
-
-describe("EmailVerifier : With soft line breaks", () => {
- jest.setTimeout(10 * 60 * 1000); // 10 minutes
-
- let dkimResult: DKIMVerificationResult;
- let circuit: any;
-
- beforeAll(async () => {
- const rawEmail = fs.readFileSync(
- path.join(__dirname, "./test-emails/lorem_ipsum.eml"),
- "utf8"
- );
- dkimResult = await verifyDKIMSignature(rawEmail);
-
- circuit = await wasm_tester(
- path.join(
- __dirname,
- "./test-circuits/email-verifier-with-soft-line-breaks-test.circom"
- ),
- {
- recompile: true,
- include: path.join(__dirname, "../../../node_modules"),
- output: path.join(__dirname, "./compiled-test-circuits"),
- }
- );
- });
-
- it("should verify email when removeSoftLineBreaks is true", async function () {
- const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(
- dkimResult,
- {
- maxHeadersLength: 640,
- maxBodyLength: 1408,
- ignoreBodyHashCheck: false,
- removeSoftLineBreaks: true,
- }
- );
-
- const witness = await circuit.calculateWitness(emailVerifierInputs);
- await circuit.checkConstraints(witness);
- });
-});
diff --git a/packages/circuits/tests/rsa.test.ts b/packages/circuits/tests/rsa.test.ts
index 4f6481b4..273db843 100644
--- a/packages/circuits/tests/rsa.test.ts
+++ b/packages/circuits/tests/rsa.test.ts
@@ -4,83 +4,142 @@ import { wasm as wasm_tester } from "circom_tester";
import { generateEmailVerifierInputs } from "@zk-email/helpers/src/input-generators";
import { toCircomBigIntBytes } from "@zk-email/helpers/src/binary-format";
-
describe("RSA", () => {
- jest.setTimeout(10 * 60 * 1000); // 10 minutes
-
- let circuit: any;
- let rawEmail: Buffer;
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
- beforeAll(async () => {
- circuit = await wasm_tester(
- path.join(__dirname, "./test-circuits/rsa-test.circom"),
- {
- recompile: true,
- include: path.join(__dirname, "../../../node_modules"),
- // output: path.join(__dirname, "./compiled-test-circuits"),
- }
- );
- rawEmail = fs.readFileSync(path.join(__dirname, "./test-emails/test.eml"));
- });
+ let circuit: any;
+ let rawEmail: Buffer;
- it("should verify 2048 bit rsa signature correctly", async function () {
- const emailVerifierInputs = await generateEmailVerifierInputs(rawEmail, {
- maxHeadersLength: 640,
- maxBodyLength: 768,
+ beforeAll(async () => {
+ circuit = await wasm_tester(
+ path.join(__dirname, "./test-circuits/rsa-test.circom"),
+ {
+ recompile: true,
+ include: path.join(__dirname, "../../../node_modules"),
+ // output: path.join(__dirname, "./compiled-test-circuits"),
+ }
+ );
+ rawEmail = fs.readFileSync(
+ path.join(__dirname, "./test-emails/test.eml")
+ );
});
+ it("should verify 2048 bit rsa signature correctly", async function () {
+ const emailVerifierInputs = await generateEmailVerifierInputs(
+ rawEmail,
+ {
+ maxHeadersLength: 640,
+ maxBodyLength: 768,
+ }
+ );
- const witness = await circuit.calculateWitness({
- signature: emailVerifierInputs.signature,
- modulus: emailVerifierInputs.pubkey,
- // TODO: generate this from the input
- message: ["1156466847851242602709362303526378170", "191372789510123109308037416804949834", "7204", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"],
+ const witness = await circuit.calculateWitness({
+ signature: emailVerifierInputs.signature,
+ modulus: emailVerifierInputs.pubkey,
+ // TODO: generate this from the input
+ message: [
+ "1156466847851242602709362303526378170",
+ "191372789510123109308037416804949834",
+ "7204",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ ],
+ });
+ await circuit.checkConstraints(witness);
+ await circuit.assertOut(witness, {});
});
- await circuit.checkConstraints(witness);
- await circuit.assertOut(witness, {})
- });
- it("should verify 1024 bit rsa signature correctly", async function () {
- const signature = toCircomBigIntBytes(
- BigInt(
- 102386562682221859025549328916727857389789009840935140645361501981959969535413501251999442013082353139290537518086128904993091119534674934202202277050635907008004079788691412782712147797487593510040249832242022835902734939817209358184800954336078838331094308355388211284440290335887813714894626653613586546719n
- )
- );
+ it("should verify 1024 bit rsa signature correctly", async function () {
+ const signature = toCircomBigIntBytes(
+ BigInt(
+ 102386562682221859025549328916727857389789009840935140645361501981959969535413501251999442013082353139290537518086128904993091119534674934202202277050635907008004079788691412782712147797487593510040249832242022835902734939817209358184800954336078838331094308355388211284440290335887813714894626653613586546719n
+ )
+ );
- const pubkey = toCircomBigIntBytes(
- BigInt(
- 106773687078109007595028366084970322147907086635176067918161636756354740353674098686965493426431314019237945536387044259034050617425729739578628872957481830432099721612688699974185290306098360072264136606623400336518126533605711223527682187548332314997606381158951535480830524587400401856271050333371205030999n
- )
- );
+ const pubkey = toCircomBigIntBytes(
+ BigInt(
+ 106773687078109007595028366084970322147907086635176067918161636756354740353674098686965493426431314019237945536387044259034050617425729739578628872957481830432099721612688699974185290306098360072264136606623400336518126533605711223527682187548332314997606381158951535480830524587400401856271050333371205030999n
+ )
+ );
- const witness = await circuit.calculateWitness({
- signature: signature,
- modulus: pubkey,
- // TODO: generate this from the input
- message: ["1156466847851242602709362303526378170", "191372789510123109308037416804949834", "7204", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"],
+ const witness = await circuit.calculateWitness({
+ signature: signature,
+ modulus: pubkey,
+ // TODO: generate this from the input
+ message: [
+ "1156466847851242602709362303526378170",
+ "191372789510123109308037416804949834",
+ "7204",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ ],
+ });
+ await circuit.checkConstraints(witness);
+ await circuit.assertOut(witness, {});
});
- await circuit.checkConstraints(witness);
- await circuit.assertOut(witness, {});
- });
- it("should fail when verifying with an incorrect signature", async function () {
- const emailVerifierInputs = await generateEmailVerifierInputs(rawEmail, {
- maxHeadersLength: 640,
- maxBodyLength: 768,
- });
+ it("should fail when verifying with an incorrect signature", async function () {
+ const emailVerifierInputs = await generateEmailVerifierInputs(
+ rawEmail,
+ {
+ maxHeadersLength: 640,
+ maxBodyLength: 768,
+ }
+ );
-
- expect.assertions(1);
- try {
- const witness = await circuit.calculateWitness({
- signature: emailVerifierInputs.signature,
- modulus: emailVerifierInputs.pubkey,
- message: ["1156466847851242602709362303526378171", "191372789510123109308037416804949834", "7204", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"],
- });
- await circuit.checkConstraints(witness);
- await circuit.assertOut(witness, {})
- } catch (error) {
- expect((error as Error).message).toMatch("Assert Failed");
- }
- });
+ expect.assertions(1);
+ try {
+ const witness = await circuit.calculateWitness({
+ signature: emailVerifierInputs.signature,
+ modulus: emailVerifierInputs.pubkey,
+ message: [
+ "1156466847851242602709362303526378171",
+ "191372789510123109308037416804949834",
+ "7204",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ "0",
+ ],
+ });
+ await circuit.checkConstraints(witness);
+ await circuit.assertOut(witness, {});
+ } catch (error) {
+ expect((error as Error).message).toMatch("Assert Failed");
+ }
+ });
});
diff --git a/packages/circuits/tests/select-regex-reveal.test.ts b/packages/circuits/tests/select-regex-reveal.test.ts
index fdf55115..cd3f3b81 100644
--- a/packages/circuits/tests/select-regex-reveal.test.ts
+++ b/packages/circuits/tests/select-regex-reveal.test.ts
@@ -1,15 +1,17 @@
import { wasm } from "circom_tester";
import path from "path";
-
describe("Select Regex Reveal", () => {
- jest.setTimeout(10 * 60 * 1000); // 10 minutes
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
let circuit: any;
beforeAll(async () => {
circuit = await wasm(
- path.join(__dirname, "./test-circuits/select-regex-reveal-test.circom"),
+ path.join(
+ __dirname,
+ "./test-circuits/select-regex-reveal-test.circom"
+ ),
{
recompile: true,
include: path.join(__dirname, "../../../node_modules"),
@@ -18,9 +20,14 @@ describe("Select Regex Reveal", () => {
});
it("should reveal the substring with maximum revealed length", async function () {
- let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ let input = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ];
const startIndex = Math.floor(Math.random() * 24);
- const revealed = Array.from("zk email").map(char => char.charCodeAt(0));
+ const revealed = Array.from("zk email").map((char) =>
+ char.charCodeAt(0)
+ );
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
@@ -29,13 +36,16 @@ describe("Select Regex Reveal", () => {
startIndex: startIndex,
});
await circuit.checkConstraints(witness);
- await circuit.assertOut(witness, { out: revealed })
+ await circuit.assertOut(witness, { out: revealed });
});
it("should reveal the substring with non-maximum revealed length", async function () {
- let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ let input = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ];
const startIndex = 30;
- const revealed = Array.from("zk").map(char => char.charCodeAt(0));
+ const revealed = Array.from("zk").map((char) => char.charCodeAt(0));
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
@@ -44,11 +54,16 @@ describe("Select Regex Reveal", () => {
startIndex: startIndex,
});
await circuit.checkConstraints(witness);
- await circuit.assertOut(witness, { out: revealed.concat([0, 0, 0, 0, 0, 0]) })
+ await circuit.assertOut(witness, {
+ out: revealed.concat([0, 0, 0, 0, 0, 0]),
+ });
});
it("should fail when all zero", async function () {
- let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ let input = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ];
const startIndex = Math.floor(Math.random() * 32);
try {
const witness = await circuit.calculateWitness({
@@ -62,9 +77,14 @@ describe("Select Regex Reveal", () => {
});
it("should fail when startIndex is 0", async function () {
- let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ let input = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ];
const startIndex = 1 + Math.floor(Math.random() * 24);
- const revealed = Array.from("zk email").map(char => char.charCodeAt(0));
+ const revealed = Array.from("zk email").map((char) =>
+ char.charCodeAt(0)
+ );
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
@@ -80,9 +100,14 @@ describe("Select Regex Reveal", () => {
});
it("should fail when startIndex is not before 0", async function () {
- let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ let input = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ];
const startIndex = Math.floor(Math.random() * 23);
- const revealed = Array.from("zk email").map(char => char.charCodeAt(0));
+ const revealed = Array.from("zk email").map((char) =>
+ char.charCodeAt(0)
+ );
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
@@ -98,16 +123,21 @@ describe("Select Regex Reveal", () => {
});
it("should fail when startIndex is larger than max length", async function () {
- let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ let input = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ];
const startIndex = Math.floor(Math.random() * 24);
- const revealed = Array.from("zk email").map(char => char.charCodeAt(0));
+ const revealed = Array.from("zk email").map((char) =>
+ char.charCodeAt(0)
+ );
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
try {
const witness = await circuit.calculateWitness({
in: input,
- startIndex: 32
+ startIndex: 32,
});
await circuit.checkConstraints(witness);
} catch (error) {
diff --git a/packages/circuits/tests/sha.test.ts b/packages/circuits/tests/sha.test.ts
index 82e8623d..e9281924 100644
--- a/packages/circuits/tests/sha.test.ts
+++ b/packages/circuits/tests/sha.test.ts
@@ -1,44 +1,44 @@
import { wasm as wasm_tester } from "circom_tester";
import path from "path";
import { sha256Pad, shaHash } from "@zk-email/helpers/src/sha-utils";
-import { Uint8ArrayToCharArray, uint8ToBits } from "@zk-email/helpers/src/binary-format";
-
+import {
+ Uint8ArrayToCharArray,
+ uint8ToBits,
+} from "@zk-email/helpers/src/binary-format";
describe("SHA256 for email header", () => {
- jest.setTimeout(10 * 60 * 1000); // 10 minutes
+ jest.setTimeout(30 * 60 * 1000); // 30 minutes
- let circuit: any;
+ let circuit: any;
- beforeAll(async () => {
- circuit = await wasm_tester(
- path.join(__dirname, "./test-circuits/sha-test.circom"),
- {
- recompile: true,
- include: path.join(__dirname, "../../../node_modules"),
- // output: path.join(__dirname, "./compiled-test-circuits"),
- }
- );
- });
+ beforeAll(async () => {
+ circuit = await wasm_tester(
+ path.join(__dirname, "./test-circuits/sha-test.circom"),
+ {
+ recompile: true,
+ include: path.join(__dirname, "../../../node_modules"),
+ // output: path.join(__dirname, "./compiled-test-circuits"),
+ }
+ );
+ });
- it("should hash correctly", async function () {
- const inputs = [
- "0", "hello world", ""
- ]
- for (const input of inputs) {
- const [
- paddedMsg,
- messageLen,
- ] = sha256Pad(
- Buffer.from(input, "ascii"), 640
- )
+ it("should hash correctly", async function () {
+ const inputs = ["0", "hello world", ""];
+ for (const input of inputs) {
+ const [paddedMsg, messageLen] = sha256Pad(
+ Buffer.from(input, "ascii"),
+ 640
+ );
- const witness = await circuit.calculateWitness({
- paddedIn: Uint8ArrayToCharArray(paddedMsg),
- paddedInLength: messageLen,
- });
+ const witness = await circuit.calculateWitness({
+ paddedIn: Uint8ArrayToCharArray(paddedMsg),
+ paddedInLength: messageLen,
+ });
- await circuit.checkConstraints(witness);
- await circuit.assertOut(witness, { out: [...uint8ToBits(shaHash(Buffer.from(input, "ascii")))] })
- }
- });
+ await circuit.checkConstraints(witness);
+ await circuit.assertOut(witness, {
+ out: [...uint8ToBits(shaHash(Buffer.from(input, "ascii")))],
+ });
+ }
+ });
});
diff --git a/packages/circuits/tests/test-circuits/body-masker-test.circom b/packages/circuits/tests/test-circuits/byte-mask-test.circom
similarity index 100%
rename from packages/circuits/tests/test-circuits/body-masker-test.circom
rename to packages/circuits/tests/test-circuits/byte-mask-test.circom
diff --git a/packages/circuits/tests/test-circuits/email-verifier-no-body-test.circom b/packages/circuits/tests/test-circuits/email-verifier-no-body-test.circom
index 39c19114..d2c0ea8e 100644
--- a/packages/circuits/tests/test-circuits/email-verifier-no-body-test.circom
+++ b/packages/circuits/tests/test-circuits/email-verifier-no-body-test.circom
@@ -2,4 +2,4 @@ pragma circom 2.1.6;
include "../../email-verifier.circom";
-component main { public [ pubkey ] } = EmailVerifier(640, 768, 121, 17, 1, 0, 0);
+component main { public [ pubkey ] } = EmailVerifier(640, 768, 121, 17, 1, 0, 0, 0);
diff --git a/packages/circuits/tests/test-circuits/email-verifier-test.circom b/packages/circuits/tests/test-circuits/email-verifier-test.circom
index 858a5443..af7a24c1 100644
--- a/packages/circuits/tests/test-circuits/email-verifier-test.circom
+++ b/packages/circuits/tests/test-circuits/email-verifier-test.circom
@@ -2,4 +2,4 @@ pragma circom 2.1.6;
include "../../email-verifier.circom";
-component main { public [ pubkey ] } = EmailVerifier(640, 768, 121, 17, 0, 0, 0);
+component main { public [ pubkey ] } = EmailVerifier(640, 768, 121, 17, 0, 0, 0, 0);
diff --git a/packages/circuits/tests/test-circuits/email-verifier-with-mask-test.circom b/packages/circuits/tests/test-circuits/email-verifier-with-body-mask-test.circom
similarity index 85%
rename from packages/circuits/tests/test-circuits/email-verifier-with-mask-test.circom
rename to packages/circuits/tests/test-circuits/email-verifier-with-body-mask-test.circom
index 66181b39..a7c1db1b 100644
--- a/packages/circuits/tests/test-circuits/email-verifier-with-mask-test.circom
+++ b/packages/circuits/tests/test-circuits/email-verifier-with-body-mask-test.circom
@@ -2,4 +2,4 @@ pragma circom 2.1.6;
include "../../email-verifier.circom";
-component main { public [ pubkey ] } = EmailVerifier(640, 768, 121, 17, 0, 0, 1);
+component main { public [ pubkey ] } = EmailVerifier(640, 768, 121, 17, 0, 0, 1, 0);
diff --git a/packages/circuits/tests/test-circuits/email-verifier-with-header-mask-test.circom b/packages/circuits/tests/test-circuits/email-verifier-with-header-mask-test.circom
new file mode 100644
index 00000000..e9ac69d1
--- /dev/null
+++ b/packages/circuits/tests/test-circuits/email-verifier-with-header-mask-test.circom
@@ -0,0 +1,5 @@
+pragma circom 2.1.6;
+
+include "../../email-verifier.circom";
+
+component main { public [ pubkey ] } = EmailVerifier(640, 768, 121, 17, 0, 1, 0, 0);
diff --git a/packages/circuits/tests/test-circuits/email-verifier-with-soft-line-breaks-test.circom b/packages/circuits/tests/test-circuits/email-verifier-with-soft-line-breaks-test.circom
index be74589d..b6e52bbd 100644
--- a/packages/circuits/tests/test-circuits/email-verifier-with-soft-line-breaks-test.circom
+++ b/packages/circuits/tests/test-circuits/email-verifier-with-soft-line-breaks-test.circom
@@ -2,4 +2,4 @@ pragma circom 2.1.6;
include "../../email-verifier.circom";
-component main { public [ pubkey ] } = EmailVerifier(640, 1408, 121, 17, 0, 1, 0);
+component main { public [ pubkey ] } = EmailVerifier(640, 1408, 121, 17, 0, 0, 0, 1);
diff --git a/packages/circuits/utils/bytes.circom b/packages/circuits/utils/bytes.circom
index a394ce2e..2bc0c1cf 100644
--- a/packages/circuits/utils/bytes.circom
+++ b/packages/circuits/utils/bytes.circom
@@ -157,29 +157,29 @@ template AssertBit() {
in * (in - 1) === 0;
}
-// The ByteMask template masks an input body array using a binary mask array.
-// Each element in the body array is multiplied by the corresponding element in the mask array.
+// The ByteMask template masks an input array using a binary mask array.
+// Each element in the input array is multiplied by the corresponding element in the mask array.
// The mask array is validated to ensure all elements are binary (0 or 1).
//
// Parameters:
-// - maxBodyLength: The maximum length of the body and mask arrays.
+// - maxLength: The maximum length of the input and mask arrays.
//
// Inputs:
// - body: An array of signals representing the body to be masked.
// - mask: An array of signals representing the binary mask.
//
// Outputs:
-// - maskedBody: An array of signals representing the masked body.
-template ByteMask(maxBodyLength) {
- signal input body[maxBodyLength];
- signal input mask[maxBodyLength];
- signal output maskedBody[maxBodyLength];
+// - out: An array of signals representing the masked input.
+template ByteMask(maxLength) {
+ signal input in[maxLength];
+ signal input mask[maxLength];
+ signal output out[maxLength];
- component bit_check[maxBodyLength];
+ component bit_check[maxLength];
- for (var i = 0; i < maxBodyLength; i++) {
+ for (var i = 0; i < maxLength; i++) {
bit_check[i] = AssertBit();
bit_check[i].in <== mask[i];
- maskedBody[i] <== body[i] * mask[i];
+ out[i] <== in[i] * mask[i];
}
}
\ No newline at end of file
diff --git a/packages/helpers/src/input-generators.ts b/packages/helpers/src/input-generators.ts
index c6e76c41..dea4b575 100644
--- a/packages/helpers/src/input-generators.ts
+++ b/packages/helpers/src/input-generators.ts
@@ -13,17 +13,20 @@ type CircuitInput = {
precomputedSHA?: string[];
bodyHashIndex?: string;
decodedEmailBodyIn?: string[];
- mask?: number[];
+ headerMask?: number[];
+ bodyMask?: number[];
};
type InputGenerationArgs = {
ignoreBodyHashCheck?: boolean;
+ enableHeaderMasking?: boolean;
enableBodyMasking?: boolean;
shaPrecomputeSelector?: string;
maxHeadersLength?: number; // Max length of the email header including padding
maxBodyLength?: number; // Max length of the email body after shaPrecomputeSelector including padding
removeSoftLineBreaks?: boolean;
- mask?: number[];
+ headerMask?: number[];
+ bodyMask?: number[];
};
function removeSoftLineBreaks(body: string[]): string[] {
@@ -95,6 +98,10 @@ export function generateEmailVerifierInputsFromDKIMResult(
signature: toCircomBigIntBytes(signature),
};
+ if (params.enableHeaderMasking) {
+ circuitInputs.headerMask = params.headerMask;
+ }
+
if (!params.ignoreBodyHashCheck) {
if (!body || !bodyHash) {
throw new Error(
@@ -132,7 +139,7 @@ export function generateEmailVerifierInputsFromDKIMResult(
}
if (params.enableBodyMasking) {
- circuitInputs.mask = params.mask;
+ circuitInputs.bodyMask = params.bodyMask;
}
}