mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
@@ -41,7 +41,7 @@ Proof of Passport currently supports the following sig/hash algorithms:
|
||||
|
||||
- [x] sha256WithRSAEncryption
|
||||
- [x] sha1WithRSAEncryption
|
||||
- [ ] rsassaPss (under development)
|
||||
- [x] sha256WithRSASSAPSS
|
||||
- [ ] ecdsa-with-SHA384
|
||||
- [ ] ecdsa-with-SHA1
|
||||
- [ ] ecdsa-with-SHA256
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
// include "@zk-email/circuits/lib/rsa.circom";
|
||||
include "@zk-email/circuits/utils/bytes.circom";
|
||||
include "@zk-email/circuits/lib/sha.circom";
|
||||
include "@zk-email/circuits/utils/array.circom";
|
||||
include "./utils/Sha256BytesStatic.circom";
|
||||
include "./utils/RSASSAPSS.circom";
|
||||
|
||||
|
||||
template PassportVerifier_sha256WithRSASSAPSS_65537(n, k, max_datahashes_bytes) {
|
||||
var hashLen = 32;
|
||||
var eContentBytesLength = 72 + hashLen; // 104
|
||||
|
||||
signal input mrz[93]; // formatted mrz (5 + 88) chars
|
||||
signal input dg1_hash_offset;
|
||||
signal input dataHashes[max_datahashes_bytes];
|
||||
signal input datahashes_padded_length;
|
||||
signal input eContentBytes[eContentBytesLength];
|
||||
|
||||
// pubkey that signed the passport
|
||||
signal input pubkey[k];
|
||||
|
||||
// signature of the passport
|
||||
signal input signature[k];
|
||||
|
||||
// compute sha256 of formatted mrz
|
||||
signal mrzSha[256] <== Sha256BytesStatic(93)(mrz);
|
||||
|
||||
// mrzSha_bytes: list of 32 Bits2Num
|
||||
component mrzSha_bytes[hashLen];
|
||||
|
||||
// cast the 256 bits from mrzSha into a list of 32 bytes
|
||||
for (var i = 0; i < hashLen; i++) {
|
||||
mrzSha_bytes[i] = Bits2Num(8);
|
||||
|
||||
for (var j = 0; j < 8; j++) {
|
||||
mrzSha_bytes[i].in[7 - j] <== mrzSha[i * 8 + j];
|
||||
}
|
||||
}
|
||||
|
||||
// assert mrz_hash equals the one extracted from dataHashes input (bytes dg1_hash_offset to dg1_hash_offset + hashLen)
|
||||
signal dg1Hash[hashLen] <== SelectSubArray(max_datahashes_bytes, hashLen)(dataHashes, dg1_hash_offset, hashLen);
|
||||
for(var i = 0; i < hashLen; i++) {
|
||||
dg1Hash[i] === mrzSha_bytes[i].out;
|
||||
}
|
||||
|
||||
// hash dataHashes dynamically
|
||||
signal dataHashesSha[256] <== Sha256Bytes(max_datahashes_bytes)(dataHashes, datahashes_padded_length);
|
||||
|
||||
// get output of dataHashes sha256 into bytes to check against eContent
|
||||
component dataHashesSha_bytes[hashLen];
|
||||
for (var i = 0; i < hashLen; i++) {
|
||||
dataHashesSha_bytes[i] = Bits2Num(8);
|
||||
for (var j = 0; j < 8; j++) {
|
||||
dataHashesSha_bytes[i].in[7 - j] <== dataHashesSha[i * 8 + j];
|
||||
}
|
||||
}
|
||||
|
||||
// assert dataHashesSha is in eContentBytes in range bytes 72 to 104
|
||||
for(var i = 0; i < hashLen; i++) {
|
||||
eContentBytes[eContentBytesLength - hashLen + i] === dataHashesSha_bytes[i].out;
|
||||
}
|
||||
|
||||
// decode signature to get encoded message
|
||||
component rsaDecode = RSASSAPSS_Decode(n, k);
|
||||
rsaDecode.signature <== signature;
|
||||
rsaDecode.modulus <== pubkey;
|
||||
signal encodedMessage[(n*k) \ 8] <== rsaDecode.eM;
|
||||
|
||||
// verify eContent signature
|
||||
component rsaVerify = RSASSAPSSVerify_SHA256(n*k, eContentBytesLength);
|
||||
rsaVerify.eM <== encodedMessage;
|
||||
rsaVerify.message <== eContentBytes;
|
||||
}
|
||||
61
circuits/circuits/register_sha256WithRSASSAPSS_65537.circom
Normal file
61
circuits/circuits/register_sha256WithRSASSAPSS_65537.circom
Normal file
@@ -0,0 +1,61 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "circomlib/circuits/poseidon.circom";
|
||||
include "@zk-email/circuits/utils/bytes.circom";
|
||||
include "./passport_verifier_sha256WithRSASSAPSS_65537.circom";
|
||||
include "./utils/chunk_data.circom";
|
||||
include "./utils/compute_pubkey_leaf.circom";
|
||||
include "binary-merkle-root.circom";
|
||||
|
||||
template register_sha256WithRSASSAPSS_65537(n, k, max_datahashes_bytes, nLevels, signatureAlgorithm) {
|
||||
signal input secret;
|
||||
|
||||
signal input mrz[93];
|
||||
signal input dg1_hash_offset;
|
||||
signal input econtent[max_datahashes_bytes];
|
||||
signal input datahashes_padded_length;
|
||||
signal input signed_attributes[104];
|
||||
signal input signature[k];
|
||||
|
||||
signal input pubkey[k];
|
||||
signal input merkle_root;
|
||||
signal input path[nLevels];
|
||||
signal input siblings[nLevels];
|
||||
|
||||
signal input attestation_id;
|
||||
|
||||
// Verify inclusion of the pubkey in the pubkey tree
|
||||
signal leaf <== ComputePubkeyLeaf(n, k, signatureAlgorithm)(pubkey);
|
||||
signal computed_merkle_root <== BinaryMerkleRoot(nLevels)(leaf, nLevels, path, siblings);
|
||||
merkle_root === computed_merkle_root;
|
||||
|
||||
// Verify passport validity
|
||||
component PV = PassportVerifier_sha256WithRSASSAPSS_65537(n, k, max_datahashes_bytes);
|
||||
PV.mrz <== mrz;
|
||||
PV.dg1_hash_offset <== dg1_hash_offset;
|
||||
PV.dataHashes <== econtent;
|
||||
PV.datahashes_padded_length <== datahashes_padded_length;
|
||||
PV.eContentBytes <== signed_attributes;
|
||||
PV.pubkey <== pubkey;
|
||||
PV.signature <== signature;
|
||||
|
||||
// Generate the commitment
|
||||
component poseidon_hasher = Poseidon(6);
|
||||
poseidon_hasher.inputs[0] <== secret;
|
||||
poseidon_hasher.inputs[1] <== attestation_id;
|
||||
poseidon_hasher.inputs[2] <== leaf;
|
||||
|
||||
signal mrz_packed[3] <== PackBytes(93)(mrz);
|
||||
for (var i = 0; i < 3; i++) {
|
||||
poseidon_hasher.inputs[i + 3] <== mrz_packed[i];
|
||||
}
|
||||
signal output commitment <== poseidon_hasher.out;
|
||||
|
||||
// Generate the nullifier
|
||||
var chunk_size = 11; // Since ceil(32 / 3) in integer division is 11
|
||||
signal chunked_signature[chunk_size] <== ChunkData(n, k, chunk_size)(signature);
|
||||
signal output nullifier <== Poseidon(chunk_size)(chunked_signature);
|
||||
}
|
||||
|
||||
// We hardcode 1 here for sha256WithRSAEncryption_65537
|
||||
component main { public [ merkle_root, attestation_id ] } = register_sha256WithRSASSAPSS_65537(64, 32, 320, 16, 4);
|
||||
@@ -34,7 +34,7 @@ template Mgf1Sha256(seedLen, maskLen) { //in bytes
|
||||
|
||||
for (var j = 0; j < 32; j++) {
|
||||
//concat seed and counter
|
||||
concated[seedLenBits + j] = num2Bits[i].out[j];
|
||||
concated[seedLenBits + j] = num2Bits[i].out[31-j];
|
||||
}
|
||||
|
||||
sha256[i].in <== concated;
|
||||
|
||||
192
circuits/circuits/utils/RSASSAPSS.circom
Normal file
192
circuits/circuits/utils/RSASSAPSS.circom
Normal file
@@ -0,0 +1,192 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "@zk-email/circuits/lib/rsa.circom";
|
||||
include "@zk-email/circuits/lib/fp.circom";
|
||||
include "@zk-email/circuits/lib/bigint-func.circom";
|
||||
include "circomlib/circuits/bitify.circom";
|
||||
include "circomlib/circuits/sha256/sha256.circom";
|
||||
include "./Mgf1Sha256.circom";
|
||||
include "./xor.circom";
|
||||
|
||||
/// @notice Returns the encoded message in 8bit chunks.
|
||||
/// @param n Number of bits per chunk the modulus is split into.
|
||||
/// @param k Number of chunks the modulus is split into.
|
||||
template RSASSAPSS_Decode(n, k) {
|
||||
signal input signature[k];
|
||||
signal input modulus[k];
|
||||
// signal output eM[k];
|
||||
signal encoded[k];
|
||||
signal eMsgInBits[n*k];
|
||||
signal output eM[(n*k)\8]; //8 bit words
|
||||
|
||||
component bigPow = FpPow65537Mod(n, k);
|
||||
for (var i = 0; i < k; i++) {
|
||||
bigPow.base[i] <== signature[i];
|
||||
bigPow.modulus[i] <== modulus[i];
|
||||
}
|
||||
|
||||
encoded <== bigPow.out;
|
||||
|
||||
component num2Bits[k];
|
||||
for (var i = 0; i < k; i++) {
|
||||
num2Bits[i] = Num2Bits(n);
|
||||
num2Bits[i].in <== encoded[k-1-i];
|
||||
|
||||
for (var j = 0; j < n; j++) {
|
||||
eMsgInBits[i * n + j] <== num2Bits[i].out[n-j-1];
|
||||
}
|
||||
}
|
||||
|
||||
component bits2Num[(n*k)\8];
|
||||
for (var i = 0; i < (n*k)\8; i++) {
|
||||
bits2Num[i] = Bits2Num(8);
|
||||
for (var j = 0; j < 8; j++) {
|
||||
bits2Num[i].in[7-j] <== eMsgInBits[i*8 + j];
|
||||
}
|
||||
eM[(n*k)\8 - i -1] <== bits2Num[i].out;
|
||||
}
|
||||
}
|
||||
|
||||
/// @param emBits Length of the encoded message in bits.
|
||||
/// @param messageLen Length of the message in bytes.
|
||||
/// @param n Number of bits per chunk the modulus is split into.
|
||||
/// @param k Number of chunks the modulus is split into.
|
||||
template RSASSAPSSVerify_SHA256(emBits, messageLen) {
|
||||
var emLen = div_ceil(emBits, 8);
|
||||
signal input eM[emLen];
|
||||
signal input message[messageLen];
|
||||
signal mHash[256];
|
||||
var hLen = 32;
|
||||
var sLen = 32;
|
||||
var hLenBits = 256; //sha256
|
||||
var sLenBits = 256; //sha256
|
||||
var emLenBits = emLen * 8;
|
||||
|
||||
signal messageBits[messageLen*8];
|
||||
component num2BitsMessage[messageLen];
|
||||
for (var i = 0; i < messageLen; i++) {
|
||||
num2BitsMessage[i] = Num2Bits(8);
|
||||
num2BitsMessage[i].in <== message[i];
|
||||
for (var j = 0; j < 8; j++) {
|
||||
messageBits[i*8 +j] <== num2BitsMessage[i].out[7-j];
|
||||
}
|
||||
}
|
||||
|
||||
//mHash
|
||||
component sha256 = Sha256(832);
|
||||
sha256.in <== messageBits;
|
||||
for (var i = 0; i < 256; i++) {
|
||||
mHash[i] <== sha256.out[i];
|
||||
}
|
||||
|
||||
//If emLen < hLen + sLen + 2, output "inconsistent" and stop.
|
||||
assert(emLen >= 32 + 32 +2);
|
||||
|
||||
//should end with 0xBC (188 in decimal)
|
||||
assert(eM[0] == 188); //inconsistent
|
||||
|
||||
signal eMsgInBits[emLen * 8];
|
||||
signal maskedDB[(emLen - hLen - 1) * 8];
|
||||
signal hash[hLen * 8];
|
||||
var dbMaskLen = emLen - hLen - 1;
|
||||
signal dbMask[dbMaskLen * 8];
|
||||
signal DB[dbMaskLen * 8];
|
||||
signal salt[hLen * 8];
|
||||
|
||||
//split eM into bits
|
||||
component num2Bits[emLen];
|
||||
for (var i = 0; i < emLen; i++) {
|
||||
num2Bits[i] = Num2Bits(8);
|
||||
num2Bits[i].in <== eM[emLen-1-i];
|
||||
|
||||
for (var j = 0; j < 8; j++) {
|
||||
eMsgInBits[i * 8 + j] <== num2Bits[i].out[8-j-1];
|
||||
}
|
||||
}
|
||||
|
||||
//extract maskedDB. leftmost emLen - hLen - 1 octets of EM
|
||||
for (var i=0; i< (emLen - hLen -1) * 8; i++) {
|
||||
maskedDB[i] <== eMsgInBits[i];
|
||||
}
|
||||
|
||||
//Ref: https://github.com/directdemocracy-vote/app/blob/d0590b5515e749fa72fc50f05062273eb2465da1/httpdocs/app/js/rsa-blind.js#L183
|
||||
signal mask <== 0xff00 >> (emLenBits / 8 - emBits) & 0xff;
|
||||
signal maskBits[8];
|
||||
component num2BitsMask = Num2Bits(8);
|
||||
num2BitsMask.in <== mask;
|
||||
for (var i = 0; i < 8; i++) {
|
||||
maskBits[i] <== num2BitsMask.out[7-i];
|
||||
}
|
||||
for (var i=0; i<8; i++) {
|
||||
assert(maskBits[i] & maskedDB[i] == 0);
|
||||
}
|
||||
|
||||
//extract hash
|
||||
for (var i=0; i<hLenBits; i++) {
|
||||
hash[i] <== eMsgInBits[(emLenBits) - hLenBits-8 +i];
|
||||
}
|
||||
|
||||
//DbMask MGF1
|
||||
component MGF1 = Mgf1Sha256(hLen, dbMaskLen);
|
||||
for (var i = 0; i < (hLenBits); i++) {
|
||||
MGF1.seed[i] <== hash[i];
|
||||
}
|
||||
for (var i = 0; i < dbMaskLen * 8; i++) {
|
||||
dbMask[i] <== MGF1.out[i];
|
||||
}
|
||||
|
||||
//DB = maskedDB xor dbMask
|
||||
component xor = Xor2(dbMaskLen * 8);
|
||||
for (var i = 0; i < dbMaskLen * 8; i++) {
|
||||
xor.a[i] <== maskedDB[i];
|
||||
xor.b[i] <== dbMask[i];
|
||||
}
|
||||
// Ref: https://github.com/directdemocracy-vote/app/blob/d0590b5515e749fa72fc50f05062273eb2465da1/httpdocs/app/js/rsa-blind.js#L188-L190
|
||||
for (var i = 0; i < dbMaskLen * 8; i++) {
|
||||
//setting the first leftmost byte to 0
|
||||
if (i==0) {
|
||||
DB[i] <== 0;
|
||||
} else {
|
||||
DB[i] <== xor.out[i];
|
||||
}
|
||||
}
|
||||
|
||||
// If the emLen - hLen - sLen - 2 leftmost octets of DB are not
|
||||
// zero, output "inconsistent" and stop.
|
||||
for (var i = 0; i < (emLenBits-528); i++) { //hLenBits + sLenBits + 16 = 256 + 256 + 16 = 528
|
||||
assert(DB[i] == 0);
|
||||
}
|
||||
// if the octet at position emLen - hLen - sLen - 1 (the
|
||||
// leftmost position is "position 1") does not have hexadecimal
|
||||
// value 0x01, output "inconsistent" and stop.
|
||||
component bits2Num = Bits2Num(8);
|
||||
for (var i = 0; i < 8; i++) {
|
||||
bits2Num.in[7-i] <== DB[(emLenBits)- 528 +i]; //emLen - hLen - sLen - 1
|
||||
|
||||
}
|
||||
assert(bits2Num.out == 1);
|
||||
|
||||
//extract salt
|
||||
for (var i = 0; i < sLenBits; i++) {
|
||||
//last sLenBits (256) bits of DB
|
||||
salt[256 -1 - i] <== DB[(dbMaskLen * 8) -1 - i];
|
||||
}
|
||||
|
||||
//M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
|
||||
signal mDash[576]; // 8 + hLen + sLen = 8 + 32 + 32 = 72 bytes = 576 bits
|
||||
for (var i = 0; i < 64; i++) {
|
||||
mDash[i] <== 0;
|
||||
}
|
||||
for (var i = 0 ; i < 256; i++) {
|
||||
mDash[64 + i] <== mHash[i];
|
||||
}
|
||||
for (var i = 0; i < 256; i++) {
|
||||
mDash[320 + i] <== salt[i];
|
||||
}
|
||||
|
||||
component hDash = Sha256(576);
|
||||
hDash.in <== mDash;
|
||||
for (var i = 0; i < 256; i++) {
|
||||
assert(hDash.out[i] == hash[i]);
|
||||
}
|
||||
}
|
||||
11
circuits/circuits/utils/xor.circom
Normal file
11
circuits/circuits/utils/xor.circom
Normal file
@@ -0,0 +1,11 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
template Xor2(n) {
|
||||
signal input a[n];
|
||||
signal input b[n];
|
||||
signal output out[n];
|
||||
|
||||
for (var k=0; k<n; k++) {
|
||||
out[k] <== a[k] + b[k] - 2*a[k]*b[k];
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ build_circuit() {
|
||||
echo "Size of ${CIRCUIT_NAME}_final.zkey: $(wc -c <build/${CIRCUIT_NAME}_final.zkey) bytes"
|
||||
}
|
||||
|
||||
declare -a CIRCUITS=("register_sha256WithRSAEncryption_65537" "register_sha1WithRSAEncryption_65537" "disclose")
|
||||
declare -a CIRCUITS=("register_sha256WithRSAEncryption_65537" "register_sha1WithRSAEncryption_65537" "register_sha256WithRSAEncryption_65537" "disclose")
|
||||
|
||||
TOTAL_START_TIME=$(date +%s)
|
||||
for CIRCUIT_NAME in "${CIRCUITS[@]}"; do
|
||||
|
||||
@@ -32,10 +32,10 @@ const sampleDataHashes = [
|
||||
[76, 123, -40, 13, 51, -29, 72, -11, 59, -63, -18, -90, 103, 49, 23, -92, -85, -68, -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38]
|
||||
]
|
||||
] as [number, number[]][]
|
||||
const signatureAlgorithm = 'rsassaPss'
|
||||
const signatureAlgorithm = 'sha256WithRSASSAPSS'
|
||||
const hashLen = 32
|
||||
|
||||
export function genMockPassportData_rsassaPss_65537(): PassportData {
|
||||
export function genMockPassportData_sha256WithRSASSAPSS_65537(): PassportData {
|
||||
const keypair = forge.pki.rsa.generateKeyPair(2048);
|
||||
const privateKeyPem = forge.pki.privateKeyToPem(keypair.privateKey);
|
||||
|
||||
@@ -117,7 +117,7 @@ function verify(passportData: PassportData): boolean {
|
||||
return isVerified;
|
||||
}
|
||||
|
||||
const mockPassportData = genMockPassportData_rsassaPss_65537();
|
||||
const mockPassportData = genMockPassportData_sha256WithRSASSAPSS_65537();
|
||||
console.log("Passport Data:", JSON.stringify(mockPassportData, null, 2));
|
||||
console.log("Signature valid:", verify(mockPassportData));
|
||||
|
||||
|
||||
@@ -36,10 +36,10 @@ const sampleDataHashes = [
|
||||
[76, 123, -40, 13, 51, -29, 72, -11, 59, -63, -18, -90, 103, 49, 23, -92, -85, -68, -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38]
|
||||
]
|
||||
] as [number, number[]][]
|
||||
const signatureAlgorithm = 'rsassaPss'
|
||||
const signatureAlgorithm = 'sha256WithRSASSAPSS'
|
||||
const hashLen = 32
|
||||
|
||||
export function genMockPassportData_rsassaPss_65537(): PassportData {
|
||||
export function genMockPassportData_sha256WithRSASSAPSS_65537(): PassportData {
|
||||
const keypair = forge.pki.rsa.generateKeyPair(2048);
|
||||
const privateKeyPem = forge.pki.privateKeyToPem(keypair.privateKey);
|
||||
|
||||
@@ -213,7 +213,7 @@ function BufferXOR(a: Buffer, b: Buffer) {
|
||||
}
|
||||
|
||||
|
||||
const mockPassportData = genMockPassportData_rsassaPss_65537();
|
||||
const mockPassportData = genMockPassportData_sha256WithRSASSAPSS_65537();
|
||||
console.log("Passport Data:", JSON.stringify(mockPassportData, null, 2));
|
||||
console.log("Signature valid:", verify(mockPassportData));
|
||||
|
||||
|
||||
132
circuits/test/RSSSSAPSS.test.ts
Normal file
132
circuits/test/RSSSSAPSS.test.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { describe } from 'mocha'
|
||||
import { assert, expect } from 'chai'
|
||||
import path from "path";
|
||||
const wasm_tester = require("circom_tester").wasm;
|
||||
import { poseidon1, poseidon6 } from "poseidon-lite";
|
||||
import { mockPassportData_sha256WithRSASSAPSS_65537 } from "../../common/src/utils/mockPassportData";
|
||||
import { generateCircuitInputsRegister } from '../../common/src/utils/generateInputs';
|
||||
import { getLeaf } from '../../common/src/utils/pubkeyTree';
|
||||
import { packBytes } from '../../common/src/utils/utils';
|
||||
|
||||
describe("Proof of Passport - Circuits - RSASSAPSS", function () {
|
||||
this.timeout(0);
|
||||
let inputs: any;
|
||||
let circuit: any;
|
||||
let passportData = mockPassportData_sha256WithRSASSAPSS_65537;
|
||||
let attestation_id: string;
|
||||
|
||||
before(async () => {
|
||||
circuit = await wasm_tester(
|
||||
path.join(__dirname, "../circuits/register_sha256WithRSASSAPSS_65537.circom"),
|
||||
{
|
||||
include: [
|
||||
"node_modules",
|
||||
"node_modules/@zk-email/circuits/helpers/sha.circom",
|
||||
"./node_modules/@zk-kit/binary-merkle-root.circom/src",
|
||||
"./node_modules/circomlib/circuits"
|
||||
]
|
||||
},
|
||||
);
|
||||
|
||||
const secret = BigInt(Math.floor(Math.random() * Math.pow(2, 254))).toString();
|
||||
console.log("secret", secret);
|
||||
|
||||
const attestation_name = "E-PASSPORT";
|
||||
attestation_id = poseidon1([
|
||||
BigInt(Buffer.from(attestation_name).readUIntBE(0, 6))
|
||||
]).toString();
|
||||
|
||||
inputs = generateCircuitInputsRegister(
|
||||
secret,
|
||||
attestation_id,
|
||||
passportData,
|
||||
[passportData],
|
||||
);
|
||||
});
|
||||
|
||||
it("should compile and load the circuit", async function () {
|
||||
expect(circuit).to.not.be.undefined;
|
||||
});
|
||||
|
||||
it("should calculate the witness with correct inputs", async function () {
|
||||
console.time('calculateWitness')
|
||||
const w = await circuit.calculateWitness(inputs);
|
||||
console.timeEnd('calculateWitness')
|
||||
await circuit.checkConstraints(w);
|
||||
|
||||
console.log("nullifier", (await circuit.getOutput(w, ["nullifier"])).nullifier);
|
||||
|
||||
const commitment_circom = (await circuit.getOutput(w, ["commitment"])).commitment;
|
||||
|
||||
const mrz_bytes = packBytes(inputs.mrz);
|
||||
const commitment_bytes = poseidon6([
|
||||
inputs.secret[0],
|
||||
attestation_id,
|
||||
getLeaf({
|
||||
signatureAlgorithm: passportData.signatureAlgorithm,
|
||||
modulus: passportData.pubKey.modulus,
|
||||
exponent: passportData.pubKey.exponent
|
||||
}),
|
||||
mrz_bytes[0],
|
||||
mrz_bytes[1],
|
||||
mrz_bytes[2]
|
||||
]);
|
||||
const commitment_js = commitment_bytes.toString();
|
||||
console.log('commitment_js', commitment_js)
|
||||
console.log('commitment_circom', commitment_circom)
|
||||
expect(commitment_circom).to.be.equal(commitment_js);
|
||||
});
|
||||
|
||||
it("should fail to calculate witness with invalid mrz", async function () {
|
||||
try {
|
||||
const invalidInputs = {
|
||||
...inputs,
|
||||
mrz: Array(93).fill(0).map(byte => BigInt(byte).toString())
|
||||
}
|
||||
await circuit.calculateWitness(invalidInputs);
|
||||
expect.fail("Expected an error but none was thrown.");
|
||||
} catch (error) {
|
||||
expect(error.message).to.include("Assert Failed");
|
||||
}
|
||||
});
|
||||
|
||||
it("should fail to calculate witness with invalid econtent", async function () {
|
||||
try {
|
||||
const invalidInputs = {
|
||||
...inputs,
|
||||
econtent: inputs.econtent.map((byte: string) => String((parseInt(byte, 10) + 1) % 256)),
|
||||
}
|
||||
await circuit.calculateWitness(invalidInputs);
|
||||
expect.fail("Expected an error but none was thrown.");
|
||||
} catch (error) {
|
||||
expect(error.message).to.include("Assert Failed");
|
||||
}
|
||||
});
|
||||
|
||||
it("should fail to calculate witness with invalid signature", async function () {
|
||||
try {
|
||||
const invalidInputs = {
|
||||
...inputs,
|
||||
signature: inputs.signature.map((byte: string) => String((parseInt(byte, 10) + 1) % 256)),
|
||||
}
|
||||
await circuit.calculateWitness(invalidInputs);
|
||||
expect.fail("Expected an error but none was thrown.");
|
||||
} catch (error) {
|
||||
expect(error.message).to.include("Assert Failed");
|
||||
}
|
||||
});
|
||||
|
||||
it("should fail to calculate witness with invalid merkle root", async function () {
|
||||
try {
|
||||
const invalidInputs = {
|
||||
...inputs,
|
||||
merkle_root: inputs.merkle_root.map((byte: string) => String((parseInt(byte, 10) + 1) % 256)),
|
||||
}
|
||||
await circuit.calculateWitness(invalidInputs);
|
||||
expect.fail("Expected an error but none was thrown.");
|
||||
} catch (error) {
|
||||
expect(error.message).to.include("Assert Failed");
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -17,8 +17,8 @@ export enum SignatureAlgorithm {
|
||||
sha256WithRSAEncryption_65537 = 1,
|
||||
sha256WithRSAEncryption_3 = 2,
|
||||
sha1WithRSAEncryption_65537 = 3,
|
||||
rsassaPss_65537 = 4,
|
||||
rsassaPss_3 = 5,
|
||||
sha256WithRSASSAPSS_65537 = 4,
|
||||
sha256WithRSASSAPSS_3 = 5,
|
||||
ecdsa_with_SHA384 = 6,
|
||||
ecdsa_with_SHA1 = 7,
|
||||
ecdsa_with_SHA256 = 8,
|
||||
|
||||
@@ -56,9 +56,14 @@ export function toStandardName(jmrtdName: string): string {
|
||||
case "SSAwithRSA/PSS":
|
||||
case "RSASSA-PSS":
|
||||
case "rsassa-pss":
|
||||
case "rsassaPss":
|
||||
case "rsassapss":
|
||||
case "rsapss":
|
||||
case "SHA256withRSAandMGF1":
|
||||
case "id-mgf1":
|
||||
return "rsassaPss";
|
||||
return "sha256WithRSASSAPSS";
|
||||
// we call it sha256WithRSASSAPSS even if specs says rsassaPss because there are multiple hash functions used
|
||||
// e.g. Italy uses sha512 with it
|
||||
|
||||
|
||||
// added this one for iOS
|
||||
|
||||
@@ -34,7 +34,11 @@ export function generateCircuitInputsRegister(
|
||||
}
|
||||
}
|
||||
|
||||
if (!["sha256WithRSAEncryption"].includes(signatureAlgorithm)) {
|
||||
if (![
|
||||
"sha256WithRSAEncryption",
|
||||
// "sha1WithRSAEncryption",
|
||||
// "sha256WithRSASSAPSS"
|
||||
].includes(signatureAlgorithm)) {
|
||||
console.error(`${signatureAlgorithm} has not been implemented.`);
|
||||
throw new Error(`${signatureAlgorithm} has not been implemented.`);
|
||||
}
|
||||
@@ -86,7 +90,7 @@ export function generateCircuitInputsRegister(
|
||||
return {
|
||||
secret: [secret],
|
||||
mrz: formattedMrz.map(byte => String(byte)),
|
||||
// dg1_hash_offset: [dg1HashOffset.toString()], uncomment when adding new circuits
|
||||
// dg1_hash_offset: [dg1HashOffset.toString()], // uncomment when adding new circuits
|
||||
econtent: Array.from(messagePadded).map((x) => x.toString()),
|
||||
datahashes_padded_length: [messagePaddedLen.toString()],
|
||||
signed_attributes: eContent.map(toUnsignedByte).map(byte => String(byte)),
|
||||
|
||||
@@ -102,9 +102,9 @@ export const mockPassportData_sha1WithRSAEncryption_65537 = {
|
||||
"photoBase64": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3..."
|
||||
}
|
||||
|
||||
export const mockPassportData_rsassaPss_65537 = {
|
||||
export const mockPassportData_sha256WithRSASSAPSS_65537 = {
|
||||
"mrz": "P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02",
|
||||
"signatureAlgorithm": "rsassaPss",
|
||||
"signatureAlgorithm": "sha256WithRSASSAPSS",
|
||||
"pubKey": {
|
||||
"modulus": "27981978959425503209292172727411418014990488071831976226616367950429509197421162582363593871537790010637936055771010989334091016580571842937938354969046967519746517641154578603398020951481965428574606776389054131169105002076650294369622499723554669350745204676674747140249001021406402432647568831293745606703965825595133008436759474663968651546630831308202454181181120020140624552468338395531631589140331577857081313096404575404894488069125604202487567850880274432629308635934045271542662361749283762712193704727156223863656866893752036283212382351869615567264550513950129097969243499462760447180472872921300872481279",
|
||||
"exponent": "65537"
|
||||
@@ -210,6 +210,6 @@ export const mockPassportData_SHA384withECDSA = {
|
||||
export const mockPassportDatas = [
|
||||
mockPassportData_sha256WithRSAEncryption_65537,
|
||||
mockPassportData_sha1WithRSAEncryption_65537,
|
||||
mockPassportData_rsassaPss_65537,
|
||||
mockPassportData_sha256WithRSASSAPSS_65537,
|
||||
// mockPassportData_SHA384withECDSA // temp cause formatting of ecdsa key is not done well now
|
||||
]
|
||||
@@ -2,6 +2,7 @@ import { poseidon12, poseidon2, poseidon8 } from "poseidon-lite"
|
||||
import { SignatureAlgorithm, PUBKEY_TREE_DEPTH } from "../constants/constants";
|
||||
import { IMT } from '@zk-kit/imt'
|
||||
import { bigIntToChunkedBytes, formatSigAlgNameForCircuit } from "./utils";
|
||||
import { toStandardName } from "./formatNames";
|
||||
|
||||
export function buildPubkeyTree(pubkeys: any[]) {
|
||||
let leaves: bigint[] = []
|
||||
@@ -38,17 +39,18 @@ export function getLeaf(pubkey: any, i?: number): bigint {
|
||||
pubkey.publicKeyQ = pubkey.pubKey.publicKeyQ
|
||||
}
|
||||
|
||||
const sigAlgFormatted = formatSigAlgNameForCircuit(pubkey.signatureAlgorithm, pubkey.exponent)
|
||||
const sigAlgFormatted = toStandardName(pubkey.signatureAlgorithm)
|
||||
const sigAlgFormattedForCircuit = formatSigAlgNameForCircuit(sigAlgFormatted, pubkey.exponent)
|
||||
|
||||
// console.log('pubkey', pubkey)
|
||||
// console.log('sigAlgFormatted', sigAlgFormatted)
|
||||
if (
|
||||
sigAlgFormatted === "sha256WithRSAEncryption_65537"
|
||||
|| sigAlgFormatted === "sha256WithRSAEncryption_3"
|
||||
|| sigAlgFormatted === "sha1WithRSAEncryption_65537"
|
||||
|| sigAlgFormatted === "rsassaPss_65537"
|
||||
|| sigAlgFormatted === "rsassaPss_3"
|
||||
|| sigAlgFormatted === "sha512WithRSAEncryption_65537"
|
||||
sigAlgFormattedForCircuit === "sha256WithRSAEncryption_65537"
|
||||
|| sigAlgFormattedForCircuit === "sha256WithRSAEncryption_3"
|
||||
|| sigAlgFormattedForCircuit === "sha1WithRSAEncryption_65537"
|
||||
|| sigAlgFormattedForCircuit === "sha256WithRSASSAPSS_65537"
|
||||
|| sigAlgFormattedForCircuit === "sha256WithRSASSAPSS_3"
|
||||
|| sigAlgFormattedForCircuit === "sha512WithRSAEncryption_65537"
|
||||
) {
|
||||
// Converting pubkey.modulus into 11 chunks of 192 bits, assuming it is originally 2048 bits.
|
||||
// This is because Poseidon circuit only supports an array of 16 elements, and field size is 254.
|
||||
@@ -57,22 +59,22 @@ export function getLeaf(pubkey: any, i?: number): bigint {
|
||||
// console.log('pubkeyChunked', pubkeyChunked.length, pubkeyChunked)
|
||||
try {
|
||||
// leaf is poseidon(signatureAlgorithm, ...pubkey)
|
||||
return poseidon12([SignatureAlgorithm[sigAlgFormatted], ...pubkeyChunked])
|
||||
return poseidon12([SignatureAlgorithm[sigAlgFormattedForCircuit], ...pubkeyChunked])
|
||||
} catch (err) {
|
||||
console.log('err', err, i, sigAlgFormatted, pubkey)
|
||||
console.log('err', err, i, sigAlgFormattedForCircuit, pubkey)
|
||||
}
|
||||
} else if (
|
||||
sigAlgFormatted === "ecdsa_with_SHA1"
|
||||
|| sigAlgFormatted === "ecdsa_with_SHA224"
|
||||
|| sigAlgFormatted === "ecdsa_with_SHA384"
|
||||
|| sigAlgFormatted === "ecdsa_with_SHA256"
|
||||
|| sigAlgFormatted === "ecdsa_with_SHA512"
|
||||
sigAlgFormattedForCircuit === "ecdsa_with_SHA1"
|
||||
|| sigAlgFormattedForCircuit === "ecdsa_with_SHA224"
|
||||
|| sigAlgFormattedForCircuit === "ecdsa_with_SHA384"
|
||||
|| sigAlgFormattedForCircuit === "ecdsa_with_SHA256"
|
||||
|| sigAlgFormattedForCircuit === "ecdsa_with_SHA512"
|
||||
) {
|
||||
try {
|
||||
// this will be replaced by just X and Y or pubkey in publicKeyQ
|
||||
return poseidon8([SignatureAlgorithm[sigAlgFormatted], pubkey.pub, pubkey.prime, pubkey.a, pubkey.b, pubkey.generator, pubkey.order, pubkey.cofactor])
|
||||
return poseidon8([SignatureAlgorithm[sigAlgFormattedForCircuit], pubkey.pub, pubkey.prime, pubkey.a, pubkey.b, pubkey.generator, pubkey.order, pubkey.cofactor])
|
||||
} catch (err) {
|
||||
console.log('err', err, i, sigAlgFormatted, pubkey)
|
||||
console.log('err', err, i, sigAlgFormattedForCircuit, pubkey)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,7 +194,7 @@ export function hash(signatureAlgorithm: string, bytesArray: number[]) {
|
||||
? sha1(unsignedBytesArray)
|
||||
: (signatureAlgorithm == 'SHA384withECDSA')
|
||||
? sha384(unsignedBytesArray)
|
||||
: (signatureAlgorithm == 'sha256WithRSAEncryption' || signatureAlgorithm == 'rsassaPss')
|
||||
: (signatureAlgorithm == 'sha256WithRSAEncryption' || signatureAlgorithm == 'sha256WithRSASSAPSS')
|
||||
? sha256(unsignedBytesArray)
|
||||
: sha256(unsignedBytesArray); // defaults to sha256
|
||||
return hexToSignedBytes(hash);
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
/*
|
||||
Copyright 2021 0KIMS association.
|
||||
|
||||
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
contract Verifier_register_sha256WithRSASSAPSS_65537 {
|
||||
// Scalar field size
|
||||
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
// Base field size
|
||||
uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
|
||||
// Verification Key data
|
||||
uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
|
||||
uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
|
||||
uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
|
||||
uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
|
||||
uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
|
||||
uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
|
||||
uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
|
||||
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
|
||||
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
|
||||
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
||||
uint256 constant deltax1 = 2513356704415346673552161314305955270236630903884681993780363069379262270944;
|
||||
uint256 constant deltax2 = 2561660084047439280986367104146460235004641848496139823103770214612527114094;
|
||||
uint256 constant deltay1 = 16723398497241255269184728114814174364828886103396228033236460836502696283958;
|
||||
uint256 constant deltay2 = 18406674030956056018589715181737882583854065581403281200957779094299343047709;
|
||||
|
||||
|
||||
uint256 constant IC0x = 6516154797273814180336004176967344307104266312158582012392061120100851162901;
|
||||
uint256 constant IC0y = 7011411371762049720135394743588784168330811849030613049161469013902729963131;
|
||||
|
||||
uint256 constant IC1x = 7490839539779982688993491760112859705035583352389262038261439790637635773288;
|
||||
uint256 constant IC1y = 3238512700884050445458358383672608752951570151934557834980826762817490123688;
|
||||
|
||||
uint256 constant IC2x = 15752392097507176707308873155820389988651860920408165055927698306096626444697;
|
||||
uint256 constant IC2y = 5976112676946398219828298974913973178576215643860049436785492553204522425577;
|
||||
|
||||
uint256 constant IC3x = 16910614110048622389326331015743537879782997691696669081560314808181162496550;
|
||||
uint256 constant IC3y = 115464461926218779265699564364532387878381884190664829188695820794383378419;
|
||||
|
||||
uint256 constant IC4x = 18688184865694347247300054969641975141367589743774271614757416410176028471659;
|
||||
uint256 constant IC4y = 19475466214309651477314430752520843379694799003033527395901992555787956235432;
|
||||
|
||||
|
||||
// Memory data
|
||||
uint16 constant pVk = 0;
|
||||
uint16 constant pPairing = 128;
|
||||
|
||||
uint16 constant pLastMem = 896;
|
||||
|
||||
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[4] calldata _pubSignals) public view returns (bool) {
|
||||
assembly {
|
||||
function checkField(v) {
|
||||
if iszero(lt(v, q)) {
|
||||
mstore(0, 0)
|
||||
return(0, 0x20)
|
||||
}
|
||||
}
|
||||
|
||||
// G1 function to multiply a G1 value(x,y) to value in an address
|
||||
function g1_mulAccC(pR, x, y, s) {
|
||||
let success
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, x)
|
||||
mstore(add(mIn, 32), y)
|
||||
mstore(add(mIn, 64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0, 0x20)
|
||||
}
|
||||
|
||||
mstore(add(mIn, 64), mload(pR))
|
||||
mstore(add(mIn, 96), mload(add(pR, 32)))
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0, 0x20)
|
||||
}
|
||||
}
|
||||
|
||||
function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
|
||||
let _pPairing := add(pMem, pPairing)
|
||||
let _pVk := add(pMem, pVk)
|
||||
|
||||
mstore(_pVk, IC0x)
|
||||
mstore(add(_pVk, 32), IC0y)
|
||||
|
||||
// Compute the linear combination vk_x
|
||||
|
||||
g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
|
||||
|
||||
g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
|
||||
|
||||
g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
|
||||
|
||||
g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
|
||||
|
||||
|
||||
// -A
|
||||
mstore(_pPairing, calldataload(pA))
|
||||
mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
|
||||
|
||||
// B
|
||||
mstore(add(_pPairing, 64), calldataload(pB))
|
||||
mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
|
||||
mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
|
||||
mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
|
||||
|
||||
// alpha1
|
||||
mstore(add(_pPairing, 192), alphax)
|
||||
mstore(add(_pPairing, 224), alphay)
|
||||
|
||||
// beta2
|
||||
mstore(add(_pPairing, 256), betax1)
|
||||
mstore(add(_pPairing, 288), betax2)
|
||||
mstore(add(_pPairing, 320), betay1)
|
||||
mstore(add(_pPairing, 352), betay2)
|
||||
|
||||
// vk_x
|
||||
mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
|
||||
mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
|
||||
|
||||
|
||||
// gamma2
|
||||
mstore(add(_pPairing, 448), gammax1)
|
||||
mstore(add(_pPairing, 480), gammax2)
|
||||
mstore(add(_pPairing, 512), gammay1)
|
||||
mstore(add(_pPairing, 544), gammay2)
|
||||
|
||||
// C
|
||||
mstore(add(_pPairing, 576), calldataload(pC))
|
||||
mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
|
||||
|
||||
// delta2
|
||||
mstore(add(_pPairing, 640), deltax1)
|
||||
mstore(add(_pPairing, 672), deltax2)
|
||||
mstore(add(_pPairing, 704), deltay1)
|
||||
mstore(add(_pPairing, 736), deltay2)
|
||||
|
||||
|
||||
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
|
||||
|
||||
isOk := and(success, mload(_pPairing))
|
||||
}
|
||||
|
||||
let pMem := mload(0x40)
|
||||
mstore(0x40, add(pMem, pLastMem))
|
||||
|
||||
// Validate that all evaluations ∈ F
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 0)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 32)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 64)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 96)))
|
||||
|
||||
checkField(calldataload(add(_pubSignals, 128)))
|
||||
|
||||
|
||||
// Validate all evaluations
|
||||
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
|
||||
|
||||
mstore(0, isValid)
|
||||
return(0, 0x20)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect, assert } from "chai";
|
||||
import { ethers } from "hardhat";
|
||||
// import { describe } from "mocha";
|
||||
import { mockPassportData_sha1WithRSAEncryption_65537, mockPassportData_sha256WithRSAEncryption_65537 } from "../../common/src/utils/mockPassportData";
|
||||
import { mockPassportData_sha256WithRSASSAPSS_65537, mockPassportData_sha1WithRSAEncryption_65537, mockPassportData_sha256WithRSAEncryption_65537 } from "../../common/src/utils/mockPassportData";
|
||||
import { countryCodes, PASSPORT_ATTESTATION_ID, SignatureAlgorithm } from "../../common/src/constants/constants";
|
||||
import { formatRoot } from "../../common/src/utils/utils";
|
||||
import { groth16 } from 'snarkjs'
|
||||
@@ -29,7 +29,6 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
|
||||
this.timeout(0);
|
||||
|
||||
let proof, publicSignals
|
||||
// Paths
|
||||
|
||||
const register_circuits: RegisterCircuitArtifacts = {
|
||||
sha256WithRSAEncryption_65537: {
|
||||
@@ -41,6 +40,11 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
|
||||
wasm: "../circuits/build/register_sha1WithRSAEncryption_65537_js/register_sha1WithRSAEncryption_65537.wasm",
|
||||
zkey: "../circuits/build/register_sha1WithRSAEncryption_65537_final.zkey",
|
||||
vkey: "../circuits/build/register_sha1WithRSAEncryption_65537_vkey.json"
|
||||
},
|
||||
sha256WithRSASSAPSS_65537: {
|
||||
wasm: "../circuits/build/register_sha256WithRSASSAPSS_65537_js/register_sha256WithRSASSAPSS_65537.wasm",
|
||||
zkey: "../circuits/build/register_sha256WithRSASSAPSS_65537_final.zkey",
|
||||
vkey: "../circuits/build/register_sha256WithRSASSAPSS_65537_vkey.json"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +57,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
|
||||
let owner, otherAccount, thirdAccount: Signer;
|
||||
let imt: LeanIMT;
|
||||
|
||||
let bitmap, scope, user_address, majority, user_identifier, current_date, input_disclose: any;
|
||||
let bitmap, scope, user_address, majority, input_disclose: any;
|
||||
let proof_disclose, publicSignals_disclose, proof_result_disclose, vkey_disclose, verified_disclose: any, rawCallData_disclose, parsedCallData_disclose: any[], formattedCallData_disclose: any;
|
||||
let secret: string = BigInt(0).toString();
|
||||
let attestation_id: string = PASSPORT_ATTESTATION_ID;
|
||||
@@ -78,6 +82,12 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
|
||||
mockPassportData_sha1WithRSAEncryption_65537,
|
||||
);
|
||||
|
||||
register_circuits.sha256WithRSASSAPSS_65537.inputs = generateCircuitInputsRegister(
|
||||
secret,
|
||||
attestation_id,
|
||||
mockPassportData_sha256WithRSASSAPSS_65537,
|
||||
);
|
||||
|
||||
/*** Deploy contracts ***/
|
||||
await deployContracts();
|
||||
|
||||
@@ -110,6 +120,12 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
|
||||
register_circuits.sha1WithRSAEncryption_65537.verifier = verifier_register_sha1WithRSAEncryption_65537;
|
||||
console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha1WithRSAEncryption_65537 deployed to ${verifier_register_sha1WithRSAEncryption_65537.target}`);
|
||||
|
||||
const Verifier_register_sha256WithRSASSAPSS_65537 = await ethers.getContractFactory("Verifier_register_sha256WithRSASSAPSS_65537");
|
||||
const verifier_register_sha256WithRSASSAPSS_65537 = await Verifier_register_sha256WithRSASSAPSS_65537.deploy(deployOptions);
|
||||
await verifier_register_sha256WithRSASSAPSS_65537.waitForDeployment();
|
||||
register_circuits.sha256WithRSASSAPSS_65537.verifier = verifier_register_sha256WithRSASSAPSS_65537;
|
||||
console.log('\x1b[34m%s\x1b[0m', `Verifier_register_sha256WithRSASSAPSS_65537 deployed to ${verifier_register_sha256WithRSASSAPSS_65537.target}`);
|
||||
|
||||
const Formatter = await ethers.getContractFactory("Formatter");
|
||||
formatter = await Formatter.deploy(deployOptions);
|
||||
await formatter.waitForDeployment();
|
||||
@@ -141,9 +157,9 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
|
||||
await verifier_disclose.waitForDeployment();
|
||||
console.log('\x1b[34m%s\x1b[0m', `Verifier_disclose deployed to ${verifier_disclose.target}`);
|
||||
|
||||
// for indexes, see SignatureAlgorithm object in common/src/constants/constants.ts
|
||||
await register.addSignatureAlgorithm(1, verifier_register_sha256WithRSAEncryption_65537.target);
|
||||
await register.addSignatureAlgorithm(3, verifier_register_sha1WithRSAEncryption_65537.target);
|
||||
await register.addSignatureAlgorithm(SignatureAlgorithm["sha256WithRSAEncryption_65537"], verifier_register_sha256WithRSAEncryption_65537.target);
|
||||
await register.addSignatureAlgorithm(SignatureAlgorithm["sha1WithRSAEncryption_65537"], verifier_register_sha1WithRSAEncryption_65537.target);
|
||||
await register.addSignatureAlgorithm(SignatureAlgorithm["sha256WithRSASSAPSS_65537"], verifier_register_sha256WithRSASSAPSS_65537.target);
|
||||
|
||||
const SBT = await ethers.getContractFactory("SBT");
|
||||
sbt = await SBT.deploy(
|
||||
@@ -172,7 +188,7 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
|
||||
|
||||
/*** Register flow ***/
|
||||
describe("Proof of Passport - Register flow", function () {
|
||||
const sigAlgNames = ['sha256WithRSAEncryption_65537', 'sha1WithRSAEncryption_65537']
|
||||
const sigAlgNames = ['sha256WithRSAEncryption_65537', 'sha1WithRSAEncryption_65537', 'sha256WithRSASSAPSS_65537']
|
||||
|
||||
before(async function () {
|
||||
await Promise.all(sigAlgNames.map(async (sigAlgName) => {
|
||||
@@ -216,7 +232,12 @@ describe("Proof of Passport - Contracts - Register & Disclose flow", function ()
|
||||
|
||||
it(`Verifier contract verifies a correct proof - Register - ${sigAlgName}`, async function () {
|
||||
expect(
|
||||
await sigAlgArtifacts.verifier.verifyProof(sigAlgArtifacts.parsedCallData[0], sigAlgArtifacts.parsedCallData[1], sigAlgArtifacts.parsedCallData[2], sigAlgArtifacts.parsedCallData[3])
|
||||
await sigAlgArtifacts.verifier.verifyProof(
|
||||
sigAlgArtifacts.parsedCallData[0],
|
||||
sigAlgArtifacts.parsedCallData[1],
|
||||
sigAlgArtifacts.parsedCallData[2],
|
||||
sigAlgArtifacts.parsedCallData[3]
|
||||
)
|
||||
).to.be.true;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user