diff --git a/circuits/circuits/disclose.circom b/circuits/circuits/disclose.circom index 3009d3998..146004b47 100644 --- a/circuits/circuits/disclose.circom +++ b/circuits/circuits/disclose.circom @@ -8,22 +8,22 @@ include "./isValid.circom"; include "binary-merkle-root.circom"; template Disclose(nLevels) { - - signal input commitment; // H (secret, mrz) - num signal input secret; + signal input commitment; // H (secret, mrz) - num signal input mrz[93]; signal input merkle_root; signal input merkletree_size; signal input path[nLevels]; signal input siblings[nLevels]; signal input bitmap[90]; - signal input scope[24]; // - ASCII + signal input scope; signal input current_date[6]; // YYMMDD - num signal input majority[2]; // YY - ASCII + signal input address; - signal output validity; // 0 or 1 - signal output revealedData_packed[3]; + //signal output validity; // 0 or 1 signal output nullifier; // Poseidon(secret, scope) - num + signal output revealedData_packed[3]; // Verify the commitment component poseidon_hasheur = Poseidon(4); @@ -57,7 +57,7 @@ template Disclose(nLevels) { for (var i = 0; i < 6; i++) { isValid.validityDateASCII[i] <== mrz[70 + i]; } - validity <== isValid.out; + 1 === isValid.out; signal revealedData[90]; for (var i = 0; i < 88; i++) { revealedData[i] <== mrz[5+i] * bitmap[i]; @@ -68,18 +68,10 @@ template Disclose(nLevels) { // Generate scope nullifier component poseidon_nullifier = Poseidon(2); - component num2Bits[24]; - component bits2Num = Bits2Num(192); - for (var i = 23; i >= 0; i--) { - num2Bits[i]= Num2Bits(8); - num2Bits[i].in <== scope[i]; - for (var j=7 ; j >= 0 ; j--){ - bits2Num.in[(23-i) * 8 + j] <== num2Bits[i].out[j]; - } - } + poseidon_nullifier.inputs[0] <== secret; - poseidon_nullifier.inputs[1] <== bits2Num.out; + poseidon_nullifier.inputs[1] <== scope; nullifier <== poseidon_nullifier.out; } -component main { public [ merkle_root ] } = Disclose(16); \ No newline at end of file +component main { public [ merkle_root, scope, address, current_date] } = Disclose(16); \ No newline at end of file diff --git a/circuits/test/disclose.test.ts b/circuits/test/disclose.test.ts index 72dc8b8ee..ad3ff5624 100644 --- a/circuits/test/disclose.test.ts +++ b/circuits/test/disclose.test.ts @@ -47,9 +47,10 @@ describe("start testing register.circom", function () { path: proof.pathIndices.map(index => index.toString()), siblings: proof.siblings.flat().map(index => index.toString()), bitmap: Array(90).fill(1).map(num => BigInt(num).toString()), - scope: Array(24).fill('0').map(char => BigInt(char.charCodeAt(0)).toString()), + scope: BigInt(0).toString(), current_date: [2, 4, 0, 5, 0, 3].map(num => BigInt(num)), majority: ["1", "8"].map(char => BigInt(char.charCodeAt(0)).toString()), + address: BigInt(0).toString(), }; console.log("inputs", inputs); convertScopeToBinaryAndComputeValue(inputs.scope); diff --git a/circuits/test/register.test.ts b/circuits/test/register.test.ts index 6c0ddd7dd..0112ffc67 100644 --- a/circuits/test/register.test.ts +++ b/circuits/test/register.test.ts @@ -5,59 +5,30 @@ const wasm_tester = require("circom_tester").wasm; import { buildPoseidon } from 'circomlibjs'; import { formatMrz } from '../../common/src/utils/utils'; import { MAX_DATAHASHES_LEN, SignatureAlgorithm, TREE_DEPTH } from "../../common/src/constants/constants"; -import { poseidon2 } from "poseidon-lite"; +import { poseidon4 } from "poseidon-lite"; import { IMT } from "@zk-kit/imt"; import { mockPassportData_sha256WithRSAEncryption_65537 } from "../../common/src/utils/mockPassportData"; import { generateCircuitInputs_Register } from '../../common/src/utils/generateInputs'; +import { packBytes } from "../../common/src/utils/utils"; -describe("start testing register.circom", function () { +describe("Proof of Passport - Circuits - Register flow", function () { this.timeout(0); let inputs: any; let circuit: any; let w: any; - let mrz: any; - let passportData: any; let poseidon: any; + let commitment: any; before(async () => { - circuit = await wasm_tester(path.join(__dirname, "../circuits/register_sha256WithRSAEncryption65537.circom"), { include: ["node_modules"] }, ); poseidon = await buildPoseidon(); const passportData = mockPassportData_sha256WithRSAEncryption_65537 - - const reveal_bitmap = Array(90).fill('1'); - const address = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8"; - - // const generated_inputs = generateCircuitInputs( - // passportData, - // reveal_bitmap, - // address, - // 18, - // { developmentMode: true } - // ); inputs = generateCircuitInputs_Register( passportData, { developmentMode: true } ); - - // inputs = { - // secret: BigInt(112111112).toString(), - // mrz: generated_inputs.mrz, - // econtent: generated_inputs.dataHashes, - // datahashes_padded_length: generated_inputs.dataHashes.length, - // signed_attributes: generated_inputs.eContentBytes, - // pubkey: generated_inputs.pubkey, - // merkle_root: generated_inputs.root, - // path: generated_inputs.pathIndices, - // siblings: generated_inputs.siblings, - // signature_algorithm: generated_inputs.signatureAlgorithm, - // signature: generated_inputs.signature, - // } - - // console.log(JSON.stringify(inputs, null, 2)); - // w = await circuit.calculateWitness(inputs); }); it("compile and load the circuit", async function () { @@ -65,10 +36,15 @@ describe("start testing register.circom", function () { }); it("calculate witness", async function () { w = await circuit.calculateWitness(inputs); - let commitment = await circuit.getOutput(w, ["commitment"]); - let nullifier = await circuit.getOutput(w, ["nullifier"]); - console.log("commitment", commitment); - console.log("nullifier", nullifier); + let commitment_circom = await circuit.getOutput(w, ["commitment"]); + commitment_circom = commitment_circom.commitment; + const formattedMrz = formatMrz(inputs.mrz); + const mrz_bytes = packBytes(formattedMrz); + const commitment_bytes = poseidon4([BigInt(inputs.secret), BigInt(mrz_bytes[0]), BigInt(mrz_bytes[1]), BigInt(mrz_bytes[2])]); + const commitment_js = BigInt(poseidon.F.toString(commitment_bytes)).toString(); + console.log('commitment_js', commitment_js) + console.log('commitment_circom', commitment_circom) + expect(commitment_circom).to.be.equal(commitment_js); }); it("try to calculate witness with bad inputs", async function () { try { diff --git a/common/src/utils/generateInputs.ts b/common/src/utils/generateInputs.ts index a987404bd..e91986029 100644 --- a/common/src/utils/generateInputs.ts +++ b/common/src/utils/generateInputs.ts @@ -3,12 +3,13 @@ import { assert, shaPad } from "./shaPad"; import { PassportData } from "./types"; import { arraysAreEqual, bytesToBigDecimal, formatMrz, formatSigAlg, hash, splitToWords, - toUnsignedByte, getDigestLengthBytes + toUnsignedByte, getDigestLengthBytes, getCurrentDateYYMMDD } from "./utils"; import { IMT } from "@zk-kit/imt"; import { getLeaf } from "./pubkeyTree"; import serializedTree from "../../pubkeys/serialized_tree.json"; import { poseidon2 } from "poseidon-lite"; +import { packBytes } from "../utils/utils"; export function generateCircuitInputs_Register( passportData: PassportData, @@ -33,7 +34,7 @@ export function generateCircuitInputs_Register( const formattedMrz = formatMrz(passportData.mrz); const concatenatedDataHashesHashDigest = hash(passportData.signatureAlgorithm, passportData.dataGroupHashes); - console.log('concatenatedDataHashesHashDigest', concatenatedDataHashesHashDigest); + // console.log('concatenatedDataHashesHashDigest', concatenatedDataHashesHashDigest); assert( arraysAreEqual(passportData.eContent.slice(72, 72 + getDigestLengthBytes(passportData.signatureAlgorithm)), @@ -41,7 +42,7 @@ export function generateCircuitInputs_Register( 'concatenatedDataHashesHashDigest is at the right place in passportData.eContent' ); - console.log('passportData.pubKey.exponent', passportData.pubKey.exponent); + // console.log('passportData.pubKey.exponent', passportData.pubKey.exponent); const sigAlgFormatted = formatSigAlg(passportData.signatureAlgorithm, passportData.pubKey.exponent); @@ -49,16 +50,16 @@ export function generateCircuitInputs_Register( signatureAlgorithm: passportData.signatureAlgorithm, ...passportData.pubKey, }).toString(); - console.log('leaf', leaf); + // console.log('leaf', leaf); const index = tree.indexOf(leaf); - console.log(`Index of pubkey in the registry: ${index}`); + // console.log(`Index of pubkey in the registry: ${index}`); if (index === -1) { throw new Error("Your public key was not found in the registry"); } const proof = tree.createProof(index); - console.log("verifyProof", tree.verifyProof(proof)); + // console.log("verifyProof", tree.verifyProof(proof)); if (passportData.dataGroupHashes.length > MAX_DATAHASHES_LEN) { console.error(`Data hashes too long. Max length is ${MAX_DATAHASHES_LEN} bytes.`); @@ -93,3 +94,45 @@ export function generateCircuitInputs_Register( siblings: proof.siblings.flat().map(index => index.toString()), }; } + +export function generateCircuitInputs_Disclose( + poseidon: any, secret: number, mrz: any, merkletree: IMT, majority: [number, number], address: string +) { + // const tree = new IMT(poseidon2, TREE_DEPTH, 0, 2); + // tree.setNodes(serializedTree); + + // if (options.developmentMode) { + // tree.insert(getLeaf({ + // signatureAlgorithm: passportData.signatureAlgorithm, + // issuer: 'C = TS, O = Government of Syldavia, OU = Ministry of tests, CN = CSCA-TEST', + // modulus: passportData.pubKey.modulus, + // exponent: passportData.pubKey.exponent + // }).toString()); + // } + + const formattedMrz = formatMrz(mrz); + const mrz_bytes = packBytes(formattedMrz); + const commitment_bytes = poseidon([secret, mrz_bytes[0], mrz_bytes[1], mrz_bytes[2]]); + const commitment = BigInt(poseidon.F.toString(commitment_bytes)).toString(); + const index = merkletree.indexOf(commitment); + console.log(`Index of pubkey in the registry: ${index}`); + if (index === -1) { + throw new Error("Your public key was not found in the registry"); + } + const proof = merkletree.createProof(index); + console.log("verifyProof", merkletree.verifyProof(proof)); + + return { + secret: [BigInt(0).toString()], + commitment: commitment, + mrz: formattedMrz.map(byte => String(byte)), + merkle_root: [merkletree.root.toString()], + path: proof.pathIndices.map(index => index.toString()), + siblings: proof.siblings.flat().map(index => index.toString()), + bitmap: Array(90).fill(1).map(num => num.toString()), + scope: [BigInt(0).toString()], + current_date: getCurrentDateYYMMDD().map(datePart => BigInt(datePart).toString()), + majority: majority.map(num => BigInt(num).toString()), + address: [BigInt(address).toString()], + }; +} \ No newline at end of file