Merge branch 'feat/circom-dl' of github.com:openpassport-org/openpassport into feat/circom-dl

This commit is contained in:
seshanthS
2024-12-15 18:53:01 +05:30
23 changed files with 221 additions and 159 deletions

View File

@@ -1,6 +1,6 @@
pragma circom 2.1.9;
include "../utils/other/bytes.circom";
include "../utils/circomlib/utils/bytes.circom";
include "../utils/passport/date/isOlderThan.circom";
template DISCLOSE() {

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.5;
include "../utils/circomlib/bitify/comparators.circom";
include "../utils/other/bytes.circom";
include "../utils/circomlib/utils/bytes.circom";
template ProveCountryIsNotInList(forbiddenCountriesListLength) {
signal input dg1[93];

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.9;
include "../utils/other/bytes.circom";
include "../utils/other/binary-merkle-root/binary-merkle-root.circom";
include "../utils/circomlib/utils/bytes.circom";
include "../utils/circomlib/merkle-trees/binary-merkle-root.circom";
include "../utils/passport/computeCommitment.circom";
template VERIFY_COMMITMENT( nLevels) {

View File

@@ -4,12 +4,11 @@ include "../utils/circomlib/bitify/bitify.circom";
include "../utils/circomlib/hasher/hash.circom";
include "../utils/circomlib/bitify/comparators.circom";
include "../utils/circomlib/hasher/hash.circom";
include "../utils/other/binary-merkle-root/binary-merkle-root.circom";
include "../utils/circomlib/merkle-trees/binary-merkle-root.circom";
include "../utils/passport/customHashers.circom";
include "../utils/other/bytes.circom";
include "../utils/passport/signatureAlgorithm.circom";
include "../utils/passport/signatureVerifier.circom";
include "../utils/other/bytes.circom";
include "../utils/circomlib/utils/bytes.circom";
template OPENPASSPORT_DSC(signatureAlgorithm, n_dsc, k_dsc, n_csca, k_csca, max_cert_bytes, dscPubkeyBytesLength, nLevels) {

View File

@@ -8,7 +8,7 @@ include "../utils/passport/date/isValid.circom";
include "../utils/passport/passportVerifier.circom";
include "../disclose/disclose.circom";
include "../disclose/proveCountryIsNotInList.circom";
include "../ofac/ofac_name.circom";
include "../utils/passport/ofac/ofac_name.circom";
template OPENPASSPORT_PROVE(signatureAlgorithm, n, k, MAX_ECONTENT_PADDED_LEN, MAX_SIGNED_ATTR_PADDED_LEN, FORBIDDEN_COUNTRIES_LIST_LENGTH) {
var kLengthFactor = getKLengthFactor(signatureAlgorithm);

View File

@@ -1,3 +1,3 @@
pragma circom 2.1.9;
include "../../ofac/ofac_name_dob.circom";
include "../../utils/passport/ofac/ofac_name_dob.circom";
component main { public [ smt_root ] } = OFAC_NAME_DOB();

View File

@@ -1,3 +1,3 @@
pragma circom 2.1.9;
include "../../ofac/ofac_name.circom";
include "../../utils/passport/ofac/ofac_name.circom";
component main { public [ smt_root ] } = OFAC_NAME();

View File

@@ -1,3 +1,3 @@
pragma circom 2.1.9;
include "../../ofac/ofac_passport_number.circom";
include "../../utils/passport/ofac/ofac_passport_number.circom";
component main { public [ smt_root ] } = OFAC_PASSPORT_NUMBER();

View File

@@ -1,7 +1,8 @@
pragma circom 2.1.5;
pragma circom 2.1.6;
include "../../circomlib/hasher/hash.circom";
include "../../circomlib/bitify/comparators.circom";
include "../../circomlib/mux/mux1.circom";
// This circuit is designed to calculate the root of a binary Merkle
// tree given a leaf, its depth, and the necessary sibling
@@ -42,32 +43,3 @@ template BinaryMerkleRoot(MAX_DEPTH) {
out <== root + isDepth * nodes[MAX_DEPTH];
}
template MultiMux1(n) {
signal input c[n][2]; // Constants
signal input s; // Selector
signal output out[n];
for (var i=0; i<n; i++) {
out[i] <== (c[i][1] - c[i][0])*s + c[i][0];
}
}
template Mux1() {
var i;
signal input c[2]; // Constants
signal input s; // Selector
signal output out;
component mux = MultiMux1(1);
for (i=0; i<2; i++) {
mux.c[0][i] <== c[i];
}
s ==> mux.s;
mux.out[0] ==> out;
}

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.9;
include "../circomlib/bitify/comparators.circom";
include "../circomlib/bitify/bitify.circom";
include "../bitify/comparators.circom";
include "../bitify/bitify.circom";
// Computes the first n common bits of the hashes
template CommonBitsLengthFromEnd() {

View File

@@ -1,10 +1,10 @@
pragma circom 2.1.9;
include "../circomlib/hasher/hash.circom";
include "../circomlib/bitify/comparators.circom";
include "../circomlib/bitify/bitify.circom";
include "./array.circom";
include "./binary-merkle-root/binary-merkle-root.circom";
include "../hasher/hash.circom";
include "../bitify/comparators.circom";
include "../bitify/bitify.circom";
include "../utils/array.circom";
include "binary-merkle-root.circom";
include "getCommonLength.circom";
template SMTVerify(nLength) {

View File

@@ -0,0 +1,48 @@
/*
Copyright 2018 0KIMS association.
This file is part of circom (Zero Knowledge Circuit Compiler).
circom 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.
circom 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 circom. If not, see <https://www.gnu.org/licenses/>.
*/
pragma circom 2.1.6;
template MultiMux1(n) {
signal input c[n][2]; // Constants
signal input s; // Selector
signal output out[n];
for (var i=0; i<n; i++) {
out[i] <== (c[i][1] - c[i][0])*s + c[i][0];
}
}
template Mux1() {
var i;
signal input c[2]; // Constants
signal input s; // Selector
signal output out;
component mux = MultiMux1(1);
for (i=0; i<2; i++) {
mux.c[0][i] <== c[i];
}
s ==> mux.s;
mux.out[0] ==> out;
}

View File

@@ -1,9 +1,10 @@
pragma circom 2.1.9;
pragma circom 2.1.6;
include "../circomlib/bitify/comparators.circom";
include "../circomlib/bitify/bitify.circom";
include "../bitify/bitify.circom";
include "../bitify/comparators.circom";
include "./functions.circom";
/// @title ItemAtIndex
/// @notice Select item at given index from the input array
/// @notice This template that the index is valid
@@ -161,3 +162,93 @@ template AssertZeroPadding(maxArrayLen) {
lessThans[i].out * in[i] === 0;
}
}
/// @title Slice
/// @notice Extract a fixed portion of an array
/// @dev Unlike SelectSubArray, Slice uses compile-time known indices and doesn't pad the output
/// @dev Slice is more efficient for fixed ranges, while SelectSubArray offers runtime flexibility
/// @param n The length of the input array
/// @param start The starting index of the slice (inclusive)
/// @param end The ending index of the slice (exclusive)
/// @input in The input array of length n
/// @output out The sliced array of length (end - start)
template Slice(n, start, end) {
assert(n >= end);
assert(start >= 0);
assert(end >= start);
signal input in[n];
signal output out[end - start];
for (var i = start; i < end; i++) {
out[i - start] <== in[i];
}
}
/// @title CheckSubstringMatch
/// @notice Check if a substring matches the input array
/// @param maxSubstringLen The maximum length of the substring
/// @input input The portion of the input array to check
/// @input substring The substring pattern to match
/// @output isMatch 1 if the substring matches, 0 otherwise
template CheckSubstringMatch(maxSubstringLen) {
signal input in[maxSubstringLen];
signal input substring[maxSubstringLen];
signal output isMatch;
// Ensure the first element of the pattern is non-zero
signal firstElementNonZero;
firstElementNonZero <== IsZero()(substring[0]);
firstElementNonZero === 0;
signal matchAccumulator[maxSubstringLen + 1];
signal difference[maxSubstringLen];
signal isZeroDifference[maxSubstringLen];
matchAccumulator[0] <== 1;
for (var i = 0; i < maxSubstringLen; i++) {
difference[i] <== (in[i] - substring[i]) * substring[i];
isZeroDifference[i] <== IsZero()(difference[i]);
matchAccumulator[i + 1] <== matchAccumulator[i] * isZeroDifference[i];
}
isMatch <== matchAccumulator[maxSubstringLen];
}
/// @title CountSubstringOccurrences
/// @notice Count the number of times a substring occurs in the input array
/// @param maxLen The maximum length of the input array
/// @param maxSubstringLen The maximum length of the substring
/// @input in The input array to search in
/// @input substring The substring to search for
/// @output count The number of occurrences of the substring in the input
template CountSubstringOccurrences(maxLen, maxSubstringLen) {
assert(maxLen >= maxSubstringLen);
signal input in[maxLen];
signal input substring[maxSubstringLen];
signal output count;
// Check for matches at each possible starting position
component matches[maxLen];
for (var i = 0; i < maxLen; i++) {
matches[i] = CheckSubstringMatch(maxSubstringLen);
for (var j = 0; j < maxSubstringLen; j++) {
if (i + j < maxLen) {
matches[i].in[j] <== in[i + j];
} else {
matches[i].in[j] <== 0;
}
}
matches[i].substring <== substring;
}
// Sum up all matches to get the total count
component summer = CalculateTotal(maxLen);
for (var i = 0; i < maxLen; i++) {
summer.nums[i] <== matches[i].isMatch;
}
count <== summer.sum;
}

View File

@@ -1,10 +1,11 @@
pragma circom 2.1.9;
pragma circom 2.1.6;
include "../circomlib/bitify/bitify.circom";
include "../circomlib/bitify/comparators.circom";
include "../bitify/bitify.circom";
include "../bitify/comparators.circom";
include "./array.circom";
include "./functions.circom";
include "./constants.circom";
include "./functions.circom";
function computeIntChunkLength(byteLength) {
var packSize = MAX_BYTES_IN_FIELD();
@@ -111,77 +112,8 @@ template DigitBytesToInt(n) {
out <== sums[n];
}
/// NOTE: this circuit is unaudited and should not be used in production
/// @title SplitBytesToWords
/// @notice split an array of bytes into an array of words
/// @notice useful for casting a message or modulus before RSA verification
/// @param l: number of bytes in the input array
/// @param n: number of bits in a word
/// @param k: number of words
/// @input in: array of bytes
/// @output out: array of words
template SplitSignalsToWords (t,l,n,k) {
assert(n*k >= t*l);
signal input in[l];
signal output out[k];
component num2bits[l];
for (var i = 0 ; i < l ; i++){
num2bits[i] = Num2Bits(t);
num2bits[i].in <== in[i];
}
for (var i = 0 ; i < t ; i ++){
}
component bits2num[k];
for (var i = 0 ; i < k ; i++){
bits2num[i] = Bits2Num(n);
for(var j = 0 ; j < n ; j++){
if(i*n + j >= l * t){
bits2num[i].in[j] <== 0;
}
else{
bits2num[i].in[j] <== num2bits[ (( i * n + j) \ t) ].out[ ((i * n + j) % t)];
}
}
}
for( var i = 0 ; i< k ; i++){
out[i] <== bits2num[i].out;
}
}
template SplitSignalsToWordsUnsafe (t,l,n,k) {
signal input in[l];
signal output out[k];
component num2bits[l];
for (var i = 0 ; i < l ; i++){
num2bits[i] = Num2Bits(t);
num2bits[i].in <== in[i];
}
for (var i = 0 ; i < t ; i ++){
}
component bits2num[k];
for (var i = 0 ; i < k ; i++){
bits2num[i] = Bits2Num(n);
for(var j = 0 ; j < n ; j++){
if(i*n + j >= l * t){
bits2num[i].in[j] <== 0;
}
else{
bits2num[i].in[j] <== num2bits[ (( i * n + j) \ t) ].out[ ((i * n + j) % t)];
}
}
}
for( var i = 0 ; i< k ; i++){
out[i] <== bits2num[i].out;
}
}
/// NOTE: this circuit is unaudited and should not be used in production
// NOTE: this circuit is unaudited and should not be used in production
/// @title SplitBytesToWords
/// @notice split an array of bytes into an array of words
/// @notice useful for casting a message or modulus before RSA verification
@@ -193,6 +125,7 @@ template SplitSignalsToWordsUnsafe (t,l,n,k) {
template SplitBytesToWords (l,n,k) {
signal input in[l];
signal output out[k];
component num2bits[l];
for (var i = 0 ; i < l ; i++){
num2bits[i] = Num2Bits(8);
@@ -213,4 +146,40 @@ template SplitBytesToWords (l,n,k) {
for( var i = 0 ; i< k ; i++){
out[i] <== bits2num[i].out;
}
}
// Asserts that a given input is binary.
//
// Inputs:
// - in: an input signal, expected to be 0 or 1.
template AssertBit() {
signal input in;
in * (in - 1) === 0;
}
// The ByteMask template masks an input array using a binary mask array.
// Each element in the input array is multiplied by the corresponding element in the mask array.
// The mask array is validated to ensure all elements are binary (0 or 1).
//
// Parameters:
// - maxLength: The maximum length of the input and mask arrays.
//
// Inputs:
// - body: An array of signals representing the body to be masked.
// - mask: An array of signals representing the binary mask.
//
// Outputs:
// - out: An array of signals representing the masked input.
template ByteMask(maxLength) {
signal input in[maxLength];
signal input mask[maxLength];
signal output out[maxLength];
component bit_check[maxLength];
for (var i = 0; i < maxLength; i++) {
bit_check[i] = AssertBit();
bit_check[i].in <== mask[i];
out[i] <== in[i] * mask[i];
}
}

View File

@@ -1,4 +1,4 @@
pragma circom 2.1.9;
pragma circom 2.1.6;
function EMAIL_ADDR_MAX_BYTES() {
@@ -12,4 +12,4 @@ function DOMAIN_MAX_BYTES() {
// Field support maximum of ~253 bit
function MAX_BYTES_IN_FIELD() {
return 31;
}
}

View File

@@ -1,4 +1,4 @@
pragma circom 2.1.9;
pragma circom 2.1.6;
/// @function log2Ceil
/// @notice Calculate log2 of a number and round it up
@@ -14,4 +14,4 @@ function log2Ceil(a) {
}
return r;
}
}

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.9;
include "../circomlib/hasher/hash.circom";
include "../other/bytes.circom";
include "../circomlib/utils/bytes.circom";
include "./customHashers.circom";
template ComputeCommitment() {

View File

@@ -1,6 +0,0 @@
pragma circom 2.1.9;
template FormatECDSAInputs(signatureAlgorithm, k) {
}

View File

@@ -1,10 +1,7 @@
pragma circom 2.1.9;
include "../utils/circomlib/hasher/hash.circom";
include "../utils/circomlib/bitify/comparators.circom";
include "../utils/other/binary-merkle-root/binary-merkle-root.circom";
include "../utils/other/getCommonLength.circom";
include "../utils/other/smt.circom";
include "../../circomlib/hasher/hash.circom";
include "../../circomlib/merkle-trees/smt.circom";
template OFAC_NAME() {

View File

@@ -1,11 +1,7 @@
pragma circom 2.1.9;
include "../utils/circomlib/hasher/hash.circom";
include "../utils/circomlib/bitify/comparators.circom";
include "../utils/circomlib/bitify/bitify.circom";
include "../utils/other/binary-merkle-root/binary-merkle-root.circom";
include "../utils/other/getCommonLength.circom";
include "../utils/other/smt.circom";
include "../../circomlib/hasher/hash.circom";
include "../../circomlib/merkle-trees/smt.circom";
template OFAC_NAME_DOB() {
@@ -19,7 +15,7 @@ template OFAC_NAME_DOB() {
for (var j = 0; j < 3; j++) {
poseidon_hasher[j] = PoseidonHash(13);
for (var i = 0; i < 13; i++) {
poseidon_hasher[j].inputs[i] <== dg1[10 + 13 * j + i];
poseidon_hasher[j].in[i] <== dg1[10 + 13 * j + i];
}
poseidon_hasher[j].dummy <== 0;
}
@@ -28,7 +24,7 @@ template OFAC_NAME_DOB() {
// Dob hash
component pos_dob = PoseidonHash(6);
for(var i = 0; i < 6; i++) {
pos_dob.inputs[i] <== dg1[62 + i];
pos_dob.in[i] <== dg1[62 + i];
}
pos_dob.dummy <== 0;

View File

@@ -1,12 +1,7 @@
pragma circom 2.1.9;
include "circom-dl/circuits/hasher/hash.circom";
include "circom-dl/circuits/bitify/comparators.circom";
include "circom-dl/circuits/bitify/bitify.circom";
include "../utils/other/array.circom";
include "binary-merkle-root.circom";
include "../utils/other/getCommonLength.circom";
include "../utils/other/smt.circom";
include "../../circomlib/hasher/hash.circom";
include "../../circomlib/merkle-trees/smt.circom";
template OFAC_PASSPORT_NUMBER() {
@@ -19,7 +14,7 @@ template OFAC_PASSPORT_NUMBER() {
component poseidon_hasher = PoseidonHash(9);
for (var i = 0; i < 9; i++) {
poseidon_hasher.inputs[i] <== dg1[49 + i];
poseidon_hasher.in[i] <== dg1[49 + i];
}
poseidon_hasher.dummy <== 0;
signal output ofacCheckResult <== SMTVerify(256)(poseidon_hasher.out, smt_leaf_value, smt_root, smt_siblings, 0);

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.9;
include "../other/array.circom";
include "../other/bytes.circom";
include "../circomlib/utils/array.circom";
include "../circomlib/utils/bytes.circom";
// include "../shaBytes/shaBytesStatic.circom";
include "../shaBytes/shaBytesDynamic.circom";
include "../circomlib/hasher/hash.circom";

View File

@@ -88,6 +88,7 @@ describe('OFAC - Passport number match', function () {
const ofacCheckResult = (await circuit.getOutput(w, ['ofacCheckResult'])).ofacCheckResult;
expect(ofacCheckResult).to.equal('0');
});
});
// Level 2: NameDob match in OfacList