From f4ddc79407de56ec5b7b0e7bd07f29f4354161af Mon Sep 17 00:00:00 2001 From: Saleel Date: Sun, 8 Sep 2024 23:22:46 +0530 Subject: [PATCH] add prettier --- .prettierignore | 1 + .prettierrc | 6 + package.json | 4 + packages/circuits/tests/base64.test.ts | 46 +- packages/circuits/tests/body-masker.test.ts | 73 ++- .../circuits/tests/email-verifier.test.ts | 558 ++++++++---------- .../tests/remove-soft-line-breaks.test.ts | 107 +--- packages/circuits/tests/rsa.test.ts | 110 +++- .../tests/select-regex-reveal.test.ts | 176 +++--- packages/circuits/tests/sha.test.ts | 39 +- .../tests/split-bytes-to-words.test.ts | 48 +- packages/helpers/src/binary-format.ts | 8 +- packages/helpers/src/chunked-zkey.ts | 52 +- packages/helpers/src/dkim/index.ts | 30 +- packages/helpers/src/dkim/sanitizers.ts | 12 +- packages/helpers/src/input-generators.ts | 35 +- packages/helpers/src/sha-utils.ts | 17 +- packages/helpers/tests/dkim.test.ts | 36 +- .../helpers/tests/input-generators.test.ts | 46 +- scripts/dkim/update-dkim-registry.ts | 183 +++--- yarn.lock | 11 + 21 files changed, 684 insertions(+), 914 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..56756a4b4 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +packages/helpers/src/lib \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..91387a9f1 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": true, + "tabWidth": 2, + "singleQuote": true, + "printWidth": 120 +} diff --git a/package.json b/package.json index b12be1360..3c3d6a6b7 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "license": "MIT", "private": true, "scripts": { + "lint": "yarn prettier --write packages/**/**.ts", "test": "jest" }, "workspaces": [ @@ -12,5 +13,8 @@ "packageManager": "yarn@3.2.3", "engines": { "node": ">=14.0.0" + }, + "devDependencies": { + "prettier": "^3.3.3" } } diff --git a/packages/circuits/tests/base64.test.ts b/packages/circuits/tests/base64.test.ts index b4711c46c..e4971ec81 100644 --- a/packages/circuits/tests/base64.test.ts +++ b/packages/circuits/tests/base64.test.ts @@ -1,24 +1,20 @@ -import { wasm } from "circom_tester"; -import path from "path"; +import { wasm } from 'circom_tester'; +import path from 'path'; - -describe("Base64 Lookup", () => { +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"), - } - ); + 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 () { + it('should decode valid base64 chars', async function () { const inputs = [ [65, 0], // A [90, 25], // Z @@ -29,30 +25,30 @@ describe("Base64 Lookup", () => { [43, 62], // + [47, 63], // / [61, 0], // = - ] + ]; for (const [input, output] of inputs) { const witness = await circuit.calculateWitness({ - in: input + in: input, }); await circuit.checkConstraints(witness); - await circuit.assertOut(witness, { out: output }) + await circuit.assertOut(witness, { out: output }); } }); - it("should fail with invalid chars", async function () { + 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"); - } + 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/body-masker.test.ts index c1fd513bb..2a711c629 100644 --- a/packages/circuits/tests/body-masker.test.ts +++ b/packages/circuits/tests/body-masker.test.ts @@ -1,47 +1,44 @@ -import { wasm as wasm_tester } from "circom_tester"; -import path from "path"; +import { wasm as wasm_tester } from 'circom_tester'; +import path from 'path'; -describe("ByteMask Circuit", () => { - let circuit: any; +describe('ByteMask Circuit', () => { + let circuit: any; - beforeAll(async () => { - circuit = await wasm_tester( - path.join(__dirname, "./test-circuits/body-masker-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/body-masker-test.circom'), { + recompile: true, + include: path.join(__dirname, '../../../node_modules'), + output: path.join(__dirname, './compiled-test-circuits'), }); + }); - it("should mask the body correctly", async () => { - const input = { - body: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - mask: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0], - }; + it('should mask the body correctly', async () => { + const input = { + body: [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], - }); + 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], }); + }); - it("should fail if mask has non-bit numbers", async () => { - const input = { - body: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - mask: [1, 2, 1, 0, 1, 0, 1, 0, 1, 0], // Mask with non-bit number (2) - }; + it('should fail if mask has non-bit numbers', async () => { + const input = { + body: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + mask: [1, 2, 1, 0, 1, 0, 1, 0, 1, 0], // Mask with non-bit number (2) + }; - try { - 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], - }); - } catch (error) { - expect(error).toBeTruthy(); - } - }); + try { + 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], + }); + } catch (error) { + expect(error).toBeTruthy(); + } + }); }); diff --git a/packages/circuits/tests/email-verifier.test.ts b/packages/circuits/tests/email-verifier.test.ts index e5a26bf97..2fe2db1fc 100644 --- a/packages/circuits/tests/email-verifier.test.ts +++ b/packages/circuits/tests/email-verifier.test.ts @@ -1,346 +1,278 @@ -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"; -import { generateEmailVerifierInputsFromDKIMResult } from "@zk-email/helpers/src/input-generators"; -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 - - 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-test.circom"), - { - // @dev During development recompile can be set to false if you are only making changes in the tests. - // This will save time by not recompiling the circuit every time. - // Compile: circom "./tests/email-verifier-test.circom" --r1cs --wasm --sym --c --wat --output "./tests/compiled-test-circuits" - recompile: true, - include: path.join(__dirname, "../../../node_modules"), - output: path.join(__dirname, "./compiled-test-circuits"), - } - ); +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'; +import { generateEmailVerifierInputsFromDKIMResult } from '@zk-email/helpers/src/input-generators'; +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 + + 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-test.circom'), { + // @dev During development recompile can be set to false if you are only making changes in the tests. + // This will save time by not recompiling the circuit every time. + // Compile: circom "./tests/email-verifier-test.circom" --r1cs --wasm --sym --c --wat --output "./tests/compiled-test-circuits" + recompile: true, + include: path.join(__dirname, '../../../node_modules'), + output: path.join(__dirname, './compiled-test-circuits'), }); + }); - it("should verify email without any SHA precompute selector", async function () { - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkimResult, - { - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - - const witness = await circuit.calculateWitness(emailVerifierInputs); - await circuit.checkConstraints(witness); + it('should verify email without any SHA precompute selector', async function () { + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkimResult, { + maxHeadersLength: 640, + maxBodyLength: 768, }); - it("should verify email with a SHA precompute selector", async function () { - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkimResult, - { - shaPrecomputeSelector: "How are", - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - - const witness = await circuit.calculateWitness(emailVerifierInputs); - await circuit.checkConstraints(witness); + const witness = await circuit.calculateWitness(emailVerifierInputs); + await circuit.checkConstraints(witness); + }); + + it('should verify email with a SHA precompute selector', async function () { + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkimResult, { + shaPrecomputeSelector: 'How are', + maxHeadersLength: 640, + maxBodyLength: 768, }); - it("should fail if the rsa signature is wrong", async function () { - const invalidRSASignature = dkimResult.signature + 1n; - const dkim = { ...dkimResult, signature: invalidRSASignature }; - - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkim, - { - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - - expect.assertions(1); - try { - const witness = await circuit.calculateWitness(emailVerifierInputs); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + const witness = await circuit.calculateWitness(emailVerifierInputs); + await circuit.checkConstraints(witness); + }); + + it('should fail if the rsa signature is wrong', async function () { + const invalidRSASignature = dkimResult.signature + 1n; + const dkim = { ...dkimResult, signature: invalidRSASignature }; + + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkim, { + maxHeadersLength: 640, + maxBodyLength: 768, }); - it("should fail if message is tampered", async function () { - const invalidHeader = Buffer.from(dkimResult.headers); - invalidHeader[0] = 1; - - const dkim = { ...dkimResult, headers: invalidHeader }; - - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkim, - { - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - - expect.assertions(1); - try { - const witness = await circuit.calculateWitness(emailVerifierInputs); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + expect.assertions(1); + try { + const witness = await circuit.calculateWitness(emailVerifierInputs); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } + }); + + it('should fail if message is tampered', async function () { + const invalidHeader = Buffer.from(dkimResult.headers); + invalidHeader[0] = 1; + + const dkim = { ...dkimResult, headers: invalidHeader }; + + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkim, { + maxHeadersLength: 640, + maxBodyLength: 768, }); - it("should fail if message padding is tampered", async function () { - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkimResult, - { - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - emailVerifierInputs.emailHeader[640 - 1] = "1"; - - expect.assertions(1); - try { - const witness = await circuit.calculateWitness(emailVerifierInputs); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + expect.assertions(1); + try { + const witness = await circuit.calculateWitness(emailVerifierInputs); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } + }); + + it('should fail if message padding is tampered', async function () { + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkimResult, { + maxHeadersLength: 640, + maxBodyLength: 768, + }); + emailVerifierInputs.emailHeader[640 - 1] = '1'; + + expect.assertions(1); + try { + const witness = await circuit.calculateWitness(emailVerifierInputs); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } + }); + + it('should fail if body is tampered', async function () { + const invalidBody = Buffer.from(dkimResult.body); + invalidBody[invalidBody.length - 1] = 1; + + const dkim = { ...dkimResult, body: invalidBody }; + + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkim, { + maxHeadersLength: 640, + maxBodyLength: 768, }); - it("should fail if body is tampered", async function () { - const invalidBody = Buffer.from(dkimResult.body); - invalidBody[invalidBody.length - 1] = 1; - - const dkim = { ...dkimResult, body: invalidBody }; - - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkim, - { - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - - expect.assertions(1); - try { - const witness = await circuit.calculateWitness(emailVerifierInputs); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + expect.assertions(1); + try { + const witness = await circuit.calculateWitness(emailVerifierInputs); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } + }); + + it('should fail if body padding is tampered', async function () { + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkimResult, { + maxHeadersLength: 640, + maxBodyLength: 768, }); + emailVerifierInputs.emailBody![768 - 1] = '1'; - it("should fail if body padding is tampered", async function () { - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkimResult, - { - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - emailVerifierInputs.emailBody![768 - 1] = "1"; - - expect.assertions(1); - try { - const witness = await circuit.calculateWitness(emailVerifierInputs); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + expect.assertions(1); + try { + const witness = await circuit.calculateWitness(emailVerifierInputs); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } + }); + + it('should fail if body hash is tampered', async function () { + const invalidBodyHash = dkimResult.bodyHash + 'a'; + + const dkim = { ...dkimResult, bodyHash: invalidBodyHash }; + + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkim, { + maxHeadersLength: 640, + maxBodyLength: 768, }); - it("should fail if body hash is tampered", async function () { - const invalidBodyHash = dkimResult.bodyHash + "a"; - - const dkim = { ...dkimResult, bodyHash: invalidBodyHash }; - - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkim, - { - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - - expect.assertions(1); - try { - const witness = await circuit.calculateWitness(emailVerifierInputs); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + expect.assertions(1); + try { + const witness = await circuit.calculateWitness(emailVerifierInputs); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } + }); + + it('should produce dkim pubkey hash correctly', async function () { + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkimResult, { + shaPrecomputeSelector: 'How are', + maxHeadersLength: 640, + maxBodyLength: 768, }); - it("should produce dkim pubkey hash correctly", async function () { - const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult( - dkimResult, - { - shaPrecomputeSelector: "How are", - maxHeadersLength: 640, - maxBodyLength: 768, - } - ); - - // Calculate the Poseidon hash with pubkey chunked to 9*242 like in circuit - const poseidonHash = await poseidonLarge(dkimResult.publicKey, 9, 242); - - // Calculate the hash using the circuit - const witness = await circuit.calculateWitness(emailVerifierInputs); - - await circuit.assertOut(witness, { - pubkeyHash: poseidonHash, - }); + // Calculate the Poseidon hash with pubkey chunked to 9*242 like in circuit + const poseidonHash = await poseidonLarge(dkimResult.publicKey, 9, 242); + + // Calculate the hash using the circuit + const witness = await circuit.calculateWitness(emailVerifierInputs); + + await circuit.assertOut(witness, { + pubkeyHash: poseidonHash, }); + }); }); -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"), - } - ); - }); +describe('EmailVerifier : Without body check', () => { + jest.setTimeout(10 * 60 * 1000); // 10 minutes - 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); + 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"), - } - ); +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)); - 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, - }); + const emailVerifierInputs = generateEmailVerifierInputsFromDKIMResult(dkimResult, { + maxHeadersLength: 640, + maxBodyLength: 768, + ignoreBodyHashCheck: false, + enableBodyMasking: true, + mask: mask.map((value) => (value ? 1 : 0)), }); -}); -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"), - } - ); + 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, }); + }); +}); - 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); +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/remove-soft-line-breaks.test.ts b/packages/circuits/tests/remove-soft-line-breaks.test.ts index 5d14f7d3f..a093221cf 100644 --- a/packages/circuits/tests/remove-soft-line-breaks.test.ts +++ b/packages/circuits/tests/remove-soft-line-breaks.test.ts @@ -7,55 +7,17 @@ describe('RemoveSoftLineBreaks', () => { let circuit: any; beforeAll(async () => { - circuit = await wasm_tester( - path.join( - __dirname, - './test-circuits/remove-soft-line-breaks-test.circom' - ), - { - recompile: true, - include: path.join(__dirname, '../../../node_modules'), - output: path.join(__dirname, './compiled-test-circuits'), - } - ); + circuit = await wasm_tester(path.join(__dirname, './test-circuits/remove-soft-line-breaks-test.circom'), { + recompile: true, + include: path.join(__dirname, '../../../node_modules'), + output: path.join(__dirname, './compiled-test-circuits'), + }); }); it('should correctly remove soft line breaks', async () => { const input = { - encoded: [ - 115, - 101, - 115, - 58, - 61, - 13, - 10, - 45, - 32, - 83, - 114, - 101, - 97, - 107, - 61, - 13, - 10, - ...Array(15).fill(0), - ], - decoded: [ - 115, - 101, - 115, - 58, - 45, - 32, - 83, - 114, - 101, - 97, - 107, - ...Array(21).fill(0), - ], + encoded: [115, 101, 115, 58, 61, 13, 10, 45, 32, 83, 114, 101, 97, 107, 61, 13, 10, ...Array(15).fill(0)], + decoded: [115, 101, 115, 58, 45, 32, 83, 114, 101, 97, 107, ...Array(21).fill(0)], }; const witness = await circuit.calculateWitness(input); @@ -68,26 +30,7 @@ describe('RemoveSoftLineBreaks', () => { it('should fail when decoded input is incorrect', async () => { const input = { - encoded: [ - 115, - 101, - 115, - 58, - 61, - 13, - 10, - 45, - 32, - 83, - 114, - 101, - 97, - 107, - 61, - 13, - 10, - ...Array(15).fill(0), - ], + encoded: [115, 101, 115, 58, 61, 13, 10, 45, 32, 83, 114, 101, 97, 107, 61, 13, 10, ...Array(15).fill(0)], decoded: [ 115, 101, @@ -128,38 +71,8 @@ describe('RemoveSoftLineBreaks', () => { it('should handle input with multiple consecutive soft line breaks', async () => { const input = { - encoded: [ - 104, - 101, - 108, - 108, - 111, - 61, - 13, - 10, - 61, - 13, - 10, - 119, - 111, - 114, - 108, - 100, - ...Array(16).fill(0), - ], - decoded: [ - 104, - 101, - 108, - 108, - 111, - 119, - 111, - 114, - 108, - 100, - ...Array(22).fill(0), - ], + encoded: [104, 101, 108, 108, 111, 61, 13, 10, 61, 13, 10, 119, 111, 114, 108, 100, ...Array(16).fill(0)], + decoded: [104, 101, 108, 108, 111, 119, 111, 114, 108, 100, ...Array(22).fill(0)], }; const witness = await circuit.calculateWitness(input); diff --git a/packages/circuits/tests/rsa.test.ts b/packages/circuits/tests/rsa.test.ts index 4f6481b4e..e2e1ada3c 100644 --- a/packages/circuits/tests/rsa.test.ts +++ b/packages/circuits/tests/rsa.test.ts @@ -1,86 +1,134 @@ -import fs from "fs"; -import path from "path"; -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"; +import fs from 'fs'; +import path from 'path'; +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", () => { +describe('RSA', () => { jest.setTimeout(10 * 60 * 1000); // 10 minutes let circuit: any; let rawEmail: Buffer; 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")); + 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 () { + 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"], + 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.assertOut(witness, {}); }); - it("should verify 1024 bit rsa signature correctly", async function () { + it('should verify 1024 bit rsa signature correctly', async function () { const signature = toCircomBigIntBytes( BigInt( - 102386562682221859025549328916727857389789009840935140645361501981959969535413501251999442013082353139290537518086128904993091119534674934202202277050635907008004079788691412782712147797487593510040249832242022835902734939817209358184800954336078838331094308355388211284440290335887813714894626653613586546719n - ) + 102386562682221859025549328916727857389789009840935140645361501981959969535413501251999442013082353139290537518086128904993091119534674934202202277050635907008004079788691412782712147797487593510040249832242022835902734939817209358184800954336078838331094308355388211284440290335887813714894626653613586546719n, + ), ); const pubkey = toCircomBigIntBytes( BigInt( - 106773687078109007595028366084970322147907086635176067918161636756354740353674098686965493426431314019237945536387044259034050617425729739578628872957481830432099721612688699974185290306098360072264136606623400336518126533605711223527682187548332314997606381158951535480830524587400401856271050333371205030999n - ) + 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"], + 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, {}); }); - it("should fail when verifying with an incorrect signature", async function () { + 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"], + 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, {}) + await circuit.assertOut(witness, {}); } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); + 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 0766b3687..653291ef7 100644 --- a/packages/circuits/tests/select-regex-reveal.test.ts +++ b/packages/circuits/tests/select-regex-reveal.test.ts @@ -1,105 +1,101 @@ -import { wasm } from "circom_tester"; -import path from "path"; +import { wasm } from 'circom_tester'; +import path from 'path'; +describe('Select Regex Reveal', () => { + jest.setTimeout(10 * 60 * 1000); // 10 minutes -describe("Select Regex Reveal", () => { - jest.setTimeout(10 * 60 * 1000); // 10 minutes + let circuit: any; - let circuit: any; - - beforeAll(async () => { - circuit = await wasm( - path.join(__dirname, "./test-circuits/select-regex-reveal-test.circom"), - { - recompile: true, - include: path.join(__dirname, "../../../node_modules"), - } - ); + beforeAll(async () => { + circuit = await wasm(path.join(__dirname, './test-circuits/select-regex-reveal-test.circom'), { + recompile: true, + include: path.join(__dirname, '../../../node_modules'), }); + }); - it("should reveal the substring with maximum revealed length", async function () { - let input = new Array(34).fill(0); - const startIndex = Math.floor(Math.random() * 24); - const revealed = Array.from("zk email").map(char => char.charCodeAt(0)); - for (let i = 0; i < revealed.length; i++) { - input[startIndex + i] = revealed[i]; - } - const witness = await circuit.calculateWitness({ - in: input, - startIndex: startIndex, - }); - await circuit.checkConstraints(witness); - await circuit.assertOut(witness, { out: revealed }) + it('should reveal the substring with maximum revealed length', async function () { + let input = new Array(34).fill(0); + const startIndex = Math.floor(Math.random() * 24); + const revealed = Array.from('zk email').map((char) => char.charCodeAt(0)); + for (let i = 0; i < revealed.length; i++) { + input[startIndex + i] = revealed[i]; + } + const witness = await circuit.calculateWitness({ + in: input, + startIndex: startIndex, }); + await circuit.checkConstraints(witness); + await circuit.assertOut(witness, { out: revealed }); + }); - it("should reveal the substring with non-maximum revealed length", async function () { - let input = new Array(34).fill(0); - const startIndex = 30; - const revealed = Array.from("zk").map(char => char.charCodeAt(0)); - for (let i = 0; i < revealed.length; i++) { - input[startIndex + i] = revealed[i]; - } - const witness = await circuit.calculateWitness({ - in: input, - startIndex: startIndex, - }); - await circuit.checkConstraints(witness); - await circuit.assertOut(witness, { out: revealed.concat([0, 0, 0, 0, 0, 0]) }) + it('should reveal the substring with non-maximum revealed length', async function () { + let input = new Array(34).fill(0); + const startIndex = 30; + const revealed = Array.from('zk').map((char) => char.charCodeAt(0)); + for (let i = 0; i < revealed.length; i++) { + input[startIndex + i] = revealed[i]; + } + const witness = await circuit.calculateWitness({ + in: input, + startIndex: startIndex, }); + await circuit.checkConstraints(witness); + await circuit.assertOut(witness, { out: revealed.concat([0, 0, 0, 0, 0, 0]) }); + }); - it("should fail when all zero", async function () { - let input = new Array(34).fill(0); - const startIndex = Math.floor(Math.random() * 34); - try { - const witness = await circuit.calculateWitness({ - in: input, - startIndex: startIndex, - }); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + it('should fail when all zero', async function () { + let input = new Array(34).fill(0); + const startIndex = Math.floor(Math.random() * 34); + try { + const witness = await circuit.calculateWitness({ + in: input, + startIndex: startIndex, + }); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } - expect.assertions(1); - }); + expect.assertions(1); + }); - it("should fail when startIndex is 0", async function () { - let input = new Array(34).fill(0); - const startIndex = 1 + Math.floor(Math.random() * 24); - 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: startIndex - 1, - }); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + it('should fail when startIndex is 0', async function () { + let input = new Array(34).fill(0); + const startIndex = 1 + Math.floor(Math.random() * 24); + 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: startIndex - 1, + }); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } - expect.assertions(1); - }); + expect.assertions(1); + }); - it("should fail when startIndex is not before 0", async function () { - let input = new Array(34).fill(0); - const startIndex = Math.floor(Math.random() * 23); - 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: startIndex + 1, - }); - await circuit.checkConstraints(witness); - } catch (error) { - expect((error as Error).message).toMatch("Assert Failed"); - } + it('should fail when startIndex is not before 0', async function () { + let input = new Array(34).fill(0); + const startIndex = Math.floor(Math.random() * 23); + 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: startIndex + 1, + }); + await circuit.checkConstraints(witness); + } catch (error) { + expect((error as Error).message).toMatch('Assert Failed'); + } - expect.assertions(1); - }); + expect.assertions(1); + }); }); diff --git a/packages/circuits/tests/sha.test.ts b/packages/circuits/tests/sha.test.ts index 82e8623d6..2ad1aceef 100644 --- a/packages/circuits/tests/sha.test.ts +++ b/packages/circuits/tests/sha.test.ts @@ -1,36 +1,25 @@ -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 { 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'; - -describe("SHA256 for email header", () => { +describe('SHA256 for email header', () => { jest.setTimeout(10 * 60 * 1000); // 10 minutes 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"), - } - ); + 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", "" - ] + 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 [paddedMsg, messageLen] = sha256Pad(Buffer.from(input, 'ascii'), 640); const witness = await circuit.calculateWitness({ paddedIn: Uint8ArrayToCharArray(paddedMsg), @@ -38,7 +27,7 @@ describe("SHA256 for email header", () => { }); await circuit.checkConstraints(witness); - await circuit.assertOut(witness, { out: [...uint8ToBits(shaHash(Buffer.from(input, "ascii")))] }) + await circuit.assertOut(witness, { out: [...uint8ToBits(shaHash(Buffer.from(input, 'ascii')))] }); } }); }); diff --git a/packages/circuits/tests/split-bytes-to-words.test.ts b/packages/circuits/tests/split-bytes-to-words.test.ts index 99fc83e41..c08dd19eb 100644 --- a/packages/circuits/tests/split-bytes-to-words.test.ts +++ b/packages/circuits/tests/split-bytes-to-words.test.ts @@ -1,33 +1,27 @@ -import { wasm as wasm_tester } from "circom_tester"; -import path from "path"; -import { bigIntToChunkedBytes, Uint8ArrayToCharArray } from "@zk-email/helpers/src/binary-format"; +import { wasm as wasm_tester } from 'circom_tester'; +import path from 'path'; +import { bigIntToChunkedBytes, Uint8ArrayToCharArray } from '@zk-email/helpers/src/binary-format'; +describe('SplitBytesToWords Helper unit test', () => { + jest.setTimeout(0.1 * 60 * 1000); + let circuit: any; -describe("SplitBytesToWords Helper unit test", () => { - jest.setTimeout(0.1 * 60 * 1000); - let circuit: any; - - beforeAll(async () => { - circuit = await wasm_tester( - path.join(__dirname, "./test-circuits/split-bytes-to-words-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/split-bytes-to-words-test.circom'), { + recompile: true, + include: path.join(__dirname, '../../../node_modules'), + // output: path.join(__dirname, "./compiled-test-circuits"), }); + }); - it("should split correctly according to bigIntToChunkedBytes function", async function () { - const bytes = new Uint8Array(256).map(() => Math.floor(Math.random() * 256)); - const bytesBigInt = bytes.reduce((acc, val) => (acc << 8n) | BigInt(val), 0n); - const ts_split_to_words = bigIntToChunkedBytes(bytesBigInt, 121, 17); - const ts_split_to_words_bigint = ts_split_to_words.map((word) => BigInt(word)); - const witness = await circuit.calculateWitness({ - in: Uint8ArrayToCharArray(bytes) - }); - await circuit.assertOut(witness, { out: ts_split_to_words_bigint }); + it('should split correctly according to bigIntToChunkedBytes function', async function () { + const bytes = new Uint8Array(256).map(() => Math.floor(Math.random() * 256)); + const bytesBigInt = bytes.reduce((acc, val) => (acc << 8n) | BigInt(val), 0n); + const ts_split_to_words = bigIntToChunkedBytes(bytesBigInt, 121, 17); + const ts_split_to_words_bigint = ts_split_to_words.map((word) => BigInt(word)); + const witness = await circuit.calculateWitness({ + in: Uint8ArrayToCharArray(bytes), }); - + await circuit.assertOut(witness, { out: ts_split_to_words_bigint }); + }); }); diff --git a/packages/helpers/src/binary-format.ts b/packages/helpers/src/binary-format.ts index a549d8654..a1925b7d3 100644 --- a/packages/helpers/src/binary-format.ts +++ b/packages/helpers/src/binary-format.ts @@ -190,14 +190,18 @@ export function packedNBytesToString(packedBytes: bigint[], n: number = 31): str } export function packBytesIntoNBytes(messagePaddedRaw: Uint8Array | string, n = 7): Array { - const messagePadded: Uint8Array = typeof messagePaddedRaw === 'string' ? stringToBytes(messagePaddedRaw) : messagePaddedRaw; + const messagePadded: Uint8Array = + typeof messagePaddedRaw === 'string' ? stringToBytes(messagePaddedRaw) : messagePaddedRaw; const output: Array = []; for (let i = 0; i < messagePadded.length; i++) { if (i % n === 0) { output.push(0n); } const j = (i / n) | 0; - console.assert(j === output.length - 1, 'Not editing the index of the last element -- packing loop invariants bug!'); + console.assert( + j === output.length - 1, + 'Not editing the index of the last element -- packing loop invariants bug!', + ); output[j] += BigInt(messagePadded[i]) << BigInt((i % n) * 8); } return output; diff --git a/packages/helpers/src/chunked-zkey.ts b/packages/helpers/src/chunked-zkey.ts index 6d0053a06..09b540d64 100644 --- a/packages/helpers/src/chunked-zkey.ts +++ b/packages/helpers/src/chunked-zkey.ts @@ -10,9 +10,7 @@ const zkeySuffix = ['b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']; // uncompresses single .gz file. // returns the contents as an ArrayBuffer -export const uncompressGz = async ( - arrayBuffer: ArrayBuffer, -): Promise => { +export const uncompressGz = async (arrayBuffer: ArrayBuffer): Promise => { const output = pako.ungzip(arrayBuffer); const buff = output.buffer; return buff; @@ -31,19 +29,13 @@ async function downloadWithRetries(link: string, downloadAttempts: number) { return response; } } - throw new Error( - `Error downloading ${link} after ${downloadAttempts} retries`, - ); + throw new Error(`Error downloading ${link} after ${downloadAttempts} retries`); } // GET the compressed file from the remote server, then store it with localforage // Note that it must be stored as an uncompressed ArrayBuffer // and named such that filename===`${name}.zkey${a}` in order for it to be found by snarkjs. -export async function downloadFromFilename( - baseUrl: string, - filename: string, - compressed = false, -) { +export async function downloadFromFilename(baseUrl: string, filename: string, compressed = false) { const link = baseUrl + filename; const zkeyResp = await downloadWithRetries(link, 3); @@ -64,28 +56,18 @@ export async function downloadFromFilename( console.log(`Storage of ${filename} successful!`); } -export async function downloadProofFiles( - baseUrl: string, - circuitName: string, - onFileDownloaded: () => void, -) { +export async function downloadProofFiles(baseUrl: string, circuitName: string, onFileDownloaded: () => void) { const filePromises = []; for (const c of zkeySuffix) { const targzFilename = `${circuitName}.zkey${c}${zkeyExtension}`; // const itemCompressed = await localforage.getItem(targzFilename); const item = await localforage.getItem(`${circuitName}.zkey${c}`); if (item) { - console.log( - `${circuitName}.zkey${c}${ - item ? '' : zkeyExtension - } already found in localforage!`, - ); + console.log(`${circuitName}.zkey${c}${item ? '' : zkeyExtension} already found in localforage!`); onFileDownloaded(); continue; } - filePromises.push( - downloadFromFilename(baseUrl, targzFilename, true).then(() => onFileDownloaded()), - ); + filePromises.push(downloadFromFilename(baseUrl, targzFilename, true).then(() => onFileDownloaded())); } console.log(filePromises); await Promise.all(filePromises); @@ -116,11 +98,7 @@ export async function verifyProof(proof: any, publicSignals: any, baseUrl: strin const vkey = await response.json(); console.log('vkey', vkey); - const proofVerified = await snarkjs.groth16.verify( - vkey, - publicSignals, - proof, - ); + const proofVerified = await snarkjs.groth16.verify(vkey, publicSignals, proof); console.log('proofV', proofVerified); return proofVerified; @@ -143,24 +121,16 @@ function bigIntToArray(n: number, k: number, x: bigint) { // taken from generation code in dizkus-circuits tests function pubkeyToXYArrays(pk: string) { - const XArr = bigIntToArray(64, 4, BigInt(`0x${pk.slice(4, 4 + 64)}`)).map( - (el) => el.toString(), - ); - const YArr = bigIntToArray(64, 4, BigInt(`0x${pk.slice(68, 68 + 64)}`)).map( - (el) => el.toString(), - ); + const XArr = bigIntToArray(64, 4, BigInt(`0x${pk.slice(4, 4 + 64)}`)).map((el) => el.toString()); + const YArr = bigIntToArray(64, 4, BigInt(`0x${pk.slice(68, 68 + 64)}`)).map((el) => el.toString()); return [XArr, YArr]; } // taken from generation code in dizkus-circuits tests function sigToRSArrays(sig: string) { - const rArr = bigIntToArray(64, 4, BigInt(`0x${sig.slice(2, 2 + 64)}`)).map( - (el) => el.toString(), - ); - const sArr = bigIntToArray(64, 4, BigInt(`0x${sig.slice(66, 66 + 64)}`)).map( - (el) => el.toString(), - ); + const rArr = bigIntToArray(64, 4, BigInt(`0x${sig.slice(2, 2 + 64)}`)).map((el) => el.toString()); + const sArr = bigIntToArray(64, 4, BigInt(`0x${sig.slice(66, 66 + 64)}`)).map((el) => el.toString()); return [rArr, sArr]; } diff --git a/packages/helpers/src/dkim/index.ts b/packages/helpers/src/dkim/index.ts index 4bd714a17..7a7af7026 100644 --- a/packages/helpers/src/dkim/index.ts +++ b/packages/helpers/src/dkim/index.ts @@ -41,18 +41,18 @@ export async function verifyDKIMSignature( let appliedSanitization; if (dkimResult.status.comment === 'bad signature' && enableSanitization) { const results = await Promise.all( - sanitizers.map((sanitize) => tryVerifyDKIM(sanitize(emailStr), domain).then((result) => ({ - result, - sanitizer: sanitize.name, - }))), + sanitizers.map((sanitize) => + tryVerifyDKIM(sanitize(emailStr), domain).then((result) => ({ + result, + sanitizer: sanitize.name, + })), + ), ); const passed = results.find((r) => r.result.status.result === 'pass'); if (passed) { - console.log( - `DKIM: Verification passed after applying sanitization "${passed.sanitizer}"`, - ); + console.log(`DKIM: Verification passed after applying sanitization "${passed.sanitizer}"`); dkimResult = passed.result; appliedSanitization = passed.sanitizer; } @@ -69,9 +69,7 @@ export async function verifyDKIMSignature( } = dkimResult; if (result !== 'pass') { - throw new Error( - `DKIM signature verification failed for domain ${signingDomain}. Reason: ${comment}`, - ); + throw new Error(`DKIM signature verification failed for domain ${signingDomain}. Reason: ${comment}`); } const pubKeyData = pki.publicKeyFromPem(publicKey.toString()); @@ -98,22 +96,16 @@ async function tryVerifyDKIM(email: Buffer | string, domain: string = '') { let domainToVerifyDKIM = domain; if (!domainToVerifyDKIM) { if (dkimVerifier.headerFrom.length > 1) { - throw new Error( - 'Multiple From header in email and domain for verification not specified', - ); + throw new Error('Multiple From header in email and domain for verification not specified'); } domainToVerifyDKIM = dkimVerifier.headerFrom[0].split('@')[1]; } - const dkimResult = dkimVerifier.results.find( - (d: any) => d.signingDomain === domainToVerifyDKIM, - ); + const dkimResult = dkimVerifier.results.find((d: any) => d.signingDomain === domainToVerifyDKIM); if (!dkimResult) { - throw new Error( - `DKIM signature not found for domain ${domainToVerifyDKIM}`, - ); + throw new Error(`DKIM signature not found for domain ${domainToVerifyDKIM}`); } dkimResult.headers = dkimVerifier.headers; diff --git a/packages/helpers/src/dkim/sanitizers.ts b/packages/helpers/src/dkim/sanitizers.ts index 652f2adea..97a42dac8 100644 --- a/packages/helpers/src/dkim/sanitizers.ts +++ b/packages/helpers/src/dkim/sanitizers.ts @@ -19,10 +19,7 @@ function revertGoogleMessageId(email: string): string { return email; } - const googleReplacedMessageId = getHeaderValue( - email, - 'X-Google-Original-Message-ID', - ); + const googleReplacedMessageId = getHeaderValue(email, 'X-Google-Original-Message-ID'); if (googleReplacedMessageId) { return setHeaderValue(email, 'Message-ID', googleReplacedMessageId); @@ -65,11 +62,6 @@ function sanitizeTabs(email: string): string { return email.replace('=09', '\t'); } -const sanitizers = [ - revertGoogleMessageId, - removeLabels, - insert13Before10, - sanitizeTabs, -]; +const sanitizers = [revertGoogleMessageId, removeLabels, insert13Before10, sanitizeTabs]; export default sanitizers; diff --git a/packages/helpers/src/input-generators.ts b/packages/helpers/src/input-generators.ts index c6e76c41c..b47f56d16 100644 --- a/packages/helpers/src/input-generators.ts +++ b/packages/helpers/src/input-generators.ts @@ -31,10 +31,10 @@ function removeSoftLineBreaks(body: string[]): string[] { let i = 0; while (i < body.length) { if ( - i + 2 < body.length - && body[i] === '61' // '=' character - && body[i + 1] === '13' // '\r' character - && body[i + 2] === '10' + i + 2 < body.length && + body[i] === '61' && // '=' character + body[i + 1] === '13' && // '\r' character + body[i + 2] === '10' ) { // '\n' character // Skip the soft line break sequence @@ -58,10 +58,7 @@ function removeSoftLineBreaks(body: string[]): string[] { * @param params Arguments to control the input generation * @returns Circuit inputs for the EmailVerifier circuit */ -export async function generateEmailVerifierInputs( - rawEmail: Buffer | string, - params: InputGenerationArgs = {}, -) { +export async function generateEmailVerifierInputs(rawEmail: Buffer | string, params: InputGenerationArgs = {}) { const dkimResult = await verifyDKIMSignature(rawEmail); return generateEmailVerifierInputsFromDKIMResult(dkimResult, params); @@ -78,15 +75,10 @@ export function generateEmailVerifierInputsFromDKIMResult( dkimResult: DKIMVerificationResult, params: InputGenerationArgs = {}, ): CircuitInput { - const { - headers, body, bodyHash, publicKey, signature, - } = dkimResult; + const { headers, body, bodyHash, publicKey, signature } = dkimResult; // SHA add padding - const [messagePadded, messagePaddedLen] = sha256Pad( - headers, - params.maxHeadersLength || MAX_HEADER_PADDED_BYTES, - ); + const [messagePadded, messagePaddedLen] = sha256Pad(headers, params.maxHeadersLength || MAX_HEADER_PADDED_BYTES); const circuitInputs: CircuitInput = { emailHeader: Uint8ArrayToCharArray(messagePadded), // Packed into 1 byte signals @@ -97,9 +89,7 @@ export function generateEmailVerifierInputsFromDKIMResult( if (!params.ignoreBodyHashCheck) { if (!body || !bodyHash) { - throw new Error( - 'body and bodyHash are required when ignoreBodyHashCheck is false', - ); + throw new Error('body and bodyHash are required when ignoreBodyHashCheck is false'); } const bodyHashIndex = headers.toString().indexOf(bodyHash); @@ -108,10 +98,7 @@ export function generateEmailVerifierInputsFromDKIMResult( // 65 comes from the 64 at the end and the 1 bit in the start, then 63 comes from the formula to round it up to the nearest 64. // see sha256algorithm.com for a more full explanation of padding length const bodySHALength = Math.floor((body.length + 63 + 65) / 64) * 64; - const [bodyPadded, bodyPaddedLen] = sha256Pad( - body, - Math.max(maxBodyLength, bodySHALength), - ); + const [bodyPadded, bodyPaddedLen] = sha256Pad(body, Math.max(maxBodyLength, bodySHALength)); const { precomputedSha, bodyRemaining, bodyRemainingLength } = generatePartialSHA({ body: bodyPadded, @@ -126,9 +113,7 @@ export function generateEmailVerifierInputsFromDKIMResult( circuitInputs.emailBody = Uint8ArrayToCharArray(bodyRemaining); if (params.removeSoftLineBreaks) { - circuitInputs.decodedEmailBodyIn = removeSoftLineBreaks( - circuitInputs.emailBody, - ); + circuitInputs.decodedEmailBodyIn = removeSoftLineBreaks(circuitInputs.emailBody); } if (params.enableBodyMasking) { diff --git a/packages/helpers/src/sha-utils.ts b/packages/helpers/src/sha-utils.ts index 0db2d8b84..2352b1841 100644 --- a/packages/helpers/src/sha-utils.ts +++ b/packages/helpers/src/sha-utils.ts @@ -1,16 +1,8 @@ import * as CryptoJS from 'crypto'; -import { - assert, - int64toBytes, - int8toBytes, - mergeUInt8Arrays, -} from './binary-format'; +import { assert, int64toBytes, int8toBytes, mergeUInt8Arrays } from './binary-format'; import { Hash } from './lib/fast-sha256'; -export function findIndexInUint8Array( - array: Uint8Array, - selector: Uint8Array, -): number { +export function findIndexInUint8Array(array: Uint8Array, selector: Uint8Array): number { let i = 0; let j = 0; while (i < array.length) { @@ -93,10 +85,7 @@ export function partialSha(msg: Uint8Array, msgLen: number): Uint8Array { } // Puts an end selector, a bunch of 0s, then the length, then fill the rest with 0s. -export function sha256Pad( - message: Uint8Array, - maxShaBytes: number, -): [Uint8Array, number] { +export function sha256Pad(message: Uint8Array, maxShaBytes: number): [Uint8Array, number] { const msgLen = message.length * 8; // bytes to bits const msgLenBytes = int64toBytes(msgLen); diff --git a/packages/helpers/tests/dkim.test.ts b/packages/helpers/tests/dkim.test.ts index 54dd8ea42..6302d8055 100644 --- a/packages/helpers/tests/dkim.test.ts +++ b/packages/helpers/tests/dkim.test.ts @@ -6,9 +6,7 @@ jest.setTimeout(10000); describe('DKIM signature verification', () => { it('should pass for valid email', async () => { - const email = fs.readFileSync( - path.join(__dirname, 'test-data/email-good.eml'), - ); + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-good.eml')); const result = await verifyDKIMSignature(email); @@ -17,25 +15,19 @@ describe('DKIM signature verification', () => { }); it('should fail for invalid selector', async () => { - const email = fs.readFileSync( - path.join(__dirname, 'test-data/email-invalid-selector.eml'), - ); + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-invalid-selector.eml')); expect.assertions(1); try { await verifyDKIMSignature(email); } catch (e) { - expect(e.message).toBe( - 'DKIM signature verification failed for domain icloud.com. Reason: no key', - ); + expect(e.message).toBe('DKIM signature verification failed for domain icloud.com. Reason: no key'); } }); it('should fail for tampered body', async () => { - const email = fs.readFileSync( - path.join(__dirname, 'test-data/email-body-tampered.eml'), - ); + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-body-tampered.eml')); expect.assertions(1); @@ -50,26 +42,20 @@ describe('DKIM signature verification', () => { it('should fail for when DKIM signature is not present for domain', async () => { // In this email From address is user@gmail.com, but the DKIM signature is only for icloud.com - const email = fs.readFileSync( - path.join(__dirname, 'test-data/email-invalid-domain.eml'), - ); + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-invalid-domain.eml')); expect.assertions(1); try { await verifyDKIMSignature(email); } catch (e) { - expect(e.message).toBe( - 'DKIM signature not found for domain gmail.com', - ); + expect(e.message).toBe('DKIM signature not found for domain gmail.com'); } }); it('should be able to override domain', async () => { // From address domain is icloud.com - const email = fs.readFileSync( - path.join(__dirname, 'test-data/email-different-domain.eml'), - ); + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-different-domain.eml')); // Should pass with default domain await verifyDKIMSignature(email); @@ -81,18 +67,14 @@ describe('DKIM signature verification', () => { try { await verifyDKIMSignature(email, 'domain.com'); } catch (e) { - expect(e.message).toBe( - 'DKIM signature not found for domain domain.com', - ); + expect(e.message).toBe('DKIM signature not found for domain domain.com'); } }); }); describe('DKIM with sanitization', () => { it('should pass after removing label from Subject', async () => { - const email = fs.readFileSync( - path.join(__dirname, 'test-data/email-good.eml'), - ); + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-good.eml')); // Add a label to the subject const tamperedEmail = email.toString().replace('Subject: ', 'Subject: [EmailListABC]'); diff --git a/packages/helpers/tests/input-generators.test.ts b/packages/helpers/tests/input-generators.test.ts index 04ce0931e..0830ba945 100644 --- a/packages/helpers/tests/input-generators.test.ts +++ b/packages/helpers/tests/input-generators.test.ts @@ -1,15 +1,13 @@ -import fs from "fs"; -import path from "path"; -import { generateEmailVerifierInputs } from "../src/input-generators"; -import { bytesToString } from "../src/binary-format"; +import fs from 'fs'; +import path from 'path'; +import { generateEmailVerifierInputs } from '../src/input-generators'; +import { bytesToString } from '../src/binary-format'; jest.setTimeout(10000); -describe("Input generators", () => { - it("should generate input from raw email", async () => { - const email = fs.readFileSync( - path.join(__dirname, "test-data/email-good.eml") - ); +describe('Input generators', () => { + it('should generate input from raw email', async () => { + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-good.eml')); const inputs = await generateEmailVerifierInputs(email); @@ -22,10 +20,8 @@ describe("Input generators", () => { expect(inputs.bodyHashIndex).toBeDefined(); }); - it("should generate input without body params when ignoreBodyHash is true", async () => { - const email = fs.readFileSync( - path.join(__dirname, "test-data/email-good.eml") - ); + it('should generate input without body params when ignoreBodyHash is true', async () => { + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-good.eml')); const inputs = await generateEmailVerifierInputs(email, { ignoreBodyHashCheck: true, @@ -40,35 +36,29 @@ describe("Input generators", () => { expect(inputs.bodyHashIndex).toBeFalsy(); }); - it("should generate input with SHA precompute selector", async () => { - const email = fs.readFileSync( - path.join(__dirname, "test-data/email-good-large.eml") - ); + it('should generate input with SHA precompute selector', async () => { + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-good-large.eml')); const inputs = await generateEmailVerifierInputs(email, { - shaPrecomputeSelector: "thousands", + shaPrecomputeSelector: 'thousands', }); expect(inputs.emailBody).toBeDefined(); - const strBody = bytesToString( - Uint8Array.from(inputs.emailBody!.map((b) => Number(b))) - ); + const strBody = bytesToString(Uint8Array.from(inputs.emailBody!.map((b) => Number(b)))); - const expected = "h hundreds of thousands of blocks."; // will round till previous 64x th byte + const expected = 'h hundreds of thousands of blocks.'; // will round till previous 64x th byte expect(strBody.startsWith(expected)).toBeTruthy(); }); - it("should throw if SHA precompute selector is invalid", async () => { - const email = fs.readFileSync( - path.join(__dirname, "test-data/email-good.eml") - ); + it('should throw if SHA precompute selector is invalid', async () => { + const email = fs.readFileSync(path.join(__dirname, 'test-data/email-good.eml')); await expect(() => generateEmailVerifierInputs(email, { - shaPrecomputeSelector: "Bla Bla", - }) + shaPrecomputeSelector: 'Bla Bla', + }), ).rejects.toThrow('SHA precompute selector "Bla Bla" not found in the body'); }); }); diff --git a/scripts/dkim/update-dkim-registry.ts b/scripts/dkim/update-dkim-registry.ts index 9bd1ef5b9..4a9f9b195 100644 --- a/scripts/dkim/update-dkim-registry.ts +++ b/scripts/dkim/update-dkim-registry.ts @@ -1,22 +1,22 @@ -import { ethers, JsonRpcProvider } from "ethers"; -import { buildPoseidon } from "circomlibjs"; -import dns from "dns"; -import path from "path"; -import forge from "node-forge"; -import { bigIntToChunkedBytes } from "@zk-email/helpers/src/binaryFormat"; -const fs = require("fs"); -import { abi } from "../abis/DKIMRegistry.json"; -import { poseidonLarge } from "@zk-email/helpers/src/hash"; -require("dotenv").config(); +import { ethers, JsonRpcProvider } from 'ethers'; +import { buildPoseidon } from 'circomlibjs'; +import dns from 'dns'; +import path from 'path'; +import forge from 'node-forge'; +import { bigIntToChunkedBytes } from '@zk-email/helpers/src/binaryFormat'; +const fs = require('fs'); +import { abi } from '../abis/DKIMRegistry.json'; +import { poseidonLarge } from '@zk-email/helpers/src/hash'; +require('dotenv').config(); async function updateContract(domain: string, pubkeyHashes: string[]) { if (!pubkeyHashes.length) { return; } - if (!process.env.PRIVATE_KEY) throw new Error("Env private key found"); - if (!process.env.RPC_URL) throw new Error("Env RPC URL found"); - if (!process.env.DKIM_REGISTRY) throw new Error("Env DKIM_REGISTRY found"); + if (!process.env.PRIVATE_KEY) throw new Error('Env private key found'); + if (!process.env.RPC_URL) throw new Error('Env RPC URL found'); + if (!process.env.DKIM_REGISTRY) throw new Error('Env DKIM_REGISTRY found'); const provider = new JsonRpcProvider(process.env.RPC_URL); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider); @@ -30,11 +30,7 @@ async function updateContract(domain: string, pubkeyHashes: string[]) { console.log(`Updated hashes for domain ${domain}. Tx: ${tx.hash}`); } -async function getPublicKeyForDomainAndSelector( - domain: string, - selector: string, - print: boolean = true -) { +async function getPublicKeyForDomainAndSelector(domain: string, selector: string, print: boolean = true) { // Construct the DKIM record name let dkimRecordName = `${selector}._domainkey.${domain}`; if (print) console.log(dkimRecordName); @@ -53,7 +49,7 @@ async function getPublicKeyForDomainAndSelector( // The DKIM record is a TXT record containing a string // We need to parse this string to get the public key - let dkimRecord = records[0].join(""); + let dkimRecord = records[0].join(''); let match = dkimRecord.match(/p=([^;]+)/); if (!match) { console.error(`No public key found in DKIM record for ${domain}`); @@ -62,16 +58,16 @@ async function getPublicKeyForDomainAndSelector( // The public key is base64 encoded, we need to decode it let pubkey = match[1]; - let binaryKey = Buffer.from(pubkey, "base64").toString("base64"); + let binaryKey = Buffer.from(pubkey, 'base64').toString('base64'); // Get match let matches = binaryKey.match(/.{1,64}/g); if (!matches) { - console.error("No matches found"); + console.error('No matches found'); return; } - let formattedKey = matches.join("\n"); - if (print) console.log("Key: ", formattedKey); + let formattedKey = matches.join('\n'); + if (print) console.log('Key: ', formattedKey); // Convert to PEM format let pemKey = `-----BEGIN PUBLIC KEY-----\n${formattedKey}\n-----END PUBLIC KEY-----`; @@ -81,18 +77,14 @@ async function getPublicKeyForDomainAndSelector( // Get the modulus n only let n = publicKey.n; - if (print) console.log("Modulus n:", n.toString(16)); + if (print) console.log('Modulus n:', n.toString(16)); return BigInt(publicKey.n.toString()); } async function checkSelector(domain: string, selector: string) { try { - const publicKey = await getPublicKeyForDomainAndSelector( - domain, - selector, - false - ); + const publicKey = await getPublicKeyForDomainAndSelector(domain, selector, false); if (publicKey) { console.log(`Domain: ${domain}, Selector: ${selector} - Match found`); return { @@ -105,9 +97,7 @@ async function checkSelector(domain: string, selector: string) { // console.log(`Domain: ${domain}, Selector: ${selector} - No match found`); } } catch (error) { - console.error( - `Error processing domain: ${domain}, Selector: ${selector} - ${error}` - ); + console.error(`Error processing domain: ${domain}, Selector: ${selector} - ${error}`); } return { @@ -121,57 +111,57 @@ async function checkSelector(domain: string, selector: string) { // Filename is a file where each line is a domain // This searches for default selectors like "google" or "default" async function getDKIMPublicKeysForDomains(filename: string) { - const domains = fs.readFileSync(filename, "utf8").split("\n"); + const domains = fs.readFileSync(filename, 'utf8').split('\n'); const selectors = [ - "google", - "default", - "mail", - "smtpapi", - "dkim", - "200608", - "20230601", - "20221208", - "20210112", - "dkim-201406", - "1a1hai", - "v1", - "v2", - "v3", - "k1", - "k2", - "k3", - "hs1", - "hs2", - "s1", - "s2", - "s3", - "sig1", - "sig2", - "sig3", - "selector", - "selector1", - "selector2", - "mindbox", - "bk", - "sm1", - "sm2", - "gmail", - "10dkim1", - "11dkim1", - "12dkim1", - "memdkim", - "m1", - "mx", - "sel1", - "bk", - "scph1220", - "ml", - "pps1", - "scph0819", - "skiff1", - "s1024", - "selector1", - "dkim-202308" + 'google', + 'default', + 'mail', + 'smtpapi', + 'dkim', + '200608', + '20230601', + '20221208', + '20210112', + 'dkim-201406', + '1a1hai', + 'v1', + 'v2', + 'v3', + 'k1', + 'k2', + 'k3', + 'hs1', + 'hs2', + 's1', + 's2', + 's3', + 'sig1', + 'sig2', + 'sig3', + 'selector', + 'selector1', + 'selector2', + 'mindbox', + 'bk', + 'sm1', + 'sm2', + 'gmail', + '10dkim1', + '11dkim1', + '12dkim1', + 'memdkim', + 'm1', + 'mx', + 'sel1', + 'bk', + 'scph1220', + 'ml', + 'pps1', + 'scph0819', + 'skiff1', + 's1024', + 'selector1', + 'dkim-202308', ]; let results = []; @@ -196,9 +186,7 @@ async function getDKIMPublicKeysForDomains(filename: string) { const publicKey = result.publicKey.toString(); - if ( - !matchedSelectors[result.domain].find((d) => d.publicKey === publicKey) - ) { + if (!matchedSelectors[result.domain].find((d) => d.publicKey === publicKey)) { matchedSelectors[result.domain].push({ selector: result.selector, publicKey, @@ -210,26 +198,17 @@ async function getDKIMPublicKeysForDomains(filename: string) { return matchedSelectors; } -async function updateDKIMRegistry({ - domainListFile, - writeToFile, -}: { - domainListFile: string; - writeToFile: boolean; -}) { +async function updateDKIMRegistry({ domainListFile, writeToFile }: { domainListFile: string; writeToFile: boolean }) { function _writeToFile(filename: string, data: object) { if (!writeToFile) return; - if (!fs.existsSync(path.join(__dirname, "out"))) { - fs.mkdirSync(path.join(__dirname, "out")); + if (!fs.existsSync(path.join(__dirname, 'out'))) { + fs.mkdirSync(path.join(__dirname, 'out')); } - fs.writeFileSync( - path.join(__dirname, "out/" + filename), - JSON.stringify(data, null, 2) - ); + fs.writeFileSync(path.join(__dirname, 'out/' + filename), JSON.stringify(data, null, 2)); } const domainPubKeyMap = await getDKIMPublicKeysForDomains(domainListFile); - _writeToFile("dkim-keys.json", domainPubKeyMap); + _writeToFile('dkim-keys.json', domainPubKeyMap); // const domainPubKeyMap = JSON.parse( // fs.readFileSync(path.join(__dirname, "out/dkim-keys.json")).toString() @@ -249,7 +228,7 @@ async function updateDKIMRegistry({ chunkedDKIMPubKeyMap[domain].push(pubkeyChunked.map((s) => s.toString())); } } - _writeToFile("dkim-keys-chunked.json", chunkedDKIMPubKeyMap); + _writeToFile('dkim-keys-chunked.json', chunkedDKIMPubKeyMap); // Generate pub key hash using 242 * 9 chunks (Poseidon lib don't take more than 16 inputs) const domainHashedPubKeyMap: { [key: string]: string[] } = {}; @@ -264,7 +243,7 @@ async function updateDKIMRegistry({ domainHashedPubKeyMap[domain].push(poseidonHash.toString()); } } - _writeToFile("dkim-keys-hashed.json", domainHashedPubKeyMap); + _writeToFile('dkim-keys-hashed.json', domainHashedPubKeyMap); // Update Mailserver contract with found keys for (let domain of Object.keys(domainHashedPubKeyMap)) { @@ -273,6 +252,6 @@ async function updateDKIMRegistry({ } updateDKIMRegistry({ - domainListFile: path.join(__dirname, "domains.txt"), + domainListFile: path.join(__dirname, 'domains.txt'), writeToFile: true, }); diff --git a/yarn.lock b/yarn.lock index d144c86c0..6a20f568c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7168,6 +7168,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^3.3.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" + bin: + prettier: bin/prettier.cjs + checksum: bc8604354805acfdde6106852d14b045bb20827ad76a5ffc2455b71a8257f94de93f17f14e463fe844808d2ccc87248364a5691488a3304f1031326e62d9276e + languageName: node + linkType: hard + "pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" @@ -7455,6 +7464,8 @@ __metadata: "root-workspace-0b6124@workspace:.": version: 0.0.0-use.local resolution: "root-workspace-0b6124@workspace:." + dependencies: + prettier: ^3.3.3 languageName: unknown linkType: soft