fix: working tests

This commit is contained in:
ayman
2025-01-07 16:50:52 +05:30
parent 6a8cd77740
commit 17240f5d9f
36 changed files with 422 additions and 283 deletions

View File

@@ -1,5 +0,0 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(24, 64, 4, 512, 256, 20);

View File

@@ -1,5 +0,0 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(22, 64, 6, 512, 256, 20);

View File

@@ -1,5 +0,0 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(9, 64, 6, 512, 256, 20);

View File

@@ -1,5 +0,0 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(25, 64, 4, 640, 256, 20);

View File

@@ -1,5 +0,0 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(26, 64, 6, 640, 256, 20);

View File

@@ -2,4 +2,4 @@ pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(28, 32, 7, 384, 192, 20);
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(160, 160, 27, 32, 7, 320, 128, 20);

View File

@@ -2,4 +2,4 @@ pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(21, 64, 4, 384, 192, 20);
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(256, 224, 30, 32, 7, 448, 128, 20);

View File

@@ -2,4 +2,4 @@ pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(23, 64, 6, 384, 192, 20);
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(256, 256, 28, 32, 7, 448, 128, 20);

View File

@@ -0,0 +1,5 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(256, 256, 21, 64, 4, 448, 128, 20);

View File

@@ -0,0 +1,5 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(256, 256, 23, 64, 6, 448, 128, 20);

View File

@@ -0,0 +1,5 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(384, 384, 24, 64, 4, 640, 256, 20);

View File

@@ -0,0 +1,5 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(384, 384, 22, 64, 6, 640, 256, 20);

View File

@@ -2,4 +2,4 @@ pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(27, 32, 7, 320, 192, 20);
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(384, 384, 9, 64, 6, 640, 256, 20);

View File

@@ -0,0 +1,5 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(512, 512, 25, 64, 4, 768, 256, 20);

View File

@@ -0,0 +1,5 @@
pragma circom 2.1.9;
include "../openpassport_prove.circom";
component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(512, 512, 26, 64, 6, 768, 256, 20);

View File

@@ -331,7 +331,7 @@ function prod_dl(n, k, a, b) {
// k * n <= 500
// p is a prime
// computes a^e mod p
function mod_exp(n, k, a, p, e) {
function mod_exp_dl(n, k, a, p, e) {
var eBits[512];
for (var i = 0; i < k; i++) {
for (var j = 0; j < n; j++) {

View File

@@ -49,7 +49,6 @@ include "./get.circom";
// λ = (3 * x ** 2 + a) / (2 * y)
// y3 = λ * (x - x3) - y
template TangentCheck(CHUNK_SIZE, CHUNK_NUMBER, A, B, P){
assert(CHUNK_SIZE == 64);
signal input in1[2][CHUNK_NUMBER];
@@ -728,7 +727,6 @@ template EllipticCurvePipingerMult(CHUNK_SIZE, CHUNK_NUMBER, A, B, P, WINDOW_SIZ
if (i != 0){
for (var j = 0; j < WINDOW_SIZE; j++){
doublers[i + j - WINDOW_SIZE] = EllipticCurveDouble(CHUNK_SIZE, CHUNK_NUMBER, A, B, P);
doublers[i + j - WINDOW_SIZE].dummy <== dummy;
if (j == 0){
for (var axis_idx = 0; axis_idx < 2; axis_idx++){

View File

@@ -3,22 +3,29 @@ pragma circom 2.0.0;
include "../sha2Common.circom";
include "../sha256/sha256Schedule.circom";
include "../sha256/sha256Rounds.circom";
include "@zk-email/circuits/utils/array.circom";
include "sha224InitialValue.circom";
template Sha224HashChunks(BLOCK_NUM) {
signal input in[BLOCK_NUM * 512];
template Sha224HashChunks(MAX_BLOCKS) {
signal input in[MAX_BLOCKS * 512];
signal input paddedInLength;
signal output out[224];
signal inBlockIndex;
inBlockIndex <-- (paddedInLength >> 9);
paddedInLength === inBlockIndex * 512;
signal states[BLOCK_NUM + 1][8][32];
signal states[MAX_BLOCKS + 1][8][32];
component iv = Sha224InitialValue();
iv.out ==> states[0];
component sch[BLOCK_NUM];
component rds[BLOCK_NUM];
component sch[MAX_BLOCKS];
component rds[MAX_BLOCKS];
for (var m = 0; m < BLOCK_NUM; m++) {
for (var m = 0; m < MAX_BLOCKS; m++) {
sch[m] = Sha2_224_256Shedule();
rds[m] = Sha2_224_256Rounds(64);
@@ -35,9 +42,15 @@ template Sha224HashChunks(BLOCK_NUM) {
rds[m].outHash ==> states[m + 1];
}
component arraySelectors[224];
for (var j = 0; j < 7; j++) {
for (var i = 0; i < 32; i++){
out[j * 32 + i] <== states[BLOCK_NUM][j][31 - i];
arraySelectors[j * 32 + i] = ItemAtIndex(MAX_BLOCKS + 1);
for (var k = 0; k <= MAX_BLOCKS; k++) {
arraySelectors[j * 32 + i].in[k] <== states[k][j][31 - i];
}
arraySelectors[j * 32 + i].index <== inBlockIndex;
out[j * 32 + i] <== arraySelectors[j * 32 + i].out;
}
}
}

View File

@@ -3,14 +3,12 @@ pragma circom 2.0.0;
include "../sha2Common.circom";
include "../sha512/sha512Schedule.circom";
include "../sha512/sha512Rounds.circom";
include "../../../utils/array.circom";
include "@zk-email/circuits/utils/array.circom";
include "sha384InitialValue.circom";
template Sha384HashChunks(MAX_BLOCKS) {
signal input in[MAX_BLOCKS * 1024];
signal input paddedInLength;
signal input dummy;
dummy * dummy === 0;
signal output out[384];

View File

@@ -3,7 +3,7 @@ pragma circom 2.0.0;
include "../sha2Common.circom";
include "sha512InitialValue.circom";
include "sha512Schedule.circom";
include "../../../utils/array.circom";
include "@zk-email/circuits/utils/array.circom";
include "sha512Rounds.circom";
template Sha512HashChunks(MAX_BLOCKS) {

View File

@@ -0,0 +1,27 @@
pragma circom 2.1.9;
include "circomlib/circuits/bitify.circom";
include "circomlib/circuits/comparators.circom";
include "../../sha2/sha224/sha224HashChunks.circom";
template Sha224Bytes(maxByteLength) {
signal input paddedIn[maxByteLength];
signal input paddedInLength;
signal output out[224];
component sha = Sha224HashChunks((maxByteLength * 8) \ 512);
sha.paddedInLength <== paddedInLength * 8;
component bytes[maxByteLength];
for (var i = 0; i < maxByteLength; i++) {
bytes[i] = Num2Bits(8);
bytes[i].in <== paddedIn[i];
for (var j = 0; j < 8; j++) {
sha.in[i*8+j] <== bytes[i].out[7-j];
}
}
for (var i = 0; i < 224; i++) {
out[i] <== sha.out[i];
}
}

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.9;
include "../../../bitify/bitify.circom";
include "../../../bitify/comparators.circom";
include "circomlib/circuits/bitify.circom";
include "circomlib/circuits/comparators.circom";
include "../../sha2/sha384/sha384HashChunks.circom";
template Sha384Bytes(maxByteLength) {
@@ -20,7 +20,6 @@ template Sha384Bytes(maxByteLength) {
sha.in[i*8+j] <== bytes[i].out[7-j];
}
}
sha.dummy <== 0;
for (var i = 0; i < 384; i++) {
out[i] <== sha.out[i];

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.9;
include "../../../bitify/bitify.circom";
include "../../../bitify/comparators.circom";
include "circomlib/circuits/bitify.circom";
include "circomlib/circuits/comparators.circom";
include "../../sha2/sha512/sha512HashChunks.circom";
template Sha512Bytes(maxByteLength) {

View File

@@ -1,7 +1,8 @@
pragma circom 2.1.9;
include "./dynamic/sha1Bytes.circom";
include "./dynamic/sha256Bytes.circom";
include "./dynamic/sha224Bytes.circom";
include "@zk-email/circuits/lib/sha.circom";
include "./dynamic/sha384Bytes.circom";
include "./dynamic/sha512Bytes.circom";
@@ -20,6 +21,9 @@ template ShaBytesDynamic(hashLen, max_num_bits) {
if (hashLen == 256) {
hash <== Sha256Bytes(max_num_bits)(in_padded, in_len_padded_bytes);
}
if (hashLen == 224) {
hash <== Sha224Bytes(max_num_bits)(in_padded, in_len_padded_bytes);
}
if (hashLen == 160) {
hash <== Sha1Bytes(max_num_bits)(in_padded, in_len_padded_bytes);
}

View File

@@ -67,7 +67,6 @@ template EcdsaVerifier(signatureAlgorithm, n, k) {
ecdsa_verify.pubkey <== pubkey_xy;
ecdsa_verify.signature <== [signature_r, signature_s];
ecdsa_verify.hashed <== hash;
ecdsa_verify.dummy <== 0;
}
if (signatureAlgorithm == 9 || signatureAlgorithm == 23) {
component ecdsa_verify = verifyECDSABits(n, k, [
@@ -98,7 +97,6 @@ template EcdsaVerifier(signatureAlgorithm, n, k) {
ecdsa_verify.pubkey <== pubkey_xy;
ecdsa_verify.signature <== [signature_r, signature_s];
ecdsa_verify.hashed <== hash;
ecdsa_verify.dummy <== 0;
}
if (signatureAlgorithm == 21 || signatureAlgorithm == 24 || signatureAlgorithm == 25) {
component ecdsa_verify = verifyECDSABits(n, k, [
@@ -123,7 +121,6 @@ template EcdsaVerifier(signatureAlgorithm, n, k) {
ecdsa_verify.pubkey <== pubkey_xy;
ecdsa_verify.signature <== [signature_r, signature_s];
ecdsa_verify.hashed <== hash;
ecdsa_verify.dummy <== 0;
}
if (signatureAlgorithm == 22 || signatureAlgorithm == 26) {
component ecdsa_verify = verifyECDSABits(n, k, [
@@ -154,9 +151,8 @@ template EcdsaVerifier(signatureAlgorithm, n, k) {
ecdsa_verify.pubkey <== pubkey_xy;
ecdsa_verify.signature <== [signature_r, signature_s];
ecdsa_verify.hashed <== hash;
ecdsa_verify.dummy <== 0;
}
if (signatureAlgorithm == 27 || signatureAlgorithm == 28) {
if (signatureAlgorithm == 27 || signatureAlgorithm == 28 || signatureAlgorithm == 30) {
component ecdsa_verify = verifyECDSABits(n, k, [
3402800963,
2953063001,
@@ -188,7 +184,6 @@ template EcdsaVerifier(signatureAlgorithm, n, k) {
ecdsa_verify.pubkey <== pubkey_xy;
ecdsa_verify.signature <== [signature_r, signature_s];
ecdsa_verify.hashed <== hash;
ecdsa_verify.dummy <== 0;
}
if (signatureAlgorithm == 29) {
component ecdsa_verify = verifyECDSABits(n, k, [
@@ -225,6 +220,5 @@ template EcdsaVerifier(signatureAlgorithm, n, k) {
ecdsa_verify.pubkey <== pubkey_xy;
ecdsa_verify.signature <== [signature_r, signature_s];
ecdsa_verify.hashed <== hash;
ecdsa_verify.dummy <== 0;
}
}

View File

@@ -27,6 +27,7 @@ pragma circom 2.1.9;
27: ecdsa_sha1_brainpoolP224r1_224
28: ecdsa_sha256_brainpoolP224r1_224
29: ecdsa_sha512_brainpoolP512r1_512
30: ecdsa_sha224_brainpoolP224r1_224
*/
function getHashLength(signatureAlgorithm) {
@@ -108,6 +109,9 @@ function getHashLength(signatureAlgorithm) {
if (signatureAlgorithm == 29) {
return 512;
}
if (signatureAlgorithm == 30) {
return 224;
}
return 0;
}
@@ -187,6 +191,9 @@ function getKeyLength(signatureAlgorithm) {
if (signatureAlgorithm == 29) {
return 512;
}
if (signatureAlgorithm == 30) {
return 224;
}
return 0;
}
@@ -267,6 +274,9 @@ function getKLengthFactor(signatureAlgorithm) {
if (signatureAlgorithm == 29) {
return 2;
}
if (signatureAlgorithm == 30) {
return 2;
}
return 0;
}

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.9;
include "../circomlib/signature/rsapss/rsapss.circom";
include "secp256r1Verifier.circom";
include "ecdsaVerifier.circom";
include "../circomlib/signature/rsa/verifyRsa3Pkcs1v1_5.circom";
include "../circomlib/signature/rsa/verifyRsa65537Pkcs1v1_5.circom";
include "@zk-email/circuits/utils/bytes.circom";
@@ -82,6 +82,7 @@ template SignatureVerifier(signatureAlgorithm, n, k) {
|| signatureAlgorithm == 27
|| signatureAlgorithm == 28
|| signatureAlgorithm == 29
|| signatureAlgorithm == 30
) {
EcdsaVerifier (signatureAlgorithm, n, k)(signature, pubKey, hash);
}

View File

@@ -9,33 +9,7 @@ import crypto from 'crypto';
import { poseidon2 } from 'poseidon-lite';
import { SMT } from '@openpassport/zk-kit-smt';
import namejson from '../../common/ofacdata/outputs/nameSMT.json';
import { log } from 'console';
// const sigAlgs = [
// { sigAlg: 'rsa', hashFunction: 'sha1', domainParameter: '65537', keyLength: '2048' },
// { sigAlg: 'rsa', hashFunction: 'sha256', domainParameter: '65537', keyLength: '2048' },
// { sigAlg: 'rsapss', hashFunction: 'sha256', domainParameter: '65537', keyLength: '2048' },
// { sigAlg: 'rsapss', hashFunction: 'sha256', domainParameter: '65537', keyLength: '3072' },
// { sigAlg: 'rsapss', hashFunction: 'sha256', domainParameter: '65537', keyLength: '4096' },
// { sigAlg: 'rsapss', hashFunction: 'sha256', domainParameter: '3', keyLength: '4096' },
// { sigAlg: 'rsapss', hashFunction: 'sha256', domainParameter: '3', keyLength: '3072' },
// { sigAlg: 'rsa', hashFunction: 'sha256', domainParameter: '3', keyLength: '2048' },
// { sigAlg: 'rsa', hashFunction: 'sha256', domainParameter: '65537', keyLength: '3072' },
// { sigAlg: 'ecdsa', hashFunction: 'sha1', domainParameter: 'brainpoolP224r1', keyLength: '224' },
// { sigAlg: 'ecdsa', hashFunction: 'sha256', domainParameter: 'brainpoolP224r1', keyLength: '224' },
// { sigAlg: 'ecdsa', hashFunction: 'sha256', domainParameter: 'secp256r1', keyLength: '256' },
// { sigAlg: 'ecdsa', hashFunction: 'sha1', domainParameter: 'secp256r1', keyLength: '256' },
// { sigAlg: 'ecdsa', hashFunction: 'sha256', domainParameter: 'brainpoolP256r1', keyLength: '256' },
// { sigAlg: 'ecdsa', hashFunction: 'sha384', domainParameter: 'brainpoolP256r1', keyLength: '256' },
// { sigAlg: 'ecdsa', hashFunction: 'sha512', domainParameter: 'brainpoolP256r1', keyLength: '256' },
// { sigAlg: 'ecdsa', hashFunction: 'sha512', domainParameter: 'brainpoolP256r1', keyLength: '256' },
// { sigAlg: 'ecdsa', hashFunction: 'sha384', domainParameter: 'secp384r1', keyLength: '384' },
// { sigAlg: 'ecdsa', hashFunction: 'sha256', domainParameter: 'secp384r1', keyLength: '384' },
// { sigAlg: 'ecdsa', hashFunction: 'sha384', domainParameter: 'brainpoolP384r1', keyLength: '384' },
// ];
// { sigAlg: 'ecdsa', hashFunction: 'sha512', domainParameter: 'brainpoolP384r1', keyLength: '384' },
import { getCircuitNameFromPassportData } from '../../common/src/utils/circuitsName';
import { parsePassportData } from '../../common/src/utils/parsePassportData';
const sigAlgs = [
{
@@ -70,6 +44,86 @@ const sigAlgs = [
domainParameter: 'secp256r1',
keyLength: '256',
},
{
dgHashAlgo: 'sha256',
eContentHashAlgo: 'sha256',
sigAlg: 'ecdsa',
hashFunction: 'sha256',
domainParameter: 'brainpoolP256r1',
keyLength: '256',
},
{
dgHashAlgo: 'sha256',
eContentHashAlgo: 'sha256',
sigAlg: 'ecdsa',
hashFunction: 'sha256',
domainParameter: 'secp384r1',
keyLength: '384',
},
{
dgHashAlgo: 'sha384',
eContentHashAlgo: 'sha384',
sigAlg: 'ecdsa',
hashFunction: 'sha384',
domainParameter: 'brainpoolP256r1',
keyLength: '256',
},
{
dgHashAlgo: 'sha384',
eContentHashAlgo: 'sha384',
sigAlg: 'ecdsa',
hashFunction: 'sha384',
domainParameter: 'brainpoolP384r1',
keyLength: '384',
},
{
dgHashAlgo: 'sha384',
eContentHashAlgo: 'sha384',
sigAlg: 'ecdsa',
hashFunction: 'sha384',
domainParameter: 'secp384r1',
keyLength: '384',
},
{
dgHashAlgo: 'sha512',
eContentHashAlgo: 'sha512',
sigAlg: 'ecdsa',
hashFunction: 'sha512',
domainParameter: 'brainpoolP256r1',
keyLength: '256',
},
{
dgHashAlgo: 'sha256',
eContentHashAlgo: 'sha224',
sigAlg: 'ecdsa',
hashFunction: 'sha224',
domainParameter: 'brainpoolP224r1',
keyLength: '224',
},
{
dgHashAlgo: 'sha256',
eContentHashAlgo: 'sha256',
sigAlg: 'ecdsa',
hashFunction: 'sha256',
domainParameter: 'brainpoolP224r1',
keyLength: '224',
},
{
dgHashAlgo: 'sha1',
eContentHashAlgo: 'sha1',
sigAlg: 'ecdsa',
hashFunction: 'sha1',
domainParameter: 'brainpoolP224r1',
keyLength: '224',
},
{
dgHashAlgo: 'sha256',
eContentHashAlgo: 'sha256',
sigAlg: 'ecdsa',
hashFunction: 'sha256',
domainParameter: 'secp256r1',
keyLength: '256',
},
];
const fullSigAlgs = [

View File

@@ -40,19 +40,21 @@ export const DEFAULT_MAJORITY = '18';
// rsa_sha256_65537_3072: 384,
// rsa_sha256_3_2048: 384,
// };
export const hashAlgos = ['sha1', 'sha256', 'sha384', 'sha512'] as const;
export const hashAlgos = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512'] as const;
export const MAX_PADDED_ECONTENT_LEN: Record<(typeof hashAlgos)[number], number> = {
sha1: 320,
sha224: 384,
sha256: 448,
sha384: 576,
sha512: 704,
sha384: 640,
sha512: 768,
};
export const MAX_PADDED_SIGNED_ATTR_LEN: Partial<Record<(typeof hashAlgos)[number], number>> = {
export const MAX_PADDED_SIGNED_ATTR_LEN: Record<(typeof hashAlgos)[number], number> = {
sha1: 128,
sha224: 128,
sha256: 128,
sha384: 128,
sha512: 192,
sha384: 256,
sha512: 256,
};
export const MAX_CERT_BYTES: Partial<Record<keyof typeof SignatureAlgorithmIndex, number>> = {
@@ -104,6 +106,7 @@ export enum SignatureAlgorithmIndex {
ecdsa_sha1_brainpoolP224r1_224 = 27,
ecdsa_sha256_brainpoolP224r1_224 = 28,
ecdsa_sha512_brainpoolP512r1_512 = 29,
ecdsa_sha224_brainpoolP224r1_224 = 30,
}
export const attributeToPosition = {

View File

@@ -1265,6 +1265,25 @@ jnD0AhwDAIPS8xytmOiI0MuVj3kwdnzTLdsGslSkmj8l
-----END CERTIFICATE-----
`;
export const mock_dsc_key_sha224_braipoolP224r1 = `-----BEGIN EC PRIVATE KEY-----
MGwCAQEEHD8zMUlakQzf4dhsIN/RlRKZqRRPX+y2LJj/6OWgCwYJKyQDAwIIAQEF
oTwDOgAEVhYeSwufAC+rdeIw8skbC2bwM3g7giuR+5vl0brGHgiEIaUr33msAPHz
epGlvTkSRQz+nOWMogI=
-----END EC PRIVATE KEY-----`;
export const mock_dsc_sha224_brainpoolP224r1 = `-----BEGIN CERTIFICATE-----
MIIB0DCCAX6gAwIBAgIUKS+C9XWWr12MLB1+rcVEaYGW53UwCgYIKoZIzj0EAwEw
RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTAxMDcwNzUxMDJaFw0yNjAxMDcw
NzUxMDJaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwUjAUBgcqhkjOPQIBBgkrJAMD
AggBAQUDOgAEVhYeSwufAC+rdeIw8skbC2bwM3g7giuR+5vl0brGHgiEIaUr33ms
APHzepGlvTkSRQz+nOWMogKjUzBRMB0GA1UdDgQWBBS7hFp/MRDFZ//5GxYHnpM+
N8mqKTAfBgNVHSMEGDAWgBS7hFp/MRDFZ//5GxYHnpM+N8mqKTAPBgNVHRMBAf8E
BTADAQH/MAoGCCqGSM49BAMBA0AAMD0CHQCT+jX3mCRjmvdXO2HKlb9faeYgKfiX
frIJV5mBAhwEqIQRW2USNItxRt1iTO69eBj/20q67UOhDgK2
-----END CERTIFICATE-----`;
export const mock_dsc_key_sha256_brainpoolP224r1 = `-----BEGIN EC PRIVATE KEY-----
MGwCAQEEHEtm6OSi3EClphbb0ovVMLNX6SCQ/ZpYsFTjlnqgCwYJKyQDAwIIAQEF
oTwDOgAEb8kcLsVLjpC1RWAjA/lRTHP2HVdW1ntmtfo1g2R6E6NkgLetsRXxc8Sn

View File

@@ -56,12 +56,15 @@ import {
mock_dsc_sha256_brainpoolP224r1,
mock_dsc_key_sha512_brainpoolP512r1,
mock_dsc_sha512_brainpoolP512r1,
mock_dsc_key_sha224_braipoolP224r1,
mock_dsc_sha224_brainpoolP224r1,
} from '../constants/mockCertificates';
import { countryCodes } from '../constants/constants';
import { parseCertificateSimple } from './certificate_parsing/parseCertificateSimple';
import { SignatureAlgorithm } from './types';
import { PublicKeyDetailsECDSA, PublicKeyDetailsRSAPSS } from './certificate_parsing/dataStructure';
import { getCurveForElliptic } from './certificate_parsing/curves';
import { createHash } from 'crypto';
function generateRandomBytes(length: number): number[] {
// Generate numbers between -128 and 127 to match the existing signed byte format
@@ -219,6 +222,10 @@ export function genMockPassportData(
privateKeyPem = mock_dsc_key_sha1_brainpoolP224r1;
dsc = mock_dsc_sha1_brainpoolP224r1;
break;
case 'ecdsa_sha224_brainpoolP224r1_224':
privateKeyPem = mock_dsc_key_sha224_braipoolP224r1;
dsc = mock_dsc_sha224_brainpoolP224r1;
break;
case 'ecdsa_sha256_brainpoolP224r1_224':
privateKeyPem = mock_dsc_key_sha256_brainpoolP224r1;
dsc = mock_dsc_sha256_brainpoolP224r1;
@@ -284,22 +291,16 @@ function sign(
);
const asn1Data = asn1.fromBER(privateKeyDer);
const privateKeyBuffer = (asn1Data.result.valueBlock as any).value[1].valueBlock.valueHexView;
// console.log('sig deets');
// console.log('pk', privateKeyBuffer);
// console.log('hashFUnction', hashAlgorithm);
// console.log('message', Buffer.from(eContent).toString('hex'));
const keyPair = ec.keyFromPrivate(privateKeyBuffer);
let md = forge.md[hashAlgorithm].create();
md.update(forge.util.binary.raw.encode(new Uint8Array(eContent)));
// let md = forge.md[hashAlgorithm].create();
// md.update(forge.util.binary.raw.encode(new Uint8Array(eContent)));
const hasher = createHash(hashAlgorithm);
const msgHash = hasher.update(new Uint8Array(eContent)).digest('hex');
// console.log('message to sign', md.digest().toHex());
const signature = keyPair.sign(md.digest().toHex(), 'hex');
// console.log(Buffer.from(signature.toDER(), 'hex').toString('hex'));
const signature = keyPair.sign(msgHash, 'hex');
const signatureBytes = Array.from(Buffer.from(signature.toDER(), 'hex'));
// console.log('sig', JSON.stringify(signatureBytes));
return signatureBytes;
} else {
const privKey = forge.pki.privateKeyFromPem(privateKeyPem);

View File

@@ -221,11 +221,12 @@ export function generateCircuitInputsProve(
);
}
// const paddingFunction =
// hashFunction == 'sha1' || hashFunction == 'sha256' ? shaPad : sha384_512Pad;
const dg1PaddingFunction =
MAX_PADDED_ECONTENT_LEN[passportMetadata.dg1HashFunction] <= 256 ? shaPad : sha384_512Pad;
passportMetadata.dg1HashFunction === 'sha1' ||
passportMetadata.dg1HashFunction === 'sha224' ||
passportMetadata.dg1HashFunction === 'sha256'
? shaPad
: sha384_512Pad;
const [eContentPadded, eContentLen] = dg1PaddingFunction(
new Uint8Array(eContent),
@@ -233,7 +234,11 @@ export function generateCircuitInputsProve(
);
const eContentPaddingFunction =
MAX_PADDED_ECONTENT_LEN[passportMetadata.eContentHashFunction] <= 256 ? shaPad : sha384_512Pad;
passportMetadata.eContentHashFunction === 'sha1' ||
passportMetadata.eContentHashFunction === 'sha224' ||
passportMetadata.eContentHashFunction === 'sha256'
? shaPad
: sha384_512Pad;
const [signedAttrPadded, signedAttrPaddedLen] = eContentPaddingFunction(
new Uint8Array(signedAttr),
MAX_PADDED_SIGNED_ATTR_LEN[passportMetadata.eContentHashFunction]

View File

@@ -2,10 +2,10 @@ import { PassportData } from '../../../common/src/utils/types';
import { findSubarrayIndex, formatMrz, hash } from './utils';
import { parseCertificateSimple } from './certificate_parsing/parseCertificateSimple';
import {
CertificateData,
PublicKeyDetailsECDSA,
PublicKeyDetailsRSA,
PublicKeyDetailsRSAPSS,
CertificateData,
PublicKeyDetailsECDSA,
PublicKeyDetailsRSA,
PublicKeyDetailsRSAPSS,
} from './certificate_parsing/dataStructure';
import { getCSCAFromSKI } from './csca';
import { hashAlgos } from '../constants/constants';
@@ -14,225 +14,227 @@ import forge from 'node-forge';
import * as asn1js from 'asn1js';
import { initElliptic } from './elliptic';
import { getCurveForElliptic } from './certificate_parsing/curves';
import { createHash } from 'crypto';
export interface PassportMetadata {
dataGroups: string;
dg1HashFunction: string;
dg1HashOffset: number;
eContentSize: number;
eContentHashFunction: string;
eContentHashOffset: number;
signedAttrSize: number;
signedAttrHashFunction: string;
signatureAlgorithm: string;
signatureAlgorithmDetails: string;
curveOrExponent: string;
signatureAlgorithmBits: number;
countryCode: string;
cscaFound: boolean;
cscaHashFunction: string;
cscaSignature: string;
cscaSignatureAlgorithmDetails: string;
cscaCurveOrExponent: string;
cscaSignatureAlgorithmBits: number;
dsc: string;
dataGroups: string;
dg1HashFunction: string;
dg1HashOffset: number;
eContentSize: number;
eContentHashFunction: string;
eContentHashOffset: number;
signedAttrSize: number;
signedAttrHashFunction: string;
signatureAlgorithm: string;
signatureAlgorithmDetails: string;
curveOrExponent: string;
signatureAlgorithmBits: number;
countryCode: string;
cscaFound: boolean;
cscaHashFunction: string;
cscaSignature: string;
cscaSignatureAlgorithmDetails: string;
cscaCurveOrExponent: string;
cscaSignatureAlgorithmBits: number;
dsc: string;
}
export function findHashSizeOfEContent(eContent: number[], signedAttr: number[]) {
for (const hashFunction of hashAlgos) {
const hashValue = hash(hashFunction, eContent);
const hashOffset = findSubarrayIndex(signedAttr, hashValue);
if (hashOffset !== -1) {
return { hashFunction, offset: hashOffset };
}
for (const hashFunction of hashAlgos) {
const hashValue = hash(hashFunction, eContent);
const hashOffset = findSubarrayIndex(signedAttr, hashValue);
if (hashOffset !== -1) {
return { hashFunction, offset: hashOffset };
}
return { hashFunction: 'unknown', offset: -1 };
}
return { hashFunction: 'unknown', offset: -1 };
}
export function findDG1HashInEContent(
mrz: string,
eContent: number[]
mrz: string,
eContent: number[]
): { hash: number[]; hashFunction: string; offset: number } | null {
const formattedMrz = formatMrz(mrz);
const formattedMrz = formatMrz(mrz);
for (const hashFunction of hashAlgos) {
const hashValue = hash(hashFunction, formattedMrz);
const normalizedHash = hashValue.map((byte) => (byte > 127 ? byte - 256 : byte));
const hashOffset = findSubarrayIndex(eContent, normalizedHash);
for (const hashFunction of hashAlgos) {
const hashValue = hash(hashFunction, formattedMrz);
const normalizedHash = hashValue.map((byte) => (byte > 127 ? byte - 256 : byte));
const hashOffset = findSubarrayIndex(eContent, normalizedHash);
if (hashOffset !== -1) {
return { hash: hashValue, hashFunction, offset: hashOffset };
}
if (hashOffset !== -1) {
return { hash: hashValue, hashFunction, offset: hashOffset };
}
return null;
}
return null;
}
export function getCountryCodeFromMrz(mrz: string): string {
return mrz.substring(2, 5);
return mrz.substring(2, 5);
}
export function getCurveOrExponent(certData: CertificateData): string {
if (certData.signatureAlgorithm === 'rsapss' || certData.signatureAlgorithm === 'rsa') {
return (certData.publicKeyDetails as PublicKeyDetailsRSA).exponent;
}
return (certData.publicKeyDetails as PublicKeyDetailsECDSA).curve;
if (certData.signatureAlgorithm === 'rsapss' || certData.signatureAlgorithm === 'rsa') {
return (certData.publicKeyDetails as PublicKeyDetailsRSA).exponent;
}
return (certData.publicKeyDetails as PublicKeyDetailsECDSA).curve;
}
export function getSimplePublicKeyDetails(certData: CertificateData): string {
interface SimplePublicKeyDetails {
exponent?: string;
curve?: string;
hashAlgorithm?: string;
saltLength?: string;
interface SimplePublicKeyDetails {
exponent?: string;
curve?: string;
hashAlgorithm?: string;
saltLength?: string;
}
const simplePublicKeyDetails: SimplePublicKeyDetails = {};
if (certData.signatureAlgorithm === 'rsapss' || certData.signatureAlgorithm === 'rsa') {
simplePublicKeyDetails.exponent = (certData.publicKeyDetails as PublicKeyDetailsRSA).exponent;
if (certData.signatureAlgorithm === 'rsapss') {
simplePublicKeyDetails.hashAlgorithm = (
certData.publicKeyDetails as PublicKeyDetailsRSAPSS
).hashAlgorithm;
simplePublicKeyDetails.saltLength = (
certData.publicKeyDetails as PublicKeyDetailsRSAPSS
).saltLength;
}
const simplePublicKeyDetails: SimplePublicKeyDetails = {};
if (certData.signatureAlgorithm === 'rsapss' || certData.signatureAlgorithm === 'rsa') {
simplePublicKeyDetails.exponent = (certData.publicKeyDetails as PublicKeyDetailsRSA).exponent;
if (certData.signatureAlgorithm === 'rsapss') {
simplePublicKeyDetails.hashAlgorithm = (
certData.publicKeyDetails as PublicKeyDetailsRSAPSS
).hashAlgorithm;
simplePublicKeyDetails.saltLength = (
certData.publicKeyDetails as PublicKeyDetailsRSAPSS
).saltLength;
}
} else if (certData.signatureAlgorithm === 'ecdsa') {
simplePublicKeyDetails.curve = (certData.publicKeyDetails as PublicKeyDetailsECDSA).curve;
}
return JSON.stringify(simplePublicKeyDetails);
} else if (certData.signatureAlgorithm === 'ecdsa') {
simplePublicKeyDetails.curve = (certData.publicKeyDetails as PublicKeyDetailsECDSA).curve;
}
return JSON.stringify(simplePublicKeyDetails);
}
export function verifySignature(passportData: PassportData, hashAlgorithm: string): boolean {
const elliptic = initElliptic();
const { dsc, signedAttr, encryptedDigest } = passportData;
const { signatureAlgorithm, publicKeyDetails } = parseCertificateSimple(dsc);
const elliptic = initElliptic();
const { dsc, signedAttr, encryptedDigest } = passportData;
const { signatureAlgorithm, publicKeyDetails } = parseCertificateSimple(dsc);
if (signatureAlgorithm === 'ecdsa') {
const certBuffer = Buffer.from(
dsc.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''),
'base64'
);
const asn1Data = asn1js.fromBER(certBuffer);
const cert = new Certificate({ schema: asn1Data.result });
const publicKeyInfo = cert.subjectPublicKeyInfo;
const publicKeyBuffer = publicKeyInfo.subjectPublicKey.valueBlock.valueHexView;
const curveForElliptic = getCurveForElliptic((publicKeyDetails as PublicKeyDetailsECDSA).curve);
const ec = new elliptic.ec(curveForElliptic);
if (signatureAlgorithm === 'ecdsa') {
const certBuffer = Buffer.from(
dsc.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, ''),
'base64'
);
const asn1Data = asn1js.fromBER(certBuffer);
const cert = new Certificate({ schema: asn1Data.result });
const publicKeyInfo = cert.subjectPublicKeyInfo;
const publicKeyBuffer = publicKeyInfo.subjectPublicKey.valueBlock.valueHexView;
const curveForElliptic = getCurveForElliptic((publicKeyDetails as PublicKeyDetailsECDSA).curve);
const ec = new elliptic.ec(curveForElliptic);
const key = ec.keyFromPublic(publicKeyBuffer);
const md = forge.md[hashAlgorithm].create();
md.update(forge.util.binary.raw.encode(new Uint8Array(signedAttr)));
const msgHash = md.digest().toHex();
const signature_crypto = Buffer.from(encryptedDigest).toString('hex');
const key = ec.keyFromPublic(publicKeyBuffer);
const hasher = createHash(hashAlgorithm);
const msgHash = hasher.update(new Uint8Array(signedAttr)).digest('hex');
const signature_crypto = Buffer.from(encryptedDigest).toString('hex');
return key.verify(msgHash, signature_crypto);
} else {
const cert = forge.pki.certificateFromPem(dsc);
const publicKey = cert.publicKey as forge.pki.rsa.PublicKey;
return key.verify(msgHash, signature_crypto);
} else {
const cert = forge.pki.certificateFromPem(dsc);
const publicKey = cert.publicKey as forge.pki.rsa.PublicKey;
try {
const md = forge.md[hashAlgorithm].create();
md.update(forge.util.binary.raw.encode(new Uint8Array(signedAttr)));
const md = forge.md[hashAlgorithm].create();
md.update(forge.util.binary.raw.encode(new Uint8Array(signedAttr)));
const signature = Buffer.from(encryptedDigest).toString('binary');
const signature = Buffer.from(encryptedDigest).toString('binary');
if (signatureAlgorithm === 'rsapss') {
try {
const pss = forge.pss.create({
md: forge.md[hashAlgorithm].create(),
mgf: forge.mgf.mgf1.create(forge.md[hashAlgorithm].create()),
saltLength: parseInt((publicKeyDetails as PublicKeyDetailsRSAPSS).saltLength),
});
return publicKey.verify(md.digest().bytes(), signature, pss);
} catch (error) {
return false;
}
} else {
return publicKey.verify(md.digest().bytes(), signature);
if (signatureAlgorithm === 'rsapss') {
try {
const pss = forge.pss.create({
md: forge.md[hashAlgorithm].create(),
mgf: forge.mgf.mgf1.create(forge.md[hashAlgorithm].create()),
saltLength: parseInt((publicKeyDetails as PublicKeyDetailsRSAPSS).saltLength),
});
return publicKey.verify(md.digest().bytes(), signature, pss);
} catch (error) {
return false;
}
} else {
return publicKey.verify(md.digest().bytes(), signature);
}
} catch (err) {
return false;
}
}
}
export function brutforceHashAlgorithm(passportData: PassportData): any {
for (const hashFunction of hashAlgos) {
if (verifySignature(passportData, hashFunction)) {
return hashFunction;
}
for (const hashFunction of hashAlgos) {
if (verifySignature(passportData, hashFunction)) {
return hashFunction;
}
return null;
}
return null;
}
export function parsePassportData(passportData: PassportData): PassportMetadata {
const dg1HashInfo = passportData.mrz
? findDG1HashInEContent(passportData.mrz, passportData.eContent)
: null;
const dg1HashInfo = passportData.mrz
? findDG1HashInEContent(passportData.mrz, passportData.eContent)
: null;
const dg1HashFunction = dg1HashInfo?.hashFunction || 'unknown';
const dg1HashOffset = dg1HashInfo?.offset || 0;
const dg1HashFunction = dg1HashInfo?.hashFunction || 'unknown';
const dg1HashOffset = dg1HashInfo?.offset || 0;
const { hashFunction: eContentHashFunction, offset: eContentHashOffset } = findHashSizeOfEContent(
passportData.eContent,
passportData.signedAttr
);
const { hashFunction: eContentHashFunction, offset: eContentHashOffset } = findHashSizeOfEContent(
passportData.eContent,
passportData.signedAttr
);
const signatureHashAlgo = brutforceHashAlgorithm(passportData);
const signatureHashAlgo = brutforceHashAlgorithm(passportData);
let parsedDsc = null;
let parsedCsca = null;
let csca = null;
let dscSignature = 'unknown';
let dscSignatureAlgorithmDetails = 'unknown';
let dscSignatureAlgorithmBits = 0;
let cscaHashFunction = 'unknown';
let cscaSignature = 'unknown';
let cscaSignatureAlgorithmDetails = 'unknown';
let cscaSignatureAlgorithmBits = 0;
let parsedDsc = null;
let parsedCsca = null;
let csca = null;
let dscSignature = 'unknown';
let dscSignatureAlgorithmDetails = 'unknown';
let dscSignatureAlgorithmBits = 0;
let cscaHashFunction = 'unknown';
let cscaSignature = 'unknown';
let cscaSignatureAlgorithmDetails = 'unknown';
let cscaSignatureAlgorithmBits = 0;
if (passportData.dsc) {
parsedDsc = parseCertificateSimple(passportData.dsc);
dscSignature = parsedDsc.signatureAlgorithm;
dscSignatureAlgorithmDetails = getSimplePublicKeyDetails(parsedDsc);
dscSignatureAlgorithmBits = parseInt(parsedDsc.publicKeyDetails?.bits || '0');
if (passportData.dsc) {
parsedDsc = parseCertificateSimple(passportData.dsc);
dscSignature = parsedDsc.signatureAlgorithm;
dscSignatureAlgorithmDetails = getSimplePublicKeyDetails(parsedDsc);
dscSignatureAlgorithmBits = parseInt(parsedDsc.publicKeyDetails?.bits || '0');
if (parsedDsc.authorityKeyIdentifier) {
try {
csca = getCSCAFromSKI(parsedDsc.authorityKeyIdentifier, true);
if (csca) {
parsedCsca = parseCertificateSimple(csca);
cscaHashFunction = parsedCsca.hashAlgorithm;
cscaSignature = parsedCsca.signatureAlgorithm;
cscaSignatureAlgorithmDetails = getSimplePublicKeyDetails(parsedCsca);
cscaSignatureAlgorithmBits = parseInt(parsedCsca.publicKeyDetails?.bits || '0');
}
} catch (error) {
}
if (parsedDsc.authorityKeyIdentifier) {
try {
csca = getCSCAFromSKI(parsedDsc.authorityKeyIdentifier, true);
if (csca) {
parsedCsca = parseCertificateSimple(csca);
cscaHashFunction = parsedCsca.hashAlgorithm;
cscaSignature = parsedCsca.signatureAlgorithm;
cscaSignatureAlgorithmDetails = getSimplePublicKeyDetails(parsedCsca);
cscaSignatureAlgorithmBits = parseInt(parsedCsca.publicKeyDetails?.bits || '0');
}
} catch (error) {}
}
}
return {
dataGroups:
passportData.dgPresents
?.toString()
.split(',')
.map((item) => item.replace('DG', ''))
.join(',') || 'None',
dg1HashFunction,
dg1HashOffset,
eContentSize: passportData.eContent?.length || 0,
eContentHashFunction,
eContentHashOffset,
signedAttrSize: passportData.signedAttr?.length || 0,
signedAttrHashFunction: signatureHashAlgo,
signatureAlgorithm: dscSignature,
signatureAlgorithmDetails: dscSignatureAlgorithmDetails,
curveOrExponent: parsedDsc ? getCurveOrExponent(parsedDsc) : 'unknown',
signatureAlgorithmBits: dscSignatureAlgorithmBits,
countryCode: passportData.mrz ? getCountryCodeFromMrz(passportData.mrz) : 'unknown',
cscaFound: !!csca,
cscaHashFunction,
cscaSignature,
cscaSignatureAlgorithmDetails,
cscaCurveOrExponent: parsedCsca ? getCurveOrExponent(parsedCsca) : 'unknown',
cscaSignatureAlgorithmBits: cscaSignatureAlgorithmBits,
dsc: passportData.dsc,
};
return {
dataGroups:
passportData.dgPresents
?.toString()
.split(',')
.map((item) => item.replace('DG', ''))
.join(',') || 'None',
dg1HashFunction,
dg1HashOffset,
eContentSize: passportData.eContent?.length || 0,
eContentHashFunction,
eContentHashOffset,
signedAttrSize: passportData.signedAttr?.length || 0,
signedAttrHashFunction: signatureHashAlgo,
signatureAlgorithm: dscSignature,
signatureAlgorithmDetails: dscSignatureAlgorithmDetails,
curveOrExponent: parsedDsc ? getCurveOrExponent(parsedDsc) : 'unknown',
signatureAlgorithmBits: dscSignatureAlgorithmBits,
countryCode: passportData.mrz ? getCountryCodeFromMrz(passportData.mrz) : 'unknown',
cscaFound: !!csca,
cscaHashFunction,
cscaSignature,
cscaSignatureAlgorithmDetails,
cscaCurveOrExponent: parsedCsca ? getCurveOrExponent(parsedCsca) : 'unknown',
cscaSignatureAlgorithmBits: cscaSignatureAlgorithmBits,
dsc: passportData.dsc,
};
}

View File

@@ -35,6 +35,7 @@ export type SignatureAlgorithm =
| 'ecdsa_sha384_brainpoolP384r1_384'
| 'ecdsa_sha512_brainpoolP384r1_384'
| 'ecdsa_sha1_brainpoolP224r1_224'
| 'ecdsa_sha224_brainpoolP224r1_224'
| 'ecdsa_sha256_brainpoolP224r1_224'
| 'ecdsa_sha512_brainpoolP512r1_512'
| 'rsapss_sha256_65537_4096';

View File

@@ -1,5 +1,5 @@
import { LeanIMT } from '@openpassport/zk-kit-lean-imt';
import { sha256 } from 'js-sha256';
import { sha224, sha256 } from 'js-sha256';
import { sha1 } from 'js-sha1';
import { sha384, sha512 } from 'js-sha512';
import { SMT } from '@openpassport/zk-kit-smt';
@@ -248,6 +248,9 @@ export function hash(hashFunction: string, bytesArray: number[]): number[] {
case 'sha1':
hashResult = sha1(unsignedBytesArray);
break;
case 'sha224':
hashResult = sha224(unsignedBytesArray);
break;
case 'sha256':
hashResult = sha256(unsignedBytesArray);
break;
@@ -323,6 +326,8 @@ export function getHashLen(hashFunction: string) {
switch (hashFunction) {
case 'sha1':
return 20;
case 'sha224':
return 28;
case 'sha256':
return 32;
case 'sha384':