Skip to content

Commit

Permalink
Added latest cicuit but test failing
Browse files Browse the repository at this point in the history
  • Loading branch information
Meyanis95 committed Jan 30, 2024
1 parent 0864513 commit f97fcb3
Show file tree
Hide file tree
Showing 16 changed files with 485 additions and 162 deletions.
2 changes: 1 addition & 1 deletion mopro-core/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ fn main() -> Result<()> {
// let dir = "examples/circom/keccak256";
// let circuit = "keccak256_256_test";
let dir = "examples/circom/anonAadhaar";
let circuit = "qr_verify";
let circuit = "aadhaar-verifier";

// XXX: Use RSA
// let dir = "examples/circom/rsa";
Expand Down
2 changes: 1 addition & 1 deletion mopro-core/examples/circom/anonAadhaar/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Notes

This version of the AA is the one with just Sha256 + RSA and no nullifiers with 917,344 contraints.
This is the latest version of the AA circuits with in total 1,767,153 contraints.
111 changes: 111 additions & 0 deletions mopro-core/examples/circom/anonAadhaar/aadhaar-verifier.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
pragma circom 2.1.6;

include "./helpers/rsa.circom";
include "./helpers/sha.circom";
include "./helpers/timestamp.circom";
include "./extractor.circom";

// Circuit to verify Aadhaar signature
// n: RSA pubic key size per chunk
// k: Number of chunks the RSA public key is split into
// maxDataLength: Maximum length of the data
template AadhaarVerifier(n, k, maxDataLength) {
signal input aadhaarData[maxDataLength]; // Aadhaar data padded (the data that is SHA hashed and signed)
signal input aadhaarDataLength; // length of the padded data
signal input signature[k]; // RSA signature
signal input pubKey[k]; // RSA public key (of the government)
signal input signalHash;

signal output identityNullifier; // Hash of last 4 digits of Aadhaar number, name, DOB, gender and pin code
signal output userNullifier; // Hash of last 4 digits of Aadhaar number and photo
signal output timestamp; // Timestamp of when the data was signed - extracted and converted to Unix timestamp
signal output pubkeyHash; // Poseidon hash of the RSA public key


component shaHasher = Sha256Bytes(maxDataLength);
shaHasher.in_padded <== aadhaarData;
shaHasher.in_len_padded_bytes <== aadhaarDataLength;
signal sha[256];
sha <== shaHasher.out;


component rsa = RSAVerify65537(n, k);
var rsaMsgLength = (256 + n) \ n;
component rsaBaseMsg[rsaMsgLength];
for (var i = 0; i < rsaMsgLength; i++) {
rsaBaseMsg[i] = Bits2Num(n);
}
for (var i = 0; i < 256; i++) {
rsaBaseMsg[i \ n].in[i % n] <== sha[255 - i];
}
for (var i = 256; i < n * rsaMsgLength; i++) {
rsaBaseMsg[i \ n].in[i % n] <== 0;
}

for (var i = 0; i < rsaMsgLength; i++) {
rsa.base_message[i] <== rsaBaseMsg[i].out;
}
for (var i = rsaMsgLength; i < k; i++) {
rsa.base_message[i] <== 0;
}

for (var i = 0; i < k; i++) {
rsa.modulus[i] <== pubKey[i];
rsa.signature[i] <== signature[i];
}


component extractor = Extractor(maxDataLength);
extractor.dataLen <== aadhaarDataLength;
extractor.data <== aadhaarData;

signal last4Digits[4] <== extractor.last4Digits;
signal photoHash <== extractor.photoHash;
signal basicIdentityHash <== extractor.basicIdentityHash;

component poseidonHasher[2];
poseidonHasher[0] = Poseidon(5);
poseidonHasher[0].inputs <== [last4Digits[0], last4Digits[1], last4Digits[2], last4Digits[3], photoHash];

poseidonHasher[1] = Poseidon(5);
poseidonHasher[1].inputs <== [last4Digits[0], last4Digits[1], last4Digits[2], last4Digits[3], basicIdentityHash];

userNullifier <== poseidonHasher[0].out;
identityNullifier <== poseidonHasher[1].out;


// Output the timestamp rounded to nearest hour
component dateToUnixTime = DateStringToTimestamp(2030, 1, 0, 0);
for (var i = 0; i < 14; i++) {
dateToUnixTime.in[i] <== aadhaarData[i + 6];
}
timestamp <== dateToUnixTime.out - 19800; // 19800 is the offset for IST


// Calculate Poseidon hash of the public key.
// Poseidon component can take only 16 inputs, so we convert k chunks to k/2 chunks.
// We are assuming k is > 16 and <= 32 (i.e we merge two consecutive item in array to bring down the size)
var poseidonInputSize = k \ 2;
if (k % 2 == 1) {
poseidonInputSize++;
}
assert(poseidonInputSize <= 16);
signal pubkeyHasherInput[poseidonInputSize];
for (var i = 0; i < poseidonInputSize; i++) {
if (i == poseidonInputSize - 1 && poseidonInputSize % 2 == 1) {
pubkeyHasherInput[i] <== pubKey[i * 2];
} else {
pubkeyHasherInput[i] <== pubKey[i * 2] + (1 << n) * pubKey[i * 2 + 1];
}
}
component pubkeyHasher = Poseidon(poseidonInputSize);
pubkeyHasher.inputs <== pubkeyHasherInput;
pubkeyHash <== pubkeyHasher.out;


signal signalHashSquare;
signalHashSquare <== signalHash * signalHash;
}


component main { public [signalHash] } = AadhaarVerifier(64, 32, 512 * 3);
145 changes: 145 additions & 0 deletions mopro-core/examples/circom/anonAadhaar/extractor.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
pragma circom 2.1.6;

include "./node_modules/circomlib/circuits/comparators.circom";
include "./node_modules/circomlib/circuits/poseidon.circom";


/**
return 1 if left <= element <= right
else return 0;
**/
template InRange(n) {
signal input left;
signal input right;
signal input element;

signal output out;

component l = GreaterEqThan(n);
component r = GreaterEqThan(n);

l.in[0] <== element;
l.in[1] <== left;

r.in[0] <== right;
r.in[1] <== element;

out <== l.out * r.out;
}


template PhotoPositionComputation(MAX_NUMBER_BYTES) {
signal input dataLen;
signal input data[MAX_NUMBER_BYTES];
signal input filter[MAX_NUMBER_BYTES];

signal output photoPosition[2];

signal numberElementLessThan16[MAX_NUMBER_BYTES];
numberElementLessThan16[0] <== 0;
signal lessThan[MAX_NUMBER_BYTES - 1];
for (var i = 1; i < MAX_NUMBER_BYTES; i++) {
lessThan[i - 1] <== LessThan(8)([filter[i], 16]);
numberElementLessThan16[i] <== numberElementLessThan16[i - 1] + lessThan[i -1 ];
}

signal totalBasicFieldsSize <== numberElementLessThan16[MAX_NUMBER_BYTES - 1];

photoPosition[0] <== totalBasicFieldsSize + 1;

signal index[MAX_NUMBER_BYTES];
signal equals[MAX_NUMBER_BYTES];
signal acctualLen[MAX_NUMBER_BYTES];
signal tmp[MAX_NUMBER_BYTES - 1];

index[0] <== 0;
acctualLen[0] <== 0;
equals[0] <== 0;

for (var i = 1; i < MAX_NUMBER_BYTES; i++) {
index[i] <== index[i - 1] + 1;
equals[i] <== IsEqual()([index[i], dataLen - 1]);
tmp[i - 1] <== data[i - 1] * 256 + data[i];
acctualLen[i] <== (tmp[i - 1] - acctualLen[i - 1]) * equals[i] + acctualLen[i - 1];
}

photoPosition[1] <== acctualLen[MAX_NUMBER_BYTES - 1]/8 - 65;

}


template Extractor(MAX_NUMBER_BYTES) {
signal input data[MAX_NUMBER_BYTES];
signal input dataLen;

signal output photoHash;
signal output basicIdentityHash;
signal output last4Digits[4];

signal sData[MAX_NUMBER_BYTES];

component isData255[MAX_NUMBER_BYTES - 1];

sData[0] <== 0;

for (var i = 0; i < MAX_NUMBER_BYTES - 1; i++) {
isData255[i] = IsEqual();
isData255[i].in[0] <== 255;
isData255[i].in[1] <== data[i + 1];
sData[i + 1] <== sData[i] + isData255[i].out;
}


component photoPositionComputation = PhotoPositionComputation(MAX_NUMBER_BYTES);
photoPositionComputation.dataLen <== dataLen;
photoPositionComputation.filter <== sData;
photoPositionComputation.data <== data;

signal photoPosition[2] <== photoPositionComputation.photoPosition;

signal photoFlag[MAX_NUMBER_BYTES];
for (var i = 0; i < MAX_NUMBER_BYTES; i++) {
photoFlag[i] <== InRange(12)(photoPosition[0], photoPosition[1], i);
}

photoHash <== HashChain(MAX_NUMBER_BYTES)(photoFlag, data);

signal basicIdentityFlag[MAX_NUMBER_BYTES];
signal pincodeFlag[MAX_NUMBER_BYTES];
signal identityFlag[MAX_NUMBER_BYTES];

for (var i = 0; i < MAX_NUMBER_BYTES; i++) {
basicIdentityFlag[i] <== InRange(12)(2, 4, sData[i]);
pincodeFlag[i] <== IsEqual()([10, sData[i]]);
identityFlag[i] <== basicIdentityFlag[i] + pincodeFlag[i] - basicIdentityFlag[i] * pincodeFlag[i];
}

basicIdentityHash <== HashChain(MAX_NUMBER_BYTES)(identityFlag, data);

// extract last fordigit;
for (var i = 0; i < 4; i++) {
last4Digits[i] <== data[i + 2];
}
}

template HashChain(MAX_NUMBER_BYTES) {
signal input flag[MAX_NUMBER_BYTES];
signal input data[MAX_NUMBER_BYTES];

signal output hash;

signal hashChain[MAX_NUMBER_BYTES];

component hasher[MAX_NUMBER_BYTES - 1];
// We always skip the first element, since email_or_phone unnessanary when compute nullifier;
hashChain[0] <== 0;

for (var i = 0; i < MAX_NUMBER_BYTES - 1; i++) {
hasher[i] = Poseidon(2);
hasher[i].inputs[0] <== hashChain[i];
hasher[i].inputs[1] <== data[i + 1];
hashChain[i + 1] <== (hasher[i].out - hashChain[i]) * flag[i + 1] + hashChain[i];
}

hash <== hashChain[MAX_NUMBER_BYTES - 1];
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pragma circom 2.1.5;

include "./node_modules/circomlib/circuits/comparators.circom";
include "./node_modules/circomlib/circuits/bitify.circom";
include "./node_modules/circomlib/circuits/gates.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/circomlib/circuits/gates.circom";

include "bigint_func.circom";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pragma circom 2.1.5;

include "./node_modules/circomlib/circuits/bitify.circom";
include "./node_modules/circomlib/circuits/comparators.circom";
include "./node_modules/circomlib/circuits/sign.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/circomlib/circuits/sign.circom";
include "./bigint.circom";
include "./bigint_func.circom";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma circom 2.1.5;

include "./node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
include "./sha256general.circom";
include "./sha256partial.circom";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pragma circom 2.1.5;

include "./node_modules/circomlib/circuits/sha256/constants.circom";
include "./node_modules/circomlib/circuits/sha256/sha256compression.circom";
include "./node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/circomlib/circuits/sha256/constants.circom";
include "../node_modules/circomlib/circuits/sha256/sha256compression.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
include "./utils.circom";

// A modified version of the SHA256 circuit that allows specified length messages up to a max to all work via array indexing on the SHA256 compression circuit.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pragma circom 2.1.5;

include "./node_modules/circomlib/circuits/sha256/constants.circom";
include "./node_modules/circomlib/circuits/sha256/sha256compression.circom";
include "./node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/circomlib/circuits/sha256/constants.circom";
include "../node_modules/circomlib/circuits/sha256/sha256compression.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
include "./utils.circom";

// Completing the sha256 hash given a pre-computed state and additional data
Expand Down
Loading

0 comments on commit f97fcb3

Please sign in to comment.