From ba597c89272262ac27302a8a5a21da7e090bdb2f Mon Sep 17 00:00:00 2001 From: 0xturboblitz Date: Thu, 27 Jul 2023 12:46:42 +0200 Subject: [PATCH 1/5] script.ts verifying from mrz to sig --- app/.gitignore | 4 +- app/package.json | 2 + app/scripts/r&d.ts | 859 ----------------------------------- app/scripts/script.ts | 407 ++++++----------- app/scripts/script2.ts | 151 ------ app/scripts/script3_photo.ts | 91 ---- app/scripts/utils.ts | 14 + app/yarn.lock | 12 + 8 files changed, 169 insertions(+), 1371 deletions(-) delete mode 100644 app/scripts/r&d.ts delete mode 100644 app/scripts/script2.ts delete mode 100644 app/scripts/script3_photo.ts create mode 100644 app/scripts/utils.ts diff --git a/app/.gitignore b/app/.gitignore index e2209bbae..06a2b148d 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -65,4 +65,6 @@ yarn-error.log # testing /coverage -.env \ No newline at end of file +.env +/scripts/env.ts +/scripts/retd.ts \ No newline at end of file diff --git a/app/package.json b/app/package.json index a47d2cc22..83d85617f 100644 --- a/app/package.json +++ b/app/package.json @@ -10,8 +10,10 @@ "test": "jest" }, "dependencies": { + "@types/node-forge": "^1.3.3", "asn1js": "^3.0.5", "buffer": "^6.0.3", + "node-forge": "^1.3.1", "pvutils": "^1.1.3", "react": "18.2.0", "react-native": "0.72.3", diff --git a/app/scripts/r&d.ts b/app/scripts/r&d.ts deleted file mode 100644 index b23e58126..000000000 --- a/app/scripts/r&d.ts +++ /dev/null @@ -1,859 +0,0 @@ -import * as crypto from 'crypto'; - -// On a la donnée de base : -const dg1File = { - length: 91, - mrzInfo: { - compositeCheckDigit: '2', - dateOfBirth: '000719', - dateOfBirthCheckDigit: '1', - dateOfExpiry: '291209', - dateOfExpiryCheckDigit: '5', - documentCode: 'P', - documentNumber: '19HA34828', - documentNumberCheckDigit: '4', - documentType: 3, - gender: 'MALE', - issuingState: 'FRA', - nationality: 'FRA', - optionalData1: '<<<<<<<<<<<<<<0', - primaryIdentifier: 'TAVERNIER', - secondaryIdentifier: 'FLORENT char.charCodeAt(0)); - -console.log('mrzCharcodes:', mrzCharcodes); - -mrzCharcodes.unshift(88); // the length of the mrz data -mrzCharcodes.unshift(95, 31); // the MRZ_INFO_TAG -mrzCharcodes.unshift(91); // the new length of the whole array -mrzCharcodes.unshift(97); // the tag for DG1 - -console.log('mrzCharcodes with tags:', mrzCharcodes); - -const hash = crypto.createHash('sha256'); -hash.update(Buffer.from(mrzCharcodes)); -const dataHash = hash.digest('hex'); - -console.log('dataHash:', dataHash); -// C'est bien dataHashes["1"] - -const dataHashes = { - '1': [ - 99, 19, -77, -51, 55, 104, 45, -42, -123, 101, -23, -79, -126, 1, 37, 89, - 125, -27, -117, 34, -124, -110, 28, 116, -8, -70, 63, -61, 96, -105, 26, - -41, - ], - '2': [ - 63, -22, 106, 78, 31, 16, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, - -23, -55, -43, 53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114, - ], - '3': [ - -120, -101, 87, -112, 121, 15, -104, 127, 85, 25, -102, 80, 20, 58, 51, 75, - -63, 116, -22, 0, 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124, - ], - '11': [ - 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, - ], - '12': [ - -66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, - -100, -115, -128, -9, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38, - ], - '13': [ - 91, -34, -46, -63, 63, -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, 52, -29, 72, -11, 59, -63, -18, -90, 103, 49, 24, -92, - -85, -68, -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38, - ], -}; - -const dataHashesAsArray = [ - [ - 99, 19, -77, -51, 55, 104, 45, -42, -123, 101, -23, -79, -126, 1, 37, 89, - 125, -27, -117, 34, -124, -110, 28, 116, -8, -70, 63, -61, 96, -105, 26, - -41, - ], - [ - 63, -22, 106, 78, 31, 16, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, - -23, -55, -43, 53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114, - ], - [ - -120, -101, 87, -112, 121, 15, -104, 127, 85, 25, -102, 80, 20, 58, 51, 75, - -63, 116, -22, 0, 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124, - ], - [ - 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, - ], - [ - -66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, - -100, -115, -128, -9, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38, - ], - [ - 91, -34, -46, -63, 63, -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, - ], - [ - 76, 123, -40, 13, 52, -29, 72, -11, 59, -63, -18, -90, 103, 49, 24, -92, - -85, -68, -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38, - ], -]; - -function concatenateHashes(hashes: Buffer[]): Buffer { - return Buffer.concat(hashes); -} -function hashData(data: Buffer): string { - const hash = crypto.createHash('sha256'); - hash.update(data); - // return new Uint8Array(hash.digest().buffer); - return hash.digest('hex'); -} - -console.log( - 'concatenateHashes(dataHashes) hash:', - hashData(concatenateHashes(dataHashesAsArray.map(hash => Buffer.from(hash)))), -); - -// const concat = [ -// 99, 19, -77, -51, 55, 104, 45, -42, -123, 101, -23, -79, -126, 1, 37, 89, 125, -// -27, -117, 34, -124, -110, 28, 116, -8, -70, 63, -61, 96, -105, 26, -41, 63, -// -22, 106, 78, 31, 16, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, -23, -// -55, -43, 53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114, -120, -101, -// 87, -112, 121, 15, -104, 127, 85, 25, -102, 80, 20, 58, 51, 75, -63, 116, -22, -// 0, 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124, 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, -66, 82, -76, -21, -34, -// 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -100, -115, -128, -9, 10, -// 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38, 91, -34, -46, -63, 63, -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, 76, 123, -40, 13, 52, -29, 72, -// -11, 59, -63, -18, -90, 103, 49, 24, -92, -85, -68, -62, -59, -100, -69, -7, -// 28, -58, 95, 69, 15, -74, 56, 54, 38, -// ]; - -// const concatHash = crypto.createHash('sha256'); -// concatHash.update(Buffer.from(concat)); -// const concatHashBytes = new Uint8Array(concatHash.digest().buffer); - -// console.log('concatHashBytes:', concatHashBytes); - -const messageDigest = [ - -80, 96, 59, -43, -125, 82, 89, -8, 105, 125, 37, -79, -98, -94, -119, 43, 13, - 39, 115, 6, 59, -27, 81, 110, 49, 75, -1, -72, -101, 73, 116, 86, -]; - -// console.log('messageDigest:', messageDigest); - -// Convert signed bytes to unsigned -const unsignedBytes = messageDigest.map(b => (b < 0 ? b + 256 : b)); - -// Convert to a Buffer, then to hex -const messageDigestHex = Buffer.from(unsignedBytes).toString('hex'); - -console.log('messageDigest:', messageDigestHex); - -const eContent = - '3166301506092a864886f70d01090331080606678108010101301c06092a864886f70d010905310f170d3139313231363137323233385a302f06092a864886f70d01090431220420b0603bd5835259f8697d25b19ea2892b0d2773063be5516e314bffb89b497456'; - -// function hexToBytes(hex: string) { -// let bytes = new Uint8Array(Math.ceil(hex.length / 2)); -// for (let i = 0; i < bytes.length; i++) { -// bytes[i] = parseInt(hex.substr(i * 2, 2), 16); -// } -// return bytes; -// } - -// console.log('hexToBytes(eContent):', hexToBytes(eContent)); - -// const eContentUTF8 = Buffer.from(eContent, 'hex').toString('ascii'); -// console.log(eContentUTF8); - -// 49 : TAG -// 102 : LENGTH -// 48... : sequence -// 49, 102, 48, 21, 6, 9, 42, 134, 72, 134, 247, 13, -// 1, 9, 3, 49, 8, 6, 6, 103, 129, 8, 1, 1, -// 1, 48, 28, 6, 9, 42, 134, 72, 134, 247, 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, -// 134, 72, 134, 247, 13, 1, 9, 4, 49, 34, 4, 32, -// 176, 96, 59, 213, 131, 82, 89, 248, 105, 125, 37, 177, -// 158, 162, 137, 43, 13, 39, 115, 6, 59, 229, 81, 110, -// 49, 75, 255, 184, 155, 73, 116, 86 - -// "1.2.840.113549.1.9.4" - -// TAG, LGT, RFC_3369 TAG..., TAG, SEQUENCE... -// RFC_3369_CONTENT_TYPE_OID 48, 21, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 3, | 49, 8, 6, 6, 103, 129, 8, 1, 1, 1, -// signing-time 48, 28, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 5, | 49, 15, 23, 13, 49, 57, 49, 50, 49, 54, 49, 55, 50, 50, 51, 56, 90, -// RFC_3369_MESSAGE_DIGEST_OID 48, 47, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 4, | 49, 34, 4, 32, | 176, 96, 59, 213, 131, 82, 89, 248, 105, 125, 37, 177, 158, 162, 137, 43, 13, 39, 115, 6, 59, 229, 81, 110, 49, 75, 255, 184, 155, 73, 116, 86 - -// Donc je veux arriver au hash suivant pour les dataHashes concaténés: -// 34, 4, 32, | 176, 96, 59, 213, 131, 82, 89, 248, 105, 125, 37, 177, 158, 162, 137, 43, 13, 39, 115, 6, 59, 229, 81, 110, 49, 75, 255, 184, 155, 73, 116, 86 - -// const dataHashes = { -// '1': [ -// 99, 19, -77, -51, 55, 104, 45, -42, -123, 101, -23, -79, -126, 1, 37, 89, -// 125, -27, -117, 34, -124, -110, 28, 116, -8, -70, 63, -61, 96, -105, 26, -// -41, -// ], -// '2': [ -// 63, -22, 106, 78, 31, 16, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, -// -23, -55, -43, 53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114, -// ], -// '3': [ -// -120, -101, 87, -112, 121, 15, -104, 127, 85, 25, -102, 80, 20, 58, 51, 75, -// -63, 116, -22, 0, 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124, -// ], -// '11': [ -// 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, -// ], -// '12': [ -// -66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -// -100, -115, -128, -9, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38, -// ], -// '13': [ -// 91, -34, -46, -63, 63, -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, 52, -29, 72, -11, 59, -63, -18, -90, 103, 49, 24, -92, -// -85, -68, -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38, -// ], -// }; - -// ContentInfo encapContentInfo = signedData.getEncapContentInfo(); -// DEROctetString eContent = (DEROctetString)encapContentInfo.getContent(); - -const signedData = { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [42, -122, 72, -122, -9, 13, 1, 9, 3], - identifier: '1.2.840.113549.1.9.3', - }, - { - bodyLength: -1, - elements: [ - {body: [103, -127, 8, 1, 1, 1], identifier: '2.23.136.1.1.1'}, - ], - isSorted: true, - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [42, -122, 72, -122, -9, 13, 1, 9, 5], - identifier: '1.2.840.113549.1.9.5', - }, - { - bodyLength: -1, - elements: [ - {time: [49, 57, 49, 50, 49, 54, 49, 55, 50, 50, 51, 56, 90]}, - ], - isSorted: true, - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [42, -122, 72, -122, -9, 13, 1, 9, 4], - identifier: '1.2.840.113549.1.9.4', - }, - { - bodyLength: -1, - elements: [ - { - string: [ - -80, 96, 59, -43, -125, 82, 89, -8, 105, 125, 37, -79, -98, -94, - -119, 43, 13, 39, 115, 6, 59, -27, 81, 110, 49, 75, -1, -72, - -101, 73, 116, 86, - ], - }, - ], - isSorted: true, - }, - ], - }, - ], - isSorted: false, -}; - -// Convert the byte arrays into hex strings, and store them in an array in the correct order -const hashHexStrings = Object.keys(dataHashes) - .sort() - .map(key => { - const byteArray = dataHashes[key as keyof typeof dataHashes]; - // Convert signed bytes to unsigned, then to hex string - const hexString = byteArray - .map(b => (b < 0 ? b + 256 : b)) - .map(b => b.toString(16).padStart(2, '0')) - .join(''); - return hexString; - }); - -// Concatenate the hex strings -const concatenatedHashesHex = hashHexStrings.join(''); - -// Hash the concatenated hashes to get the message digest in hex -const messageDigestHex2 = hashDataHex(concatenatedHashesHex); - -console.log('messageDigestHex2:', messageDigestHex2); - -// Function to hash hex data -function hashDataHex(dataHex: string): string { - const hash = crypto.createHash('sha256'); - hash.update(dataHex, 'hex'); - return hash.digest('hex'); -} - -// SignedAttributesSet: -// [1.2.840.113549.1.9.3, [2.23.136.1.1.1]], -// [1.2.840.113549.1.9.5, [191216172238Z]] -// [1.2.840.113549.1.9.4, [#b0603bd5835259f8697d25b19ea2892b0d2773063be5516e314bffb89b497456]] - -// ContentInfo contentInfo = signedData.getEncapContentInfo(); -// et contentBytes -// C'est le champ contentInfo de signedData -const contentBytes = [ - 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, 99, 19, -77, -51, 55, 104, 45, -42, -123, - 101, -23, -79, -126, 1, 37, 89, 125, -27, -117, 34, -124, -110, 28, 116, -8, - -70, 63, -61, 96, -105, 26, -41, 48, 37, 2, 1, 2, 4, 32, 63, -22, 106, 78, 31, - 16, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, -23, -55, -43, 53, 4, - 47, -67, -55, -123, 6, 121, 34, -125, 64, -114, 48, 37, 2, 1, 3, 4, 32, -120, - -101, 87, -112, 121, 15, -104, 127, 85, 25, -102, 80, 20, 58, 51, 75, -63, - 116, -22, 0, 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124, 48, 37, 2, - 1, 11, 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, 12, 4, 32, -66, 82, -76, -21, -34, 33, 79, 50, -104, -120, - -114, 35, 116, -32, 6, -14, -100, -115, -128, -9, 10, 61, 98, 86, -8, 45, -49, - -46, 90, -24, -81, 38, 48, 37, 2, 1, 13, 4, 32, 91, -34, -46, -63, 63, -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, 52, -29, 72, -11, 59, -63, -18, -90, 103, 49, 24, -92, -85, -68, - -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38, -]; - -// let's hash contentBytes -const contentBytesHash = crypto.createHash('sha256'); -contentBytesHash.update(Buffer.from(contentBytes)); -const concatHashBytes = new Uint8Array(contentBytesHash.digest().buffer); -console.log('concatHashBytes', concatHashBytes); -// AttributesBytes : ça c'est précisément le eContent entier -// [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, -80, 96, 59, -43, -125, 82, 89, -8, 105, 125, 37, -79, -98, -94, -119, 43, 13, 39, 115, 6, 59, -27, 81, 110, 49, 75, -1, -72, -101, 73, 116, 86] - -// storedDigestedContent = computedDigestedContent = ça : -// [-80, 96, 59, -43, -125, 82, 89, -8, 105, 125, 37, -79, -98, -94, -119, 43, 13, 39, 115, 6, 59, -27, 81, 110, 49, 75, -1, -72, -101, 73, 116, 86] - -// Premier mystère résolu : le truc est bien le contentBytes hashé - -// 48 : SEQUENCE -// -126, 1, 37 : LENGTH (293 bytes long (1*256 + 37 = 293)) -// 2, 1, 0 : VERSION of the ASN.1 structure, which is 0. - -// 48 : SEQUENCE -// 11 : LENGTH (11 bytes long) -// 6 : ASN.1 tag for OBJECT IDENTIFIER, or OID. -// 9 : the OID is 9 bytes long. -// 96, -122, 72, 1, 101, 3, 4, 2, 1 : the OID for SHA-256 - -// 48 : SEQUENCE -// -126, 1, 17, : LENGTH (273 bytes long) - -// DATAHASHES : -// 48, 37, 2, 1, 1, 4, 32, -// 99, 19, -77, -51, 55, 104, 45, -42, -123, 101, -23, -79, -126, 1, 37, 89, 125, -27, -117, 34, -124, -110, 28, 116, -8, -70, 63, -61, 96, -105, 26, -41, - -// 48, 37, 2, 1, 2, 4, 32, -// 63, -22, 106, 78, 31, 16, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, -23, -55, -43, 53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114, - -// 48, 37, 2, 1, 3, 4, 32, -// -120, -101, 87, -112, 121, 15, -104, 127, 85, 25, -102, 80, 20, 58, 51, 75, -63, 116, -22, 0, 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124, - -// 48, 37, 2, 1, 11, 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, 12, 4, 32, -// -66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -100, -115, -128, -9, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38, - -// 48, 37, 2, 1, 13, 4, 32, -// 91, -34, -46, -63, 63, -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, 52, -29, 72, -11, 59, -63, -18, -90, 103, 49, 24, -92, -85, -68, -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38, - -const SignedData = { - certificates: { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - explicit: true, - obj: { - bytes: [2], - start: 0, - }, - tagNo: 0, - }, - { - bytes: [ - 17, 33, -111, 26, -11, -11, 51, -30, -25, -93, 97, 37, -92, - 106, -34, -23, 36, 61, - ], - start: 0, - }, - { - bodyLength: -1, - elements: [ - { - body: [42, -122, 72, -122, -9, 13, 1, 1, 11], - identifier: '1.2.840.113549.1.1.11', - }, - {}, - ], - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 4, 6], - identifier: '2.5.4.6', - }, - { - string: [70, 82], - }, - ], - }, - ], - isSorted: true, - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 4, 10], - identifier: '2.5.4.10', - }, - { - string: [71, 111, 117, 118], - }, - ], - }, - ], - isSorted: true, - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 4, 3], - identifier: '2.5.4.3', - }, - { - string: [ - 67, 83, 67, 65, 45, 70, 82, 65, 78, 67, 69, - ], - }, - ], - }, - ], - isSorted: true, - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - time: [49, 57, 49, 49, 48, 53, 49, 52, 50, 57, 48, 55, 90], - }, - { - time: [51, 48, 48, 50, 48, 53, 49, 52, 50, 57, 48, 55, 90], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 4, 6], - identifier: '2.5.4.6', - }, - { - string: [70, 82], - }, - ], - }, - ], - isSorted: true, - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 4, 10], - identifier: '2.5.4.10', - }, - { - string: [71, 111, 117, 118], - }, - ], - }, - ], - isSorted: true, - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 4, 11], - identifier: '2.5.4.11', - }, - { - string: [ - 68, 111, 99, 117, 109, 101, 110, 116, 32, 83, 105, - 103, 110, 101, 114, - ], - }, - ], - }, - ], - isSorted: true, - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 4, 3], - identifier: '2.5.4.3', - }, - { - string: [72, 83, 77, 95, 68, 83, 95, 50], - }, - ], - }, - ], - isSorted: true, - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 4, 5], - identifier: '2.5.4.5', - }, - { - string: [ - 50, 48, 49, 57, 49, 49, 48, 53, 49, 52, 50, 57, - 48, 50, 48, - ], - }, - ], - }, - ], - isSorted: true, - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [42, -122, 72, -122, -9, 13, 1, 1, 1], - identifier: '1.2.840.113549.1.1.1', - }, - {}, - ], - }, - { - data: [ - 48, -126, 1, 10, 2, -126, 1, 1, 0, -33, 17, -70, 6, -41, - -109, 122, 5, -98, -116, -25, -111, 106, -80, -5, 11, 9, - 74, -101, -98, -49, -104, -23, 126, -38, 104, 52, -94, 48, - 117, -14, 3, 0, 114, -93, -57, -122, -113, -123, 4, 90, - -14, -84, -75, -11, -62, -66, -33, 108, 37, 97, 77, -103, - 35, 43, -104, -69, 69, 110, 95, -116, -29, 33, 72, -120, - 47, 34, -127, 83, 122, -57, -86, -128, -28, -51, -73, -98, - 12, -33, 70, 39, -51, 8, -38, 50, -50, 38, 62, -11, 74, - 38, -62, -54, 52, -109, -15, -48, 45, -97, -85, -51, -119, - -107, 32, 88, -53, 0, -123, -6, 53, 107, 19, -7, -30, -52, - 30, -100, -92, -12, 118, 120, -36, 73, 18, -99, 85, 83, - 27, -46, -127, 125, -44, 54, -43, -82, -9, 120, -44, -44, - 57, -46, -42, 89, -80, -49, -99, 88, -18, -1, 67, -50, 44, - -1, 38, -43, -58, 109, 35, 22, 65, 35, -4, -100, 62, 108, - -44, -112, 46, -99, 123, 84, -39, 80, -101, 3, -7, 93, - -21, -4, 63, -79, 94, -9, -76, 88, -84, 100, -94, -58, - -30, 107, -16, 16, 69, 30, -1, 103, -19, -121, -10, -54, - 122, -108, 109, -41, -84, -122, -34, -94, 86, 108, -67, - -55, -86, 14, 60, -70, -83, -97, 94, -44, -74, -120, 108, - -48, -113, 107, -81, 20, -121, -75, -113, 107, -93, 48, - 117, -106, -125, -106, -62, 22, -17, 101, -80, -21, 73, - -58, -105, -124, 100, -36, -34, -103, -7, -87, -95, 2, 3, - 1, 0, 1, - ], - padBits: 0, - }, - ], - }, - { - explicit: true, - obj: { - bodyLength: -1, - elements: [ - { - bodyLength: -1, - elements: [ - { - body: [85, 29, 32], - identifier: '2.5.29.32', - }, - { - string: [ - 48, 55, 48, 53, 6, 10, 42, -127, 122, 1, -127, 31, - 1, 1, 1, 2, 48, 39, 48, 37, 6, 8, 43, 6, 1, 5, 5, 7, - 2, 1, 22, 25, 104, 116, 116, 112, 115, 58, 47, 47, - 97, 110, 116, 115, 46, 103, 111, 117, 118, 46, 102, - 114, 47, 99, 115, 99, 97, - ], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [85, 29, 15], - identifier: '2.5.29.15', - }, - { - value: -1, - }, - { - string: [3, 2, 7, -128], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [85, 29, 16], - identifier: '2.5.29.16', - }, - { - string: [ - 48, 34, -128, 15, 50, 48, 49, 57, 49, 49, 48, 53, - 49, 52, 50, 57, 48, 55, 90, -127, 15, 50, 48, 50, - 48, 48, 50, 48, 53, 49, 52, 50, 57, 48, 55, 90, - ], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [85, 29, 17], - identifier: '2.5.29.17', - }, - { - string: [ - 48, 27, -122, 25, 104, 116, 116, 112, 115, 58, 47, - 47, 97, 110, 116, 115, 46, 103, 111, 117, 118, 46, - 102, 114, 47, 99, 115, 99, 97, - ], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [85, 29, 18], - identifier: '2.5.29.18', - }, - { - string: [ - 48, 45, -122, 25, 104, 116, 116, 112, 115, 58, 47, - 47, 97, 110, 116, 115, 46, 103, 111, 117, 118, 46, - 102, 114, 47, 99, 115, 99, 97, -92, 16, 48, 14, 49, - 12, 48, 10, 6, 3, 85, 4, 7, 19, 3, 70, 82, 65, - ], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [85, 29, 31], - identifier: '2.5.29.31', - }, - { - string: [ - 48, 36, 48, 34, -96, 32, -96, 30, -122, 28, 104, - 116, 116, 112, 58, 47, 47, 97, 110, 116, 115, 46, - 103, 111, 117, 118, 46, 102, 114, 47, 99, 115, 99, - 97, 95, 99, 114, 108, - ], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [103, -127, 8, 1, 1, 6, 2], - identifier: '2.23.136.1.1.6.2', - }, - { - string: [ - 48, 12, 2, 1, 0, 49, 7, 19, 1, 80, 19, 2, 73, 82, - ], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [85, 29, 14], - identifier: '2.5.29.14', - }, - { - string: [ - 4, 20, 66, -31, -84, 81, 17, -85, -80, 4, 76, 116, - -104, -95, 29, -98, -44, 101, -47, 31, 41, -5, - ], - }, - ], - }, - { - bodyLength: -1, - elements: [ - { - body: [85, 29, 35], - identifier: '2.5.29.35', - }, - { - string: [ - 48, 22, -128, 20, 15, -52, 50, 124, -66, 4, -9, 41, - 5, -34, 37, 14, -7, -106, -100, -91, 28, -120, 38, - 124, -33, 27, 100, -92, -22, 107, 90, 76, 46, 98, - -42, -60, -48, -16, -67, 62, 56, -77, -42, -17, 13, - -107, 113, 82, -18, 77, 114, 115, -57, -101, 40, - -15, 85, 120, -40, 17, 123, -81, -49, 114, -81, 27, - -27, 33, -47, -61, 65, -37, -28, 111, -39, 15, -33, - 98, -21, 83, -13, -32, -33, -80, 27, 104, 102, 66, - -11, -103, 28, 12, 7, 117, 90, 95, 29, 54, 122, -28, - -108, -28, -114, 103, -47, -51, -78, -109, -31, 13, - -111, -115, - ], - padBits: 0, - }, - ], - }, - ], - isSorted: true, - }, - certsBer: false, - contentInfo: { - content: { - string: [ - 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, - 99, 19, -77, -51, 55, 104, 45, -42, -123, 101, -23, -79, - -126, 1, 37, 89, 125, -27, -117, 34, -124, -110, 28, 116, - -8, -70, 63, -61, 96, -105, 26, -41, 48, 37, 2, 1, 2, 4, - 32, 63, -22, 106, 78, 31, 16, 114, -119, -19, 17, 92, 71, - -122, 47, 62, 78, -67, -23, -55, -43, 53, 4, 47, -67, -55, - -123, 6, 121, 34, -125, 64, -114, 48, 37, 2, 1, - ], - }, - }, - }, - ], - }, - ], - }, - ], - }, -}; diff --git a/app/scripts/script.ts b/app/scripts/script.ts index 1888232fc..398143241 100644 --- a/app/scripts/script.ts +++ b/app/scripts/script.ts @@ -1,288 +1,157 @@ -// const crypto = require('crypto'); import * as crypto from 'crypto'; +import { + dg1File, + dataHashes, + contentBytes, + eContent, + modulusHex, + exponentHex, + encryptedDigest, +} from './env'; +import {toUnsigned, arraysAreEqual} from './utils'; +import * as forge from 'node-forge'; -const firstName = 'FLORENTHUGUESJEAN'; -const lastName = 'TAVERNIER'; -const gender = 'MALE'; -const issuer = 'FRA'; -const nationality = 'FRA'; -const photo = { - base64: - 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAIQAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMA///////////////////////////////////////////////////////////////////////////////////////bAEMB///////////////////////////////////////////////////////////////////////////////////////AABEIAUAA8AMBIgACEQEDEQH/xAAXAAEBAQEAAAAAAAAAAAAAAAAAAQID/8QAIRABAQABAwQDAQAAAAAAAAAAAAERAhJhMYGh8CFB0VH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/ANmRAXJlFAAAAAAAAAAAEAUQBcmUAXJlAFyIAogCiAKIAqKgCoAoAAACKgKIAAAAAAAAAAAAAAAAAAAqKAgKAigAIADFoN5kZ3MgLupuqANbqu5gB0zBzMg6DE1YbAAAAAAAAAABQQAAFEAAtc7bQW3LIAAAAAAAAALLhAHSVXJqXANhLkAAAAAABQAQFBALcAzqv0wdQAAAAAAAAAAAFBBcICyukuXNZcA2AAAACgIqAAAMar9NuYIAAAAAALhcAyq4XAMmGsAJhcKAmEsaKDCNVkG9N+mnJ0lzAUABUUBFQAAC9HJvV0YAAAFMZBMNyEigAIoKAgoCKigIqKJWHRiiI1prIDqEAAABUAABjV1Zb1MAA1AMNIoAACoCqIAoggAKAAgxW2KCAsB0nQJ0AAAUEBUAGdTC6rmoBG2Z1aBREBcmWcGAayZZUGhAVUyIIZMphcAZXKAKzWkoMrIjpOgKAAACgAIqAxq+mWtXVkFjTMaATKpATItiSAKAKqKKyKgiCpgF5MqmAVKqUEb09HN009AUAAAFAARUBnVPth0vRzoLG2I0AKAiKAigAqKKgAIoCAKAzWmaCRudGI6QAAAAFRQBFARit1kGY0z0aBQBUFAQABUUEAAVFABAGa0n2ISNsxoAAAAFAARUASxQGaLhAFQBUAUBKCjKiKMqKoAAAgDUAgAAAAAKAAigIAAipQQAAAAAEFQFEUUAAAEGmY0AAAAAACgAIqAAAAAyLUABAPkAE+RQEUAFQBQAWKAAAAAAAKAAioAAAADNv0jOfloFEABQEFAQUBAAFlRJfkHQAAAAAAAFQAAAAS3AKl6VjdUttBGpWQGxnKgqoAqACoAAiZAtQAdZ0ipLmKAAAAAAACWyAqZwxdX8QGrq/jAAAAAAAA1KrC5BpEyZBTKZQFQAAAGpq/rIDqrlLY3NQNAAAAxdX8YAAAAAAAAAAAAAAAAAAAAAAAAAFlsdJcuQDsMTV/W5cg4jrsnPvY2Tn3sDkOuyc+9jZOfH4DkOuyc+9jZOfH4DkOuyc+9jZOfewOQ67Jz72Nk597A5DrsnPj8Nk58fgOQ67Jz72Nk597A5DrsnPvY2Tnx+A5DrsnPj8Nk58fgOQ67Jz72Nk597A5DrsnPvY2Tn3sDkOuyc+9jZOfewOQ67Jz4/DZOfH4DkOuyc+Pw2Tn3sDksvy6bJz72Nk597A//Z', - height: 320, - width: 240, -}; -const dg1File = { - length: 91, - mrzInfo: { - compositeCheckDigit: '2', - dateOfBirth: '000719', - dateOfBirthCheckDigit: '1', - dateOfExpiry: '291209', - dateOfExpiryCheckDigit: '5', - documentCode: 'P', - documentNumber: '19HA34828', - documentNumberCheckDigit: '4', - documentType: 3, - gender: 'MALE', - issuingState: 'FRA', - nationality: 'FRA', - optionalData1: '<<<<<<<<<<<<<<0', - primaryIdentifier: 'TAVERNIER', - secondaryIdentifier: 'FLORENT { + const dataHash = dataHashes[key as keyof typeof dataHashes]; + return [Number(key), dataHash]; + }) + .sort((a, b) => (a[0] as number) - (b[0] as number)); + +console.log('dataHashesAsArray:', dataHashesAsArray); + +console.log('mrz: ', mrz); + +const mrzCharcodes = [...mrz].map(char => char.charCodeAt(0)); + +console.log('mrzCharcodes:', mrzCharcodes); + +mrzCharcodes.unshift(88); // the length of the mrz data +mrzCharcodes.unshift(95, 31); // the MRZ_INFO_TAG +mrzCharcodes.unshift(91); // the new length of the whole array +mrzCharcodes.unshift(97); // the tag for DG1 + +console.log('mrzCharcodes with tags:', mrzCharcodes); + +const hash = crypto.createHash('sha256'); +hash.update(Buffer.from(mrzCharcodes)); +const mrzHash = Array.from(hash.digest()).map(x => (x < 128 ? x : x - 256)); + +// Ça correspond bien : +console.log('mrzHash:', mrzHash); +console.log('dataHashes["1"]:', dataHashes['1']); +console.log('Are they equal ?', arraysAreEqual(mrzHash, dataHashes['1'])); + +// Let's replace the first array with the MRZ hash +dataHashesAsArray.shift(); +dataHashesAsArray.unshift([1, mrzHash]); +// Concaténons les dataHashes : +const concatenatedDataHashes: number[] = [].concat( + ...dataHashesAsArray.map((dataHash: any) => { + dataHash[1].unshift(...[48, 37, 2, 1, dataHash[0], 4, 32]); + return dataHash[1]; + }), +); + +// Starting sequence. Should be the same for everybody, but not sure +concatenatedDataHashes.unshift( + ...[ + 48, -126, 1, 37, 2, 1, 0, 48, 11, 6, 9, 96, -122, 72, 1, 101, 3, 4, 2, 1, + 48, -126, 1, 17, ], - '11': [ - 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, - ], - '12': [ - -66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, - -100, -115, -128, -9, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38, - ], - '13': [ - 91, -34, -46, -63, 63, -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, 52, -29, 72, -11, 59, -63, -18, -90, 103, 49, 24, -92, - -85, -68, -62, -59, -100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38, - ], - '2': [ - 63, -22, 106, 78, 31, 16, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, - -23, -55, -43, 53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114, - ], - '3': [ - -120, -101, 87, -112, 121, 15, -104, 127, 85, 25, -102, 80, 20, 58, 51, 75, - -63, 116, -22, 0, 60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124, - ], -}; -const eContent = - '3166301506092a864886f70d01090331080606678108010101301c06092a864886f70d010905310f170d3139313231363137323233385a302f06092a864886f70d01090431220420b0603bd5835259f8697d25b19ea2892b0d2773063be5516e314bffb89b497456'; -const encryptedDigest = - '5a78c5d241463136f26255cb75fe2de2dbaeda10ef7c7eea2f6b635940e079b04d6bfec592ef1293366076382e2a9543bd84a973c66e6c0715e468738c5d802c98cd81aa3d338a4e338e93e219412835456c4a0208587c360a5b8d4c2d09d069671e4175104c69c8ad2dadc6dea40729463dd8543392420406c08a020dadcb14ec78fad95ccef0cbe06a5416c45a9abc31c38d88190cb650a6536f0357bb6a04c59817a889d2eee4128b7757b2f7b52e572b030ef7b362dbad20de3a2a2c488134042fb8b18a254d2332cde4996e768da37863419a2760b9f394de395425db5b8276a24b60f02a0b595bf81a28dc3bd7584863641a75504b0df267467de87516'; +); -// Assemble the MRZ in two lines -// let mrzLine1 = -// dg1File.mrzInfo.documentCode + -// dg1File.mrzInfo.issuingState + -// dg1File.mrzInfo.primaryIdentifier + -// dg1File.mrzInfo.optionalData1.toUpperCase(); +// They are equal ! +console.log('concatenatedDataHashes', concatenatedDataHashes); +console.log('contentBytes', contentBytes); +console.log( + 'Are they equal ?', + arraysAreEqual(concatenatedDataHashes, contentBytes), +); -// let mrzLine2 = -// dg1File.mrzInfo.documentNumber + -// dg1File.mrzInfo.documentNumberCheckDigit + -// dg1File.mrzInfo.nationality + -// dg1File.mrzInfo.dateOfBirth + -// dg1File.mrzInfo.dateOfBirthCheckDigit + -// dg1File.mrzInfo.gender + -// dg1File.mrzInfo.dateOfExpiry + -// dg1File.mrzInfo.dateOfExpiryCheckDigit + -// dg1File.mrzInfo.secondaryIdentifier.toUpperCase() + -// dg1File.mrzInfo.compositeCheckDigit; +// please hash concatenatedDataHashes +const concatenatedDataHashesHash = crypto.createHash('sha256'); +concatenatedDataHashesHash.update(Buffer.from(concatenatedDataHashes)); +const concatenatedDataHashesHashDigest = Array.from( + concatenatedDataHashesHash.digest(), +).map(x => (x < 128 ? x : x - 256)); -// Form the MRZ string -// const mrzString = `${dg1File.mrzInfo.documentCode}<${dg1File.mrzInfo.issuingState}${dg1File.mrzInfo.primaryIdentifier}<<${dg1File.mrzInfo.secondaryIdentifier}\n${dg1File.mrzInfo.documentNumber}${dg1File.mrzInfo.documentNumberCheckDigit}${dg1File.mrzInfo.nationality}${dg1File.mrzInfo.dateOfBirth}${dg1File.mrzInfo.dateOfBirthCheckDigit}${dg1File.mrzInfo.gender}${dg1File.mrzInfo.dateOfExpiry}${dg1File.mrzInfo.dateOfExpiryCheckDigit}${dg1File.mrzInfo.optionalData1}${dg1File.mrzInfo.compositeCheckDigit}`; +// Now let's reconstruct the eContent -// console.log('MRZ string:', mrzString); +const constructedEContent = []; -// // Convert the MRZ string to a byte array -// const mrzByteArray = Array.from(Buffer.from(mrzString, 'utf8')); +// 191216172238Z : 16th December 2019, 17:22:38 UTC +const timeOfSignature = [ + 49, 15, 23, 13, 49, 57, 49, 50, 49, 54, 49, 55, 50, 50, 51, 56, 90, +]; -// console.log('MRZ byte array:', mrzByteArray); +// Detailed description is in private file r&d.ts for now +// First, the tag and length, assumed to be always the same +constructedEContent.push(...[49, 102]); -// // Hash the MRZ byte array using SHA-256 -// const sha256 = crypto.createHash('sha256'); -// sha256.update(Buffer.from(mrzByteArray)); -// const hash = sha256.digest(); +// 1.2.840.113549.1.9.3 is RFC_3369_CONTENT_TYPE_OID +constructedEContent.push(...[48, 21, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 3]); +// 2.23.136.1.1.1 is ldsSecurityObject +constructedEContent.push(...[49, 8, 6, 6, 103, 129, 8, 1, 1, 1]); -// // Convert the hash to a byte array -// const hashByteArray = Array.from(hash); +// 1.2.840.113549.1.9.5 is signing-time +constructedEContent.push(...[48, 28, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 5]); +// time of the signature +constructedEContent.push(...timeOfSignature); +// 1.2.840.113549.1.9.4 is RFC_3369_MESSAGE_DIGEST_OID +constructedEContent.push(...[48, 47, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 4]); +// TAG and length of the message digest +constructedEContent.push(...[49, 34, 4, 32]); -// console.log('Hash byte array:', hashByteArray); +constructedEContent.push( + ...concatenatedDataHashesHashDigest.map((byte: number) => toUnsigned(byte)), +); -// The MRZ information -// const mrz = -// 'P String.fromCharCode(code)).join(''); - -// console.log('encodedString', encodedString); - -// const hash = crypto.createHash('sha256'); -// hash.update(encodedString); -// const hashedEncoded = hash.digest('hex'); - -// console.log('hashedEncoded', hashedEncoded); - -// const hash2 = crypto.createHash('sha256'); -// hash2.update(Buffer.from(encoded)); -// const hashedEncoded2 = hash2.digest('hex'); - -// console.log('hashedEncoded2', hashedEncoded2); - -function getEncoded(dg1File: any) { - let buffers = []; - - // helper to write string as ASCII codes - const write = (str: string) => { - buffers.push(Buffer.from(str, 'utf8')); - }; - - // helper to write '<' filled string of certain length - const writeFixedSize = (str: any, size: any) => { - str = str.padEnd(size, '<'); - buffers.push(Buffer.from(str, 'utf8')); - }; - - const writeDocumentType = () => write(dg1File.mrzInfo.documentCode); - const writeIssuingState = () => write(dg1File.mrzInfo.issuingState); - const writeDocumentNumber = () => - writeFixedSize(dg1File.mrzInfo.documentNumber, 9); - const writeDateOfBirth = () => write(dg1File.mrzInfo.dateOfBirth); - const writeGender = () => write(dg1File.mrzInfo.gender); - const writeDateOfExpiry = () => write(dg1File.mrzInfo.dateOfExpiry); - const writeNationality = () => write(dg1File.mrzInfo.nationality); - const writeName = () => - writeFixedSize( - dg1File.mrzInfo.primaryIdentifier + - '<<' + - dg1File.mrzInfo.secondaryIdentifier, - 39, - ); - - if (dg1File.mrzInfo.documentType === 3) { - // check if it's an ID3 document - writeDocumentType(); - writeIssuingState(); - writeName(); - writeDocumentNumber(); - buffers.push( - Buffer.from([dg1File.mrzInfo.documentNumberCheckDigit.charCodeAt(0)]), - ); // Convert string digit to ASCII code - writeNationality(); - writeDateOfBirth(); - buffers.push( - Buffer.from([dg1File.mrzInfo.dateOfBirthCheckDigit.charCodeAt(0)]), - ); // Convert string digit to ASCII code - writeGender(); - writeDateOfExpiry(); - buffers.push( - Buffer.from([dg1File.mrzInfo.dateOfExpiryCheckDigit.charCodeAt(0)]), - ); // Convert string digit to ASCII code - // assuming personal number is optionalData1 - writeFixedSize(dg1File.mrzInfo.optionalData1, 14); - // assuming personal number check digit is missing - buffers.push( - Buffer.from([dg1File.mrzInfo.compositeCheckDigit.charCodeAt(0)]), - ); // Convert string digit to ASCII code - } else { - console.error('Unsupported document type: ', dg1File.mrzInfo.documentType); - } - - return Buffer.concat(buffers); +if (valid) { + console.log('The signature is valid.'); +} else { + console.log('The signature is not valid.'); } - -const encoded = Array.from(getEncoded(dg1File)); -console.log(encoded); -const a = [ - 80, 70, 82, 65, 84, 65, 86, 69, 82, 78, 73, 69, 82, 60, 60, 70, 76, 79, 82, - 69, 78, 84, 60, 72, 85, 71, 85, 69, 83, 60, 74, 69, 65, 78, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 49, 57, 72, 65, 51, 52, 56, 50, 56, 4, 70, 82, 65, 48, 48, - 48, 55, 49, 57, 1, 77, 65, 76, 69, 50, 57, 49, 50, 48, 57, 5, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 48, 2, -]; - -console.log('a', a.map(code => String.fromCharCode(code)).join('')); - -const b = [ - 97, 91, 95, 31, 88, 80, 60, 70, 82, 65, 84, 65, 86, 69, 82, 78, 73, 69, 82, - 60, 60, 70, 76, 79, 82, 69, 78, 84, 60, 72, 85, 71, 85, 69, 83, 60, 74, 69, - 65, 78, 60, 60, 60, 60, 60, 60, 60, 60, 60, 49, 57, 72, 65, 51, 52, 56, 50, - 56, 52, 70, 82, 65, 48, 48, 48, 55, 49, 57, 49, 77, 50, 57, 49, 50, 48, 57, - 53, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 48, 50, -]; -console.log('b', b.map(code => String.fromCharCode(code)).join('')); - -// PFRATAVERNIER< { - const dataHash = dataHashes[key as keyof typeof dataHashes]; - return [Number(key), dataHash]; - }) - .sort((a, b) => (a[0] as number) - (b[0] as number)); - -console.log('dataHashesAsArray:', dataHashesAsArray); - -console.log('mrz: ', mrz); - -const mrzCharcodes = [...mrz].map(char => char.charCodeAt(0)); - -console.log('mrzCharcodes:', mrzCharcodes); - -mrzCharcodes.unshift(88); // the length of the mrz data -mrzCharcodes.unshift(95, 31); // the MRZ_INFO_TAG -mrzCharcodes.unshift(91); // the new length of the whole array -mrzCharcodes.unshift(97); // the tag for DG1 - -console.log('mrzCharcodes with tags:', mrzCharcodes); - -const hash = crypto.createHash('sha256'); -hash.update(Buffer.from(mrzCharcodes)); -const mrzHash = Array.from(hash.digest()).map(x => (x < 128 ? x : x - 256)); - -// Ça correspond bien : -console.log('mrzHash:', mrzHash); -console.log('dataHashes["1"]:', dataHashes['1']); - -// Let's replace the first array with the MRZ hash -dataHashesAsArray.shift(); -dataHashesAsArray.unshift([1, mrzHash]); -// Concaténons les dataHashes : -const concatenatedDataHashes: number[] = [].concat( - ...dataHashesAsArray.map((dataHash: any) => { - dataHash[1].unshift(...[48, 37, 2, 1, dataHash[0], 4, 32]); - return dataHash[1]; - }), -); - -// Starting sequence. Should be the same for everybody, but not sure -concatenatedDataHashes.unshift( - ...[ - 48, -126, 1, 37, 2, 1, 0, 48, 11, 6, 9, 96, -122, 72, 1, 101, 3, 4, 2, 1, - 48, -126, 1, 17, - ], -); - -// They are equal ! -console.log('concatenatedDataHashes', concatenatedDataHashes); -console.log('contentBytes', contentBytes); diff --git a/app/scripts/script3_photo.ts b/app/scripts/script3_photo.ts deleted file mode 100644 index b4302b7b6..000000000 --- a/app/scripts/script3_photo.ts +++ /dev/null @@ -1,91 +0,0 @@ -import * as crypto from 'crypto'; - -// On a la donnée de base : -// Pas besoin de faire ça, on va pas prouver l'image pour l'instant - -const dg2InSave = { - buffer: [ - 127, 41, 40, -118, 2, -112, -1, -39, -19, -19, 105, -71, -45, 50, 40, 106, - 53, -53, 70, 125, -69, 14, -50, 127, -91, -81, 110, -74, 44, -38, 92, 37, - -8, -64, 126, -88, -84, 127, -122, -118, -65, -92, 15, 63, 28, 39, 13, 42, - 125, 54, -107, 2, -97, 100, 117, -38, 1, 27, 61, 79, -118, -104, 31, 99, 29, - -94, 12, -16, -27, -46, -40, -127, 7, -1, 53, -90, 33, 63, 105, -33, 119, - -81, 107, 119, -105, 48, 20, -13, -74, 112, -30, -106, 39, -10, -29, -112, - -17, -2, 54, -9, -115, -16, 75, 104, 103, 94, 87, -60, -82, 13, 92, -16, 9, - -38, 17, -101, -95, 125, 121, 70, -104, -120, 58, 51, -108, -125, 40, 48, - -57, 88, -112, 95, -52, 69, 26, -62, -22, 94, -35, -104, -88, 28, 61, 87, - -126, -60, -70, -22, 19, 122, -19, 30, -3, -109, -32, 18, -15, -3, 4, -116, - -19, 112, -85, 121, -17, -60, -128, -28, 14, -85, -85, 0, -19, 62, 14, 95, - 63, -40, 77, -27, 6, 78, -47, 93, -33, -7, 61, -46, -126, 120, 1, 67, -38, - 74, 45, 96, 54, -67, 40, -1, -124, 33, -15, 63, -111, 119, 66, 106, -21, - -46, -107, 75, -37, -114, 111, 48, 0, 0, 0, 0, 0, 0, 0, 0, - ], - bufferLength: 8, - fileLength: 13814, - fs: { - fidToSFI: { - '257': 1, - '258': 2, - '259': 3, - '260': 4, - '261': 5, - '262': 6, - '263': 7, - '264': 8, - '265': 9, - '266': 10, - '267': 11, - '268': 12, - '269': 13, - '270': 14, - '271': 15, - '272': 16, - '284': 28, - '285': 29, - '286': 30, - }, - fileInfos: { - '257': [Object], - '258': [Object], - '270': [Object], - '285': [Object], - }, - isSFIEnabled: false, - isSelected: true, - selectedFID: 270, - service: {secureMessagingSender: [Object], service: [Object]}, - wrapper: { - ksEnc: [Object], - ksMac: [Object], - maxTranceiveLength: 256, - shouldCheckMAC: false, - ssc: 0, - }, - }, - markedOffset: -1, - offsetBufferInFile: 13806, - offsetInBuffer: 8, - path: [{buffer: [Object], fid: 258}], -}; - -const photo = { - base64: - 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAIQAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAAAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3BhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADTLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAwADEANv/bAEMA///////////////////////////////////////////////////////////////////////////////////////bAEMB///////////////////////////////////////////////////////////////////////////////////////AABEIAUAA8AMBIgACEQEDEQH/xAAXAAEBAQEAAAAAAAAAAAAAAAAAAQID/8QAIRABAQABAwQDAQAAAAAAAAAAAAERAhJhMYGh8CFB0VH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/ANmRAXJlFAAAAAAAAAAAEAUQBcmUAXJlAFyIAogCiAKIAqKgCoAoAAACKgKIAAAAAAAAAAAAAAAAAAAqKAgKAigAIADFoN5kZ3MgLupuqANbqu5gB0zBzMg6DE1YbAAAAAAAAAABQQAAFEAAtc7bQW3LIAAAAAAAAALLhAHSVXJqXANhLkAAAAAABQAQFBALcAzqv0wdQAAAAAAAAAAAFBBcICyukuXNZcA2AAAACgIqAAAMar9NuYIAAAAAALhcAyq4XAMmGsAJhcKAmEsaKDCNVkG9N+mnJ0lzAUABUUBFQAAC9HJvV0YAAAFMZBMNyEigAIoKAgoCKigIqKJWHRiiI1prIDqEAAABUAABjV1Zb1MAA1AMNIoAACoCqIAoggAKAAgxW2KCAsB0nQJ0AAAUEBUAGdTC6rmoBG2Z1aBREBcmWcGAayZZUGhAVUyIIZMphcAZXKAKzWkoMrIjpOgKAAACgAIqAxq+mWtXVkFjTMaATKpATItiSAKAKqKKyKgiCpgF5MqmAVKqUEb09HN009AUAAAFAARUBnVPth0vRzoLG2I0AKAiKAigAqKKgAIoCAKAzWmaCRudGI6QAAAAFRQBFARit1kGY0z0aBQBUFAQABUUEAAVFABAGa0n2ISNsxoAAAAFAARUASxQGaLhAFQBUAUBKCjKiKMqKoAAAgDUAgAAAAAKAAigIAAipQQAAAAAEFQFEUUAAAEGmY0AAAAAACgAIqAAAAAyLUABAPkAE+RQEUAFQBQAWKAAAAAAAKAAioAAAADNv0jOfloFEABQEFAQUBAAFlRJfkHQAAAAAAAFQAAAAS3AKl6VjdUttBGpWQGxnKgqoAqACoAAiZAtQAdZ0ipLmKAAAAAAACWyAqZwxdX8QGrq/jAAAAAAAA1KrC5BpEyZBTKZQFQAAAGpq/rIDqrlLY3NQNAAAAxdX8YAAAAAAAAAAAAAAAAAAAAAAAAAFlsdJcuQDsMTV/W5cg4jrsnPvY2Tn3sDkOuyc+9jZOfH4DkOuyc+9jZOfH4DkOuyc+9jZOfewOQ67Jz72Nk597A5DrsnPj8Nk58fgOQ67Jz72Nk597A5DrsnPvY2Tnx+A5DrsnPj8Nk58fgOQ67Jz72Nk597A5DrsnPvY2Tn3sDkOuyc+9jZOfewOQ67Jz4/DZOfH4DkOuyc+Pw2Tn3sDksvy6bJz72Nk597A//Z', - height: 320, - width: 240, -}; - -// On veut retrouver la version encodée. Début : -const dg2fileEncodedStart = [ - 117, -126, 53, -14, 127, 97, -126, 53, -19, 2, 1, 1, 127, 96, -126, 53, -27, - -95, 15, -128, 2, 1, 1, -127, 1, 2, -121, 2, 1, 1, -120, 2, 0, 8, 95, 46, - -126, 53, -49, 70, 65, 67, 0, 48, 49, 48, 0, 0, 0, 53, -49, 0, 1, 0, 0, 53, - -63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, -16, 1, 64, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 12, 10, -]; - -const photoBytes = atob(photo.base64.split(',')[1]) - .split('') - .map(char => char.charCodeAt(0)); - -console.log('photoBytes:', photoBytes); diff --git a/app/scripts/utils.ts b/app/scripts/utils.ts new file mode 100644 index 000000000..813aac9f6 --- /dev/null +++ b/app/scripts/utils.ts @@ -0,0 +1,14 @@ +export function toUnsigned(byte: number) { + return byte & 0xff; +} + +export function arraysAreEqual(array1: number[], array2: number[]) { + return ( + array1.length === array2.length && + array1.every((value, index) => value === array2[index]) + ); +} + +export function toSigned(byte: number) { + return byte > 127 ? byte - 256 : byte; +} diff --git a/app/yarn.lock b/app/yarn.lock index f466c429a..74a64e82c 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -1879,6 +1879,13 @@ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz" integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== +"@types/node-forge@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.3.tgz#43de56dd6a7c01b755a64759def25033356cfe5c" + integrity sha512-SWpOXtqCNKaDO4xY+ZHrU5ih7UeEeo6frW468B/G7eJ3d9t2r9Vi/9iLHUuuvdZdv5l2yvZ10R2NlY3cV/CuWQ== + dependencies: + "@types/node" "*" + "@types/node@*": version "20.4.4" resolved "https://registry.npmjs.org/@types/node/-/node-20.4.4.tgz" @@ -4955,6 +4962,11 @@ node-fetch@^2.2.0, node-fetch@^2.6.0: dependencies: whatwg-url "^5.0.0" +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" From 0310ee890cd1cb65ed0ce7808c0e4478fd030fae Mon Sep 17 00:00:00 2001 From: 0xturboblitz Date: Thu, 27 Jul 2023 14:25:45 +0200 Subject: [PATCH 2/5] clean build.gradle --- .../android/build.gradle | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/app/android/react-native-passport-reader/android/build.gradle b/app/android/react-native-passport-reader/android/build.gradle index 4509c56bb..9e6ac742b 100644 --- a/app/android/react-native-passport-reader/android/build.gradle +++ b/app/android/react-native-passport-reader/android/build.gradle @@ -31,7 +31,6 @@ android { } dependencies { - // implementation files('../../app/libs/jmrtd-0.5.5.jar') implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'com.google.code.gson:gson:2.8.9' // Check for the latest version implementation 'androidx.multidex:multidex:2.0.1' @@ -39,6 +38,8 @@ dependencies { implementation 'androidx.core:core-ktx:1.9.0' implementation 'com.wdullaer:materialdatetimepicker:3.5.2' implementation 'org.jmrtd:jmrtd:0.7.18' + // implementation files('../../../../../jmrtd-0.7.18-sources/target/jmrtd-0.7.18.jar') + // implementation files('../../app/libs/jmrtd-0.7.18.jar') implementation 'net.sf.scuba:scuba-sc-android:0.0.18' implementation 'com.madgag.spongycastle:prov:1.54.0.0' implementation 'com.gemalto.jp2:jp2-android:1.0.3' @@ -46,17 +47,6 @@ dependencies { implementation 'org.bouncycastle:bcpkix-jdk15on:1.65' // do not update implementation 'commons-io:commons-io:2.8.0' implementation 'com.squareup.okhttp3:okhttp:4.9.0' - // implementation platform('com.google.firebase:firebase-bom:31.0.0') - // googleImplementation 'com.google.firebase:firebase-analytics-ktx' - // googleImplementation 'com.google.firebase:firebase-crashlytics' - // googleImplementation 'com.google.android.gms:play-services-ads:21.3.0' - // googleImplementation 'com.google.android.play:review-ktx:2.0.1' - - // implementation 'org.jmrtd:jmrtd:0.5.5' - // implementation 'com.android.support:multidex:1.0.3' - // implementation 'net.sf.scuba:scuba-sc-android:0.0.9' - // implementation 'com.madgag.spongycastle:prov:1.54.0.0' - // implementation 'com.github.mhshams:jnbis:1.1.0' implementation 'com.android.support:appcompat-v7:25.1.0' implementation 'edu.ucar:jj2000:5.2' implementation 'com.facebook.react:react-native:+' From 7d62b26fa719c0f24ccccc7e9678fff64d30ac70 Mon Sep 17 00:00:00 2001 From: 0xturboblitz Date: Thu, 27 Jul 2023 14:26:58 +0200 Subject: [PATCH 3/5] now sending and receiving all needed data --- app/.gitignore | 5 +- app/App.tsx | 109 +++--- .../io/tradle/nfc/RNPassportReaderModule.kt | 192 ++++------ app/package.json | 7 +- app/yarn.lock | 329 +++++++++++++++--- 5 files changed, 408 insertions(+), 234 deletions(-) diff --git a/app/.gitignore b/app/.gitignore index 06a2b148d..b5104e1a7 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -66,5 +66,8 @@ yarn-error.log /coverage .env + +# Contains personal information /scripts/env.ts -/scripts/retd.ts \ No newline at end of file +/scripts/retd.ts +/server/passportData.json \ No newline at end of file diff --git a/app/App.tsx b/app/App.tsx index 4742e512d..352dd89f8 100644 --- a/app/App.tsx +++ b/app/App.tsx @@ -1,5 +1,4 @@ import React, {useEffect, useState} from 'react'; -import type {PropsWithChildren} from 'react'; import { SafeAreaView, ScrollView, @@ -14,7 +13,6 @@ import { TextInput, ActivityIndicator, } from 'react-native'; -import RNFS from 'react-native-fs'; import { Colors, @@ -27,7 +25,7 @@ import { import PassportReader from 'react-native-passport-reader'; import {checkInputs} from './utils/checks'; -// const {PassportReaderModule} = NativeModules; +const CACHE_PASSPORT_DATA = true; function App(): JSX.Element { const isDarkMode = useColorScheme() === 'dark'; @@ -54,68 +52,58 @@ function App(): JSX.Element { async function handleResponse(response: any) { const { - firstName, - lastName, - gender, - issuer, - nationality, - photo, - dg1File, - dg2File, - dg2InSave, + mrzInfo, publicKey, - publicKeyOldSchool, + publicKeyPEM, dataGroupHashes, - sodFile, - signedData, eContent, encryptedDigest, + contentBytes, + eContentDecomposed, } = response; - // const responseJSON = JSON.stringify(response, null, 2); - // const responseJSONPath = RNFS. + '/response.json'; + const passportData = { + mrzInfo: JSON.parse(mrzInfo), + publicKey: publicKey, + publicKeyPEM: publicKeyPEM, + dataGroupHashes: JSON.parse(dataGroupHashes), + eContent: JSON.parse(eContent), + encryptedDigest: JSON.parse(encryptedDigest), + contentBytes: JSON.parse(contentBytes), + eContentDecomposed: JSON.parse(eContentDecomposed), + }; - // console.log('responseJSONPath', responseJSONPath); + console.log('mrzInfo', passportData.mrzInfo); + console.log('publicKey', passportData.publicKey); + console.log('publicKeyPEM', passportData.publicKeyPEM); + console.log('dataGroupHashes', passportData.dataGroupHashes); + console.log('eContent', passportData.eContent); + console.log('encryptedDigest', passportData.encryptedDigest); + console.log('contentBytes', passportData.contentBytes); + console.log('eContentDecomposed', passportData.eContentDecomposed); - // RNFS.writeFile(responseJSONPath, responseJSON, 'utf8') - // .then(success => console.log('FILE WRITTEN!')) - // .catch(err => console.log(err.message)); + // Stores data in local server to avoid having to scan the passport each time + // For development purposes only - console.log('firstName', firstName); - console.log('lastName', lastName); - console.log('gender', gender); - console.log('issuer', issuer); - console.log('nationality', nationality); - console.log('photo', photo); - console.log('dg1File', JSON.parse(dg1File)); - // console.log('dg2File', JSON.parse(dg2File)); - console.log('dg2InSave', JSON.parse(dg2InSave)); - console.log('publicKey', publicKey); - console.log('publicKeyOldSchool', publicKeyOldSchool); - // console.log('dataGroupHashes', JSON.parse(dataGroupHashes)); - console.log('eContent', JSON.parse(eContent)); - console.log('encryptedDigest', JSON.parse(encryptedDigest)); - console.log('sodFile', JSON.parse(sodFile)); - console.log('signedData', JSON.parse(signedData)); + if (CACHE_PASSPORT_DATA) { + fetch('http://192.168.1.22:3000/passportData', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(passportData), + }) + .then(response => response.json()) + .then(data => console.log(data.message)) + .catch(error => { + console.error('Error:', error); + }); + } - // copilot, please write dg2File and dg2InSave to disk as JSON files, in js - - fetch('http://192.168.1.22:3000/data', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: sodFile, - }) - .then(response => response.json()) - .then(data => console.log(data)) - .catch(error => { - console.error('Error:', error); - }); - - setFirstName(firstName); - - const {base64, width, height} = photo; + const firstName = passportData.mrzInfo.secondaryIdentifier.split('<')[0]; + setFirstName( + firstName.charAt(0).toUpperCase() + firstName.slice(1).toLowerCase(), + ); // 1. Compute the eContent from the dg1File @@ -146,6 +134,10 @@ function App(): JSX.Element { } } + const handleProve = () => { + // Generate a proof of passport here + }; + const handleMint = () => { // mint "Proof of Passport" NFT to the address logic here }; @@ -208,6 +200,13 @@ function App(): JSX.Element { value={address} placeholder="Your Address or ens name" /> +