diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha384_brainpoolP256r1_256.circom b/circuits/circuits/prove/instances/prove_ecdsa_sha384_brainpoolP256r1_256.circom deleted file mode 100644 index f07b77ae7..000000000 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha384_brainpoolP256r1_256.circom +++ /dev/null @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha384_brainpoolP384r1_384.circom b/circuits/circuits/prove/instances/prove_ecdsa_sha384_brainpoolP384r1_384.circom deleted file mode 100644 index 280bc9d53..000000000 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha384_brainpoolP384r1_384.circom +++ /dev/null @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha384_secp384r1_384.circom b/circuits/circuits/prove/instances/prove_ecdsa_sha384_secp384r1_384.circom deleted file mode 100644 index a8a691ebb..000000000 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha384_secp384r1_384.circom +++ /dev/null @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha512_brainpoolP256r1_256.circom b/circuits/circuits/prove/instances/prove_ecdsa_sha512_brainpoolP256r1_256.circom deleted file mode 100644 index 2d8f35694..000000000 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha512_brainpoolP256r1_256.circom +++ /dev/null @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha512_brainpoolP384r1_384.circom b/circuits/circuits/prove/instances/prove_ecdsa_sha512_brainpoolP384r1_384.circom deleted file mode 100644 index eb2eca24f..000000000 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha512_brainpoolP384r1_384.circom +++ /dev/null @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha256_brainpoolP224r1_224.circom b/circuits/circuits/prove/instances/prove_sha1_sha1_sha1_ecdsa_brainpoolP224r1.circom similarity index 68% rename from circuits/circuits/prove/instances/prove_ecdsa_sha256_brainpoolP224r1_224.circom rename to circuits/circuits/prove/instances/prove_sha1_sha1_sha1_ecdsa_brainpoolP224r1.circom index a7149b2d0..c31ab6fec 100644 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha256_brainpoolP224r1_224.circom +++ b/circuits/circuits/prove/instances/prove_sha1_sha1_sha1_ecdsa_brainpoolP224r1.circom @@ -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); \ No newline at end of file +component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(160, 160, 27, 32, 7, 320, 128, 20); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha256_brainpoolP256r1_256.circom b/circuits/circuits/prove/instances/prove_sha256_sha224_sha224_ecdsa_brainpoolP224r1.circom similarity index 68% rename from circuits/circuits/prove/instances/prove_ecdsa_sha256_brainpoolP256r1_256.circom rename to circuits/circuits/prove/instances/prove_sha256_sha224_sha224_ecdsa_brainpoolP224r1.circom index 68691e0e4..11af9c875 100644 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha256_brainpoolP256r1_256.circom +++ b/circuits/circuits/prove/instances/prove_sha256_sha224_sha224_ecdsa_brainpoolP224r1.circom @@ -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); \ No newline at end of file +component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(256, 224, 30, 32, 7, 448, 128, 20); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha256_secp384r1_384.circom b/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_brainpoolP224r1.circom similarity index 68% rename from circuits/circuits/prove/instances/prove_ecdsa_sha256_secp384r1_384.circom rename to circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_brainpoolP224r1.circom index 118802ff9..fb06f56d7 100644 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha256_secp384r1_384.circom +++ b/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_brainpoolP224r1.circom @@ -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); \ No newline at end of file +component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(256, 256, 28, 32, 7, 448, 128, 20); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_brainpoolP256r1.circom b/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_brainpoolP256r1.circom new file mode 100644 index 000000000..30f17f8b9 --- /dev/null +++ b/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_brainpoolP256r1.circom @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_sha256_sh256_sha256_ecdsa_secp256r1_256.circom b/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_secp256r1.circom similarity index 100% rename from circuits/circuits/prove/instances/prove_sha256_sh256_sha256_ecdsa_secp256r1_256.circom rename to circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_secp256r1.circom diff --git a/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_secp384r1.circom b/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_secp384r1.circom new file mode 100644 index 000000000..e9b46850e --- /dev/null +++ b/circuits/circuits/prove/instances/prove_sha256_sha256_sha256_ecdsa_secp384r1.circom @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_brainpoolP256r1.circom b/circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_brainpoolP256r1.circom new file mode 100644 index 000000000..063a45a2a --- /dev/null +++ b/circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_brainpoolP256r1.circom @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_brainpoolP384r1.circom b/circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_brainpoolP384r1.circom new file mode 100644 index 000000000..9b417b4b3 --- /dev/null +++ b/circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_brainpoolP384r1.circom @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_ecdsa_sha1_brainpoolP224r1_224.circom b/circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_secp384r1.circom similarity index 68% rename from circuits/circuits/prove/instances/prove_ecdsa_sha1_brainpoolP224r1_224.circom rename to circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_secp384r1.circom index f2cca9086..bb1194e0c 100644 --- a/circuits/circuits/prove/instances/prove_ecdsa_sha1_brainpoolP224r1_224.circom +++ b/circuits/circuits/prove/instances/prove_sha384_sha384_sha384_ecdsa_secp384r1.circom @@ -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); \ No newline at end of file +component main { public [ scope, user_identifier, current_date] } = OPENPASSPORT_PROVE(384, 384, 9, 64, 6, 640, 256, 20); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_sha512_sha512_sha512_ecdsa_brainpoolP256r1.circom b/circuits/circuits/prove/instances/prove_sha512_sha512_sha512_ecdsa_brainpoolP256r1.circom new file mode 100644 index 000000000..7774021ab --- /dev/null +++ b/circuits/circuits/prove/instances/prove_sha512_sha512_sha512_ecdsa_brainpoolP256r1.circom @@ -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); \ No newline at end of file diff --git a/circuits/circuits/prove/instances/prove_sha512_sha512_sha512_ecdsa_brainpoolP384r1.circom b/circuits/circuits/prove/instances/prove_sha512_sha512_sha512_ecdsa_brainpoolP384r1.circom new file mode 100644 index 000000000..af0381054 --- /dev/null +++ b/circuits/circuits/prove/instances/prove_sha512_sha512_sha512_ecdsa_brainpoolP384r1.circom @@ -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); \ No newline at end of file diff --git a/circuits/circuits/utils/circomlib/bigInt/bigIntFunc.circom b/circuits/circuits/utils/circomlib/bigInt/bigIntFunc.circom index ea2799b8b..aba0e8dfe 100644 --- a/circuits/circuits/utils/circomlib/bigInt/bigIntFunc.circom +++ b/circuits/circuits/utils/circomlib/bigInt/bigIntFunc.circom @@ -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++) { diff --git a/circuits/circuits/utils/circomlib/ec/curve.circom b/circuits/circuits/utils/circomlib/ec/curve.circom index d9c5cc851..98a00f375 100644 --- a/circuits/circuits/utils/circomlib/ec/curve.circom +++ b/circuits/circuits/utils/circomlib/ec/curve.circom @@ -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++){ diff --git a/circuits/circuits/utils/circomlib/hasher/sha2/sha224/sha224HashChunks.circom b/circuits/circuits/utils/circomlib/hasher/sha2/sha224/sha224HashChunks.circom index 0c9d51b57..1b8d21e3d 100644 --- a/circuits/circuits/utils/circomlib/hasher/sha2/sha224/sha224HashChunks.circom +++ b/circuits/circuits/utils/circomlib/hasher/sha2/sha224/sha224HashChunks.circom @@ -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; } } } diff --git a/circuits/circuits/utils/circomlib/hasher/sha2/sha384/sha384HashChunks.circom b/circuits/circuits/utils/circomlib/hasher/sha2/sha384/sha384HashChunks.circom index 72602370f..d2cc71669 100644 --- a/circuits/circuits/utils/circomlib/hasher/sha2/sha384/sha384HashChunks.circom +++ b/circuits/circuits/utils/circomlib/hasher/sha2/sha384/sha384HashChunks.circom @@ -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]; diff --git a/circuits/circuits/utils/circomlib/hasher/sha2/sha512/sha512HashChunks.circom b/circuits/circuits/utils/circomlib/hasher/sha2/sha512/sha512HashChunks.circom index 2fe47bb02..de38176dc 100644 --- a/circuits/circuits/utils/circomlib/hasher/sha2/sha512/sha512HashChunks.circom +++ b/circuits/circuits/utils/circomlib/hasher/sha2/sha512/sha512HashChunks.circom @@ -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) { diff --git a/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha224Bytes.circom b/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha224Bytes.circom new file mode 100644 index 000000000..5ca997db7 --- /dev/null +++ b/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha224Bytes.circom @@ -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]; + } +} diff --git a/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha384Bytes.circom b/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha384Bytes.circom index 6d948ea9e..6f579b371 100644 --- a/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha384Bytes.circom +++ b/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha384Bytes.circom @@ -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]; diff --git a/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha512Bytes.circom b/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha512Bytes.circom index 1b026001c..d40e68bd2 100644 --- a/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha512Bytes.circom +++ b/circuits/circuits/utils/circomlib/hasher/shaBytes/dynamic/sha512Bytes.circom @@ -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) { diff --git a/circuits/circuits/utils/circomlib/hasher/shaBytes/shaBytesDynamic.circom b/circuits/circuits/utils/circomlib/hasher/shaBytes/shaBytesDynamic.circom index 6f5c59bcc..9b5fdfc70 100644 --- a/circuits/circuits/utils/circomlib/hasher/shaBytes/shaBytesDynamic.circom +++ b/circuits/circuits/utils/circomlib/hasher/shaBytes/shaBytesDynamic.circom @@ -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); } diff --git a/circuits/circuits/utils/passport/ecdsaVerifier.circom b/circuits/circuits/utils/passport/ecdsaVerifier.circom index 106df4aab..321a723e6 100644 --- a/circuits/circuits/utils/passport/ecdsaVerifier.circom +++ b/circuits/circuits/utils/passport/ecdsaVerifier.circom @@ -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; } } \ No newline at end of file diff --git a/circuits/circuits/utils/passport/signatureAlgorithm.circom b/circuits/circuits/utils/passport/signatureAlgorithm.circom index be6111793..7bf76e7f4 100644 --- a/circuits/circuits/utils/passport/signatureAlgorithm.circom +++ b/circuits/circuits/utils/passport/signatureAlgorithm.circom @@ -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; } diff --git a/circuits/circuits/utils/passport/signatureVerifier.circom b/circuits/circuits/utils/passport/signatureVerifier.circom index d3846167f..ab8f944b0 100644 --- a/circuits/circuits/utils/passport/signatureVerifier.circom +++ b/circuits/circuits/utils/passport/signatureVerifier.circom @@ -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); } diff --git a/circuits/tests/prove.test.ts b/circuits/tests/prove.test.ts index 21fc7baeb..d34f4ac1d 100644 --- a/circuits/tests/prove.test.ts +++ b/circuits/tests/prove.test.ts @@ -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 = [ diff --git a/common/src/constants/constants.ts b/common/src/constants/constants.ts index 60a733e33..971cd0e04 100644 --- a/common/src/constants/constants.ts +++ b/common/src/constants/constants.ts @@ -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> = { +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> = { @@ -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 = { diff --git a/common/src/constants/mockCertificates.ts b/common/src/constants/mockCertificates.ts index 431cc83d7..4197e1aad 100644 --- a/common/src/constants/mockCertificates.ts +++ b/common/src/constants/mockCertificates.ts @@ -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 diff --git a/common/src/utils/genMockPassportData.ts b/common/src/utils/genMockPassportData.ts index 714bd98bf..f6a8925c1 100644 --- a/common/src/utils/genMockPassportData.ts +++ b/common/src/utils/genMockPassportData.ts @@ -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); diff --git a/common/src/utils/generateInputs.ts b/common/src/utils/generateInputs.ts index c03107c6f..fd376eaaa 100644 --- a/common/src/utils/generateInputs.ts +++ b/common/src/utils/generateInputs.ts @@ -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] diff --git a/common/src/utils/parsePassportData.ts b/common/src/utils/parsePassportData.ts index 0bbfc94f7..b7f868680 100644 --- a/common/src/utils/parsePassportData.ts +++ b/common/src/utils/parsePassportData.ts @@ -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, + }; } diff --git a/common/src/utils/types.ts b/common/src/utils/types.ts index ea3fd47d5..02f66c83e 100644 --- a/common/src/utils/types.ts +++ b/common/src/utils/types.ts @@ -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'; diff --git a/common/src/utils/utils.ts b/common/src/utils/utils.ts index 8f3cb011f..5bd89ccf4 100644 --- a/common/src/utils/utils.ts +++ b/common/src/utils/utils.ts @@ -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':