mirror of
https://github.com/selfxyz/self.git
synced 2026-01-22 21:17:59 -05:00
support for variable number of datagroups in circuit
This commit is contained in:
@@ -3,9 +3,9 @@ pragma circom 2.1.5;
|
||||
include "circomlib/circuits/bitify.circom";
|
||||
include "circomlib/circuits/sha256/sha256.circom";
|
||||
|
||||
template Sha256Bytes(max_num_bytes) {
|
||||
// Static length sha256 bytes, adapted from zk-email
|
||||
template Sha256BytesStatic(max_num_bytes) {
|
||||
signal input in_padded[max_num_bytes];
|
||||
// signal input in_len_padded_bytes;
|
||||
signal output out[256];
|
||||
|
||||
var num_bits = max_num_bytes * 8;
|
||||
@@ -19,7 +19,6 @@ template Sha256Bytes(max_num_bytes) {
|
||||
sha.in[i*8+j] <== bytes[i].out[7-j];
|
||||
}
|
||||
}
|
||||
// sha.in_len_padded_bits <== in_len_padded_bytes * 8;
|
||||
|
||||
for (var i = 0; i < 256; i++) {
|
||||
out[i] <== sha.out[i];
|
||||
@@ -2,18 +2,20 @@ pragma circom 2.1.5;
|
||||
|
||||
include "@zk-email/circuits/helpers/rsa.circom";
|
||||
include "@zk-email/circuits/helpers/extract.circom";
|
||||
include "./sha256Bytes.circom";
|
||||
include "@zk-email/circuits/helpers/sha.circom";
|
||||
include "./Sha256BytesStatic.circom";
|
||||
|
||||
template PassportVerifier(n, k) {
|
||||
template PassportVerifier(n, k, max_datahashes_bytes) {
|
||||
signal input mrz[93]; // formatted mrz (5 + 88) chars
|
||||
signal input dataHashes[297];
|
||||
signal input dataHashes[max_datahashes_bytes];
|
||||
signal input datahashes_padded_length;
|
||||
signal input eContentBytes[104];
|
||||
|
||||
signal input pubkey[k];
|
||||
signal input signature[k];
|
||||
|
||||
// compute sha256 of formatted mrz
|
||||
signal mrzSha[256] <== Sha256Bytes(93)(mrz);
|
||||
signal mrzSha[256] <== Sha256BytesStatic(93)(mrz);
|
||||
|
||||
// get output of sha256 into bytes to check against dataHashes
|
||||
component sha256_bytes[32];
|
||||
@@ -29,8 +31,8 @@ template PassportVerifier(n, k) {
|
||||
dataHashes[31 + i] === sha256_bytes[i].out;
|
||||
}
|
||||
|
||||
// hash dataHashes
|
||||
signal dataHashesSha[256] <== Sha256Bytes(297)(dataHashes);
|
||||
// hash dataHashes dynamically
|
||||
signal dataHashesSha[256] <== Sha256Bytes(max_datahashes_bytes)(dataHashes, datahashes_padded_length);
|
||||
|
||||
// get output of dataHashes sha256 into bytes to check against eContent
|
||||
component dataHashes_sha256_bytes[32];
|
||||
@@ -47,7 +49,7 @@ template PassportVerifier(n, k) {
|
||||
}
|
||||
|
||||
// hash eContentBytes
|
||||
signal eContentSha[256] <== Sha256Bytes(104)(eContentBytes);
|
||||
signal eContentSha[256] <== Sha256BytesStatic(104)(eContentBytes);
|
||||
|
||||
// get output of eContentBytes sha256 into k chunks of n bits each
|
||||
var msg_len = (256 + n) \ n;
|
||||
|
||||
@@ -4,9 +4,10 @@ include "circomlib/circuits/poseidon.circom";
|
||||
include "@zk-email/circuits/helpers/extract.circom";
|
||||
include "./passport_verifier.circom";
|
||||
|
||||
template ProofOfPassport(n, k) {
|
||||
template ProofOfPassport(n, k, max_datahashes_bytes) {
|
||||
signal input mrz[93]; // formatted mrz (5 + 88) chars
|
||||
signal input dataHashes[297];
|
||||
signal input dataHashes[max_datahashes_bytes];
|
||||
signal input datahashes_padded_length;
|
||||
signal input eContentBytes[104];
|
||||
signal input pubkey[k];
|
||||
signal input signature[k];
|
||||
@@ -15,9 +16,10 @@ template ProofOfPassport(n, k) {
|
||||
signal input address;
|
||||
|
||||
// Verify passport
|
||||
component PV = PassportVerifier(n, k);
|
||||
component PV = PassportVerifier(n, k, max_datahashes_bytes);
|
||||
PV.mrz <== mrz;
|
||||
PV.dataHashes <== dataHashes;
|
||||
PV.datahashes_padded_length <== datahashes_padded_length;
|
||||
PV.eContentBytes <== eContentBytes;
|
||||
PV.pubkey <== pubkey;
|
||||
PV.signature <== signature;
|
||||
@@ -45,7 +47,7 @@ template ProofOfPassport(n, k) {
|
||||
}
|
||||
}
|
||||
|
||||
component main { public [ address ] } = ProofOfPassport(64, 32);
|
||||
component main { public [ address ] } = ProofOfPassport(64, 32, 320);
|
||||
|
||||
// Us:
|
||||
// 11 + 1 + 3 + 1
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
"@types/node": "^20.6.3",
|
||||
"@types/node-forge": "^1.3.5",
|
||||
"@zk-email/circuits": "^3.2.2",
|
||||
"@zk-email/helpers": "^3.1.3",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"circom_tester": "^0.0.20",
|
||||
"circomlib": "^2.0.5",
|
||||
"js-sha256": "^0.10.1",
|
||||
"node-forge": "^1.3.1",
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Record the start time
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
# Check if the first argument is "app-only"
|
||||
if [ "$1" == "app-only" ]; then
|
||||
echo "Building only for the app"
|
||||
@@ -39,4 +42,9 @@ yarn snarkjs zkey export verificationkey build/proof_of_passport_final.zkey buil
|
||||
|
||||
yarn snarkjs zkey export solidityverifier build/proof_of_passport_final.zkey build/Verifier.sol
|
||||
cp build/Verifier.sol ../contracts/contracts/Verifier.sol
|
||||
echo "copied Verifier.sol to contracts"
|
||||
echo "copied Verifier.sol to contracts"
|
||||
|
||||
# Calculate and print the time taken by the whole script
|
||||
END_TIME=$(date +%s)
|
||||
ELAPSED_TIME=$(($END_TIME - $START_TIME))
|
||||
echo "Build completed in $ELAPSED_TIME seconds"
|
||||
@@ -1,12 +1,14 @@
|
||||
import { describe } from 'mocha'
|
||||
import chai, { assert, expect } from 'chai'
|
||||
import chaiAsPromised from 'chai-as-promised'
|
||||
import { hash, toUnsignedByte, arraysAreEqual, bytesToBigDecimal, formatAndConcatenateDataHashes, formatMrz, splitToWords } from '../../common/src/utils/utils'
|
||||
import { hash, toUnsignedByte, arraysAreEqual, bytesToBigDecimal, formatMrz, splitToWords } from '../../common/src/utils/utils'
|
||||
import { groth16 } from 'snarkjs'
|
||||
import { DataHash } from '../../common/src/utils/types'
|
||||
import { getPassportData } from '../../common/src/utils/passportData'
|
||||
import { attributeToPosition } from '../../common/src/constants/constants'
|
||||
import { MAX_DATAHASHES_LEN, attributeToPosition } from '../../common/src/constants/constants'
|
||||
import { sha256Pad } from '@zk-email/helpers'
|
||||
import path from "path";
|
||||
const fs = require('fs');
|
||||
const wasm_tester = require("circom_tester").wasm;
|
||||
|
||||
chai.use(chaiAsPromised)
|
||||
|
||||
@@ -21,13 +23,9 @@ describe('Circuit tests', function () {
|
||||
const passportData = getPassportData();
|
||||
|
||||
const formattedMrz = formatMrz(passportData.mrz);
|
||||
const mrzHash = hash(formatMrz(passportData.mrz));
|
||||
const concatenatedDataHashes = formatAndConcatenateDataHashes(
|
||||
mrzHash,
|
||||
passportData.dataGroupHashes as DataHash[],
|
||||
);
|
||||
|
||||
const concatenatedDataHashesHashDigest = hash(concatenatedDataHashes);
|
||||
|
||||
const concatenatedDataHashesHashDigest = hash(passportData.dataGroupHashes);
|
||||
console.log('concatenatedDataHashesHashDigest', concatenatedDataHashesHashDigest);
|
||||
|
||||
assert(
|
||||
arraysAreEqual(passportData.eContent.slice(72, 72 + 32), concatenatedDataHashesHashDigest),
|
||||
@@ -36,10 +34,16 @@ describe('Circuit tests', function () {
|
||||
|
||||
const reveal_bitmap = Array(88).fill('1');
|
||||
|
||||
const [messagePadded, messagePaddedLen] = sha256Pad(
|
||||
new Uint8Array(passportData.dataGroupHashes),
|
||||
MAX_DATAHASHES_LEN
|
||||
);
|
||||
|
||||
inputs = {
|
||||
mrz: formattedMrz.map(byte => String(byte)),
|
||||
reveal_bitmap: reveal_bitmap.map(byte => String(byte)),
|
||||
dataHashes: concatenatedDataHashes.map(toUnsignedByte).map(byte => String(byte)),
|
||||
dataHashes: Array.from(messagePadded).map((x) => x.toString()),
|
||||
datahashes_padded_length: messagePaddedLen.toString(),
|
||||
eContentBytes: passportData.eContent.map(toUnsignedByte).map(byte => String(byte)),
|
||||
pubkey: splitToWords(
|
||||
BigInt(passportData.pubKey.modulus),
|
||||
@@ -53,7 +57,8 @@ describe('Circuit tests', function () {
|
||||
),
|
||||
address: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // sample address
|
||||
}
|
||||
|
||||
|
||||
console.log('inputs', inputs);
|
||||
})
|
||||
|
||||
describe('Proof', function() {
|
||||
@@ -210,6 +215,19 @@ describe('Circuit tests', function () {
|
||||
|
||||
|
||||
})
|
||||
|
||||
// use these tests with .only to check changes without rebuilding the zkey
|
||||
describe('Circom tester tests', function() {
|
||||
it('should prove and verify with valid inputs', async function () {
|
||||
const circuit = await wasm_tester(
|
||||
path.join(__dirname, `../circuits/proof_of_passport.circom`),
|
||||
{ include: ["node_modules"] },
|
||||
);
|
||||
const w = await circuit.calculateWitness(inputs);
|
||||
await circuit.checkConstraints(w);
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ export const attributeToPosition: { [key: string]: number[] } = {
|
||||
expiry_date: [65, 70],
|
||||
};
|
||||
|
||||
export const MAX_DATAHASHES_LEN = 320; // max formatted and concatenated datagroup hashes length in bytes
|
||||
|
||||
export const countryCodes = {
|
||||
"AFG": "Afghanistan",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DataHash, PassportData } from "./types";
|
||||
import { PassportData } from "./types";
|
||||
import { hash, assembleEContent, formatAndConcatenateDataHashes, formatMrz, hexToDecimal } from "./utils";
|
||||
import * as forge from 'node-forge';
|
||||
const fs = require('fs');
|
||||
@@ -38,7 +38,7 @@ export function genSampleData(): PassportData {
|
||||
sampleDataHashes.unshift([1, mrzHash]);
|
||||
const concatenatedDataHashes = formatAndConcatenateDataHashes(
|
||||
mrzHash,
|
||||
sampleDataHashes as DataHash[],
|
||||
sampleDataHashes as [number, number[]][],
|
||||
);
|
||||
const eContent = assembleEContent(
|
||||
hash(concatenatedDataHashes),
|
||||
@@ -55,24 +55,16 @@ export function genSampleData(): PassportData {
|
||||
const signature = privKey.sign(md)
|
||||
const signatureBytes = Array.from(signature, (c: string) => c.charCodeAt(0));
|
||||
|
||||
// Signature verification
|
||||
// const hashOfEContent = md.digest().getBytes();
|
||||
// const publicKey = rsa.setPublicKey(
|
||||
// new forge.jsbn.BigInteger(modulus, 16),
|
||||
// new forge.jsbn.BigInteger("10001", 16),
|
||||
// );
|
||||
// const valid = publicKey.verify(hashOfEContent, signature);
|
||||
// console.log('valid ?', valid)
|
||||
|
||||
return {
|
||||
mrz: sampleMRZ,
|
||||
signatureAlgorithm: 'SHA256withRSA', // sha256WithRSAEncryption
|
||||
pubKey: {
|
||||
modulus: hexToDecimal(modulus),
|
||||
},
|
||||
dataGroupHashes: sampleDataHashes as DataHash[],
|
||||
dataGroupHashes: concatenatedDataHashes,
|
||||
eContent: eContent,
|
||||
encryptedDigest: signatureBytes,
|
||||
photoBase64: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3" // meaningless for now
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { PassportData } from "./types";
|
||||
|
||||
|
||||
// export const samplePassportData = {
|
||||
// "mrz":"P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02",
|
||||
// "signatureAlgorithm":"SHA256withRSA",
|
||||
@@ -10,10 +9,58 @@ import { PassportData } from "./types";
|
||||
// "encryptedDigest":[35,76,28,227,212,141,111,134,230,196,96,116,211,137,66,36,193,89,118,85,247,107,239,228,229,86,134,71,247,88,48,232,173,172,80,223,44,146,97,248,103,82,33,114,87,80,255,13,24,129,48,30,162,233,32,107,108,229,199,248,215,187,5,72,112,185,114,80,178,117,203,63,6,231,104,72,89,158,77,232,82,147,35,57,119,151,60,235,210,216,86,76,164,16,203,111,60,20,0,100,174,175,95,8,150,248,65,207,55,251,206,141,26,30,49,218,160,56,92,45,212,121,61,231,174,175,171,234,83,17,225,249,52,208,223,8,234,208,152,168,146,187,0,80,25,235,145,196,157,113,38,65,71,214,143,36,82,212,45,0,242,120,73,54,24,115,24,157,188,79,59,60,202,74,129,47,245,202,141,15,135,7,34,18,56,24,85,173,125,205,71,127,103,236,77,176,100,35,59,179,123,84,158,84,195,113,98,202,218,2,1,170,194,243,245,174,205,102,28,118,156,57,106,37,244,45,174,157,202,217,38,179,126,94,205,74,100,64,225,183,145,157,148,213,45,228,170,122,190,239,11,135,24,239,17,252]
|
||||
// } as PassportData // not working for some reason
|
||||
export const samplePassportData = {
|
||||
"mrz":"P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02",
|
||||
"signatureAlgorithm":"SHA256withRSA",
|
||||
"pubKey":{"modulus":"27753994424842443894245786782525308860959074811630074275687092737154570193632490725867032155150260554771168206321835563490551248035290893473617891334580992862631549002795628558031117970107680315966672387663922543753771000203286710765623272481585597066810453899915515725100524233057337421264922943787074825558632263475983266815680559554396939901695379704841007360145443136768496914184384265135937789216999239019764915126071941382094849289770921106079335274789472186657871647693785381678061690538186504807895527639676843719555029569743949997938238439702614424217784475162038335863063315103644827846898314629359021121163"},
|
||||
"dataGroupHashes":[[1,[-80,-33,31,-123,108,84,-98,102,70,11,-91,-81,-60,12,-55,-126,25,-125,46,125,-100,-62,28,23,55,-123,-99,-92,-121,-120,-36,78]],[2,[-66,82,-76,-21,-34,33,79,50,-104,-120,-114,35,116,-32,6,-14,-100,-115,-128,-8,10,61,98,86,-8,45,-49,-46,90,-24,-81,38]],[3,[0,-62,104,108,-19,-10,97,-26,116,-58,69,110,26,87,17,89,110,-57,108,-6,36,21,39,87,110,102,-6,-43,-82,-125,-85,-82]],[11,[-120,-101,87,-112,111,15,-104,127,85,25,-102,81,20,58,51,75,-63,116,-22,0,60,30,29,30,-73,-115,72,-9,-1,-53,100,124]],[12,[41,-22,106,78,31,11,114,-119,-19,17,92,71,-122,47,62,78,-67,-23,-55,-42,53,4,47,-67,-55,-123,6,121,34,-125,64,-114]],[13,[91,-34,-46,-63,62,-34,104,82,36,41,-118,-3,70,15,-108,-48,-100,45,105,-85,-15,-61,-71,43,-39,-94,-110,-55,-34,89,-18,38]],[14,[76,123,-40,13,51,-29,72,-11,59,-63,-18,-90,103,49,23,-92,-85,-68,-62,-59,-100,-69,-7,28,-58,95,69,15,-74,56,54,38]]],
|
||||
"eContent":[49,102,48,21,6,9,42,-122,72,-122,-9,13,1,9,3,49,8,6,6,103,-127,8,1,1,1,48,28,6,9,42,-122,72,-122,-9,13,1,9,5,49,15,23,13,49,57,49,50,49,54,49,55,50,50,51,56,90,48,47,6,9,42,-122,72,-122,-9,13,1,9,4,49,34,4,32,32,85,108,-82,127,112,-78,-74,8,43,-122,123,-64,-45,-125,66,-72,-16,-44,-75,-16,-76,106,-61,24,117,54,-127,19,10,-6,53],
|
||||
"encryptedDigest":[75,38,146,115,39,182,117,54,54,210,123,175,120,2,192,161,4,95,215,96,181,238,178,2,228,31,135,28,151,187,17,28,127,71,108,224,207,180,75,237,108,85,103,115,141,94,95,117,167,89,69,182,24,100,154,168,188,176,221,182,102,174,113,187,207,82,146,21,124,207,87,239,148,209,129,187,247,245,50,37,208,152,209,204,42,219,163,63,138,79,73,229,179,58,208,232,48,43,203,122,160,37,19,213,231,179,165,204,124,143,157,198,110,230,138,9,115,93,85,94,12,120,44,206,93,27,52,240,142,103,10,199,221,189,229,43,157,129,187,187,248,12,219,186,145,147,226,177,111,180,87,107,27,222,110,92,246,176,123,17,201,118,4,217,246,248,15,22,255,75,42,101,189,203,22,253,197,91,227,187,206,2,106,14,154,222,145,202,15,106,237,158,254,79,244,234,118,5,245,212,45,45,217,170,144,93,44,129,190,180,33,13,123,120,145,100,157,198,178,177,197,93,2,62,2,49,197,23,198,150,249,19,118,239,22,211,116,205,101,141,250,21,19,229,26,201,241,226,109,249,221,9,20,242,21,250]
|
||||
}
|
||||
mrz: "P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02",
|
||||
signatureAlgorithm: "SHA256withRSA",
|
||||
pubKey: {
|
||||
modulus:
|
||||
"25765736223988998667840500778189949868451613342077606460859210922511052625759496119999327689569971597023682649195203990693368929496225818878431536656524613749134155885566243710074017849156387160630116071644605393154527561104329314133650925802529202493002281004186898817134780029845600308376449076243160628443612875871696451909631444284612538876146775788454905886375392424559872753930863026490112290338742311706592933371007008127621682785088607674884944461624900996663751897866140822800320086882377049066596330978938181261694513943840546157351331784368336520946815362357363027160374987439808774582633894814729403608773",
|
||||
},
|
||||
dataGroupHashes: [
|
||||
48, -126, 1, 37, 2, 1, 0, 48, 11, 6, 9, 96, -122, 72, 1, 101, 3, 4, 2, 1,
|
||||
48, -126, 1, 17, 48, 37, 2, 1, 1, 4, 32, -80, -33, 31, -123, 108, 84, -98,
|
||||
102, 70, 11, -91, -81, -60, 12, -55, -126, 25, -125, 46, 125, -100, -62, 28,
|
||||
23, 55, -123, -99, -92, -121, -120, -36, 78, 48, 37, 2, 1, 2, 4, 32, -66,
|
||||
82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -100,
|
||||
-115, -128, -8, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38, 48, 37,
|
||||
2, 1, 3, 4, 32, 0, -62, 104, 108, -19, -10, 97, -26, 116, -58, 69, 110, 26,
|
||||
87, 17, 89, 110, -57, 108, -6, 36, 21, 39, 87, 110, 102, -6, -43, -82, -125,
|
||||
-85, -82, 48, 37, 2, 1, 11, 4, 32, -120, -101, 87, -112, 111, 15, -104, 127,
|
||||
85, 25, -102, 81, 20, 58, 51, 75, -63, 116, -22, 0, 60, 30, 29, 30, -73,
|
||||
-115, 72, -9, -1, -53, 100, 124, 48, 37, 2, 1, 12, 4, 32, 41, -22, 106, 78,
|
||||
31, 11, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, -23, -55, -42,
|
||||
53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114, 48, 37, 2, 1, 13, 4,
|
||||
32, 91, -34, -46, -63, 62, -34, 104, 82, 36, 41, -118, -3, 70, 15, -108,
|
||||
-48, -100, 45, 105, -85, -15, -61, -71, 43, -39, -94, -110, -55, -34, 89,
|
||||
-18, 38, 48, 37, 2, 1, 14, 4, 32, 76, 123, -40, 13, 51, -29, 72, -11, 59,
|
||||
-63, -18, -90, 103, 49, 23, -92, -85, -68, -62, -59, -100, -69, -7, 28, -58,
|
||||
95, 69, 15, -74, 56, 54, 38,
|
||||
],
|
||||
eContent: [
|
||||
49, 102, 48, 21, 6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 3, 49, 8, 6, 6,
|
||||
103, -127, 8, 1, 1, 1, 48, 28, 6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 5,
|
||||
49, 15, 23, 13, 49, 57, 49, 50, 49, 54, 49, 55, 50, 50, 51, 56, 90, 48, 47,
|
||||
6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 4, 49, 34, 4, 32, 32, 85, 108, -82,
|
||||
127, 112, -78, -74, 8, 43, -122, 123, -64, -45, -125, 66, -72, -16, -44,
|
||||
-75, -16, -76, 106, -61, 24, 117, 54, -127, 19, 10, -6, 53,
|
||||
],
|
||||
encryptedDigest: [
|
||||
106, 37, 43, 211, 248, 15, 89, 233, 214, 213, 175, 251, 124, 21, 199, 184,
|
||||
123, 40, 130, 167, 156, 177, 103, 237, 234, 71, 198, 47, 32, 189, 212, 157,
|
||||
238, 88, 183, 46, 152, 216, 89, 160, 64, 159, 193, 189, 45, 222, 64, 23,
|
||||
222, 28, 189, 2, 56, 82, 141, 104, 191, 65, 99, 38, 124, 95, 53, 149, 133,
|
||||
202, 22, 203, 65, 44, 153, 208, 10, 62, 59, 5, 238, 60, 112, 118, 208, 114,
|
||||
230, 203, 17, 118, 114, 78, 136, 244, 243, 219, 138, 251, 243, 28, 168, 217,
|
||||
251, 147, 93, 114, 8, 3, 63, 79, 114, 14, 64, 173, 90, 233, 92, 91, 156,
|
||||
167, 59, 68, 158, 136, 153, 38, 134, 128, 209, 231, 20, 16, 35, 241, 186,
|
||||
186, 185, 40, 68, 250, 185, 36, 239, 195, 27, 234, 233, 38, 237, 167, 97,
|
||||
107, 255, 187, 118, 247, 231, 233, 234, 56, 182, 181, 237, 210, 20, 185, 11,
|
||||
0, 5, 158, 197, 141, 200, 70, 40, 70, 87, 92, 227, 63, 144, 229, 45, 136,
|
||||
29, 239, 47, 193, 0, 184, 97, 161, 239, 105, 87, 124, 55, 54, 208, 68, 161,
|
||||
152, 108, 4, 32, 255, 210, 159, 6, 10, 64, 96, 19, 183, 93, 149, 212, 178,
|
||||
185, 135, 208, 62, 139, 42, 241, 210, 124, 164, 222, 172, 136, 16, 88, 99,
|
||||
59, 100, 114, 123, 119, 86, 20, 190, 107, 152, 106, 244, 223, 112, 83, 110,
|
||||
215, 104, 183, 109, 43, 19, 159, 165, 105, 25,
|
||||
],
|
||||
photoBase64:
|
||||
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAIQAABtbnRyUkdCI",
|
||||
};
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
export type DataHash = [number, number[]];
|
||||
|
||||
export type PassportData = {
|
||||
mrz: string;
|
||||
signatureAlgorithm: string;
|
||||
pubKey: {modulus?: string, curveName?: string, publicKeyQ?: string};
|
||||
dataGroupHashes: DataHash[] | number[];
|
||||
dataGroupHashes: number[];
|
||||
eContent: number[];
|
||||
encryptedDigest: number[];
|
||||
photoBase64: string;
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
import { DataHash } from './types';
|
||||
import {sha256} from 'js-sha256';
|
||||
|
||||
export function dataHashesObjToArray(dataHashes: {
|
||||
[key: string]: number[];
|
||||
}): DataHash[] {
|
||||
return Object.keys(dataHashes)
|
||||
.map(key => {
|
||||
const dataHash = dataHashes[key as keyof typeof dataHashes];
|
||||
return [Number(key), dataHash];
|
||||
})
|
||||
.sort((a, b) => (a[0] as number) - (b[0] as number)) as DataHash[];
|
||||
}
|
||||
|
||||
export function formatMrz(mrz: string) {
|
||||
const mrzCharcodes = [...mrz].map(char => char.charCodeAt(0));
|
||||
|
||||
@@ -49,7 +37,7 @@ export function parsePubKeyString(pubKeyString: string) {
|
||||
|
||||
export function formatAndConcatenateDataHashes(
|
||||
mrzHash: number[],
|
||||
dataHashes: DataHash[],
|
||||
dataHashes: [number, number[]][],
|
||||
) {
|
||||
// Let's replace the first array with the MRZ hash
|
||||
dataHashes.shift();
|
||||
@@ -58,13 +46,19 @@ export function formatAndConcatenateDataHashes(
|
||||
|
||||
let concat: number[] = []
|
||||
|
||||
// Starting sequence. Should be the same for everybody, but not sure
|
||||
concat.push(...[
|
||||
const startingSequence = [
|
||||
48, -126, 1, 37, 2, 1, 0, 48, 11, 6, 9, 96, -122, 72, 1, 101, 3, 4, 2, 1,
|
||||
48, -126, 1, 17,
|
||||
])
|
||||
]
|
||||
|
||||
// console.log(`startingSequence`, startingSequence.map(byte => (byte < 0 ? byte + 256 : byte).toString(16).padStart(2, '0')).join(''));
|
||||
|
||||
// Starting sequence. Should be the same for everybody, but not sure
|
||||
concat.push(...startingSequence)
|
||||
|
||||
for(const dataHash of dataHashes) {
|
||||
// console.log(`dataHash ${dataHash[0]}`, dataHash[1].map(byte => (byte < 0 ? byte + 256 : byte).toString(16).padStart(2, '0')).join(''));
|
||||
|
||||
concat.push(...[48, 37, 2, 1, dataHash[0], 4, 32, ...dataHash[1]])
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user