mirror of
https://github.com/selfxyz/self.git
synced 2026-01-23 13:38:04 -05:00
Merge branch 'new-app' into ios-nfc
This commit is contained in:
5
app/.babelrc
Normal file
5
app/.babelrc
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"plugins": [
|
||||
["module:react-native-dotenv"]
|
||||
]
|
||||
}
|
||||
2
app/.gitignore
vendored
2
app/.gitignore
vendored
@@ -72,4 +72,4 @@ yarn-error.log
|
||||
/scripts/retd.ts
|
||||
/server/passportData.json
|
||||
|
||||
.expo/
|
||||
.expo/
|
||||
|
||||
149
app/App.tsx
149
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,
|
||||
@@ -25,18 +23,33 @@ import {
|
||||
} from 'react-native/Libraries/NewAppScreen';
|
||||
// @ts-ignore
|
||||
import PassportReader from 'react-native-passport-reader';
|
||||
import {checkInputs} from './utils/checks';
|
||||
import {checkInputs, getFirstName} from './utils/checks';
|
||||
import {DEFAULT_PNUMBER, DEFAULT_DOB, DEFAULT_DOE, DEFAULT_ADDRESS} from '@env';
|
||||
|
||||
// const {PassportReaderModule} = NativeModules;
|
||||
console.log('DEFAULT_PNUMBER', DEFAULT_PNUMBER);
|
||||
|
||||
const CACHE_DATA_IN_LOCAL_SERVER = true;
|
||||
const SKIP_SCAN = true;
|
||||
|
||||
type PassportData = {
|
||||
mrzInfo: any;
|
||||
publicKey: any;
|
||||
publicKeyPEM: any;
|
||||
dataGroupHashes: any;
|
||||
eContent: any;
|
||||
encryptedDigest: any;
|
||||
contentBytes: any;
|
||||
eContentDecomposed: any;
|
||||
};
|
||||
|
||||
function App(): JSX.Element {
|
||||
const isDarkMode = useColorScheme() === 'dark';
|
||||
const [passportNumber, setPassportNumber] = useState('19HA34828');
|
||||
const [dateOfBirth, setDateOfBirth] = useState('000719');
|
||||
const [dateOfExpiry, setDateOfExpiry] = useState('291209');
|
||||
const [address, setAddress] = useState('');
|
||||
const [passportNumber, setPassportNumber] = useState(DEFAULT_PNUMBER ?? '');
|
||||
const [dateOfBirth, setDateOfBirth] = useState(DEFAULT_DOB ?? '');
|
||||
const [dateOfExpiry, setDateOfExpiry] = useState(DEFAULT_DOE ?? '');
|
||||
const [address, setAddress] = useState(DEFAULT_ADDRESS ?? '');
|
||||
const [passportData, setPassportData] = useState<PassportData | null>(null);
|
||||
const [step, setStep] = useState('enterDetails');
|
||||
const [firstName, setFirstName] = useState('');
|
||||
|
||||
const backgroundStyle = {
|
||||
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
|
||||
@@ -52,70 +65,67 @@ function App(): JSX.Element {
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (SKIP_SCAN && passportData === null) {
|
||||
console.log('skipping scan step...');
|
||||
fetch('http://192.168.1.22:3000/passportData')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log('passport data fetched');
|
||||
setPassportData(data);
|
||||
setStep('scanCompleted');
|
||||
});
|
||||
}
|
||||
|
||||
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));
|
||||
setPassportData(passportData);
|
||||
|
||||
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));
|
||||
|
||||
// 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;
|
||||
if (CACHE_DATA_IN_LOCAL_SERVER) {
|
||||
// Caches data in local server to avoid having to scan the passport each time
|
||||
// For development purposes only
|
||||
fetch('http://192.168.1.22:3000/post', {
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
// 1. Compute the eContent from the dg1File
|
||||
|
||||
@@ -146,6 +156,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
|
||||
};
|
||||
@@ -206,7 +220,9 @@ function App(): JSX.Element {
|
||||
{step === 'scanCompleted' ? (
|
||||
<View style={styles.sectionContainer}>
|
||||
<Text style={styles.header}>Connection successful</Text>
|
||||
<Text style={styles.sectionDescription}>Hi {firstName} </Text>
|
||||
<Text style={styles.header}>
|
||||
Hi {getFirstName(passportData?.mrzInfo)} !{' '}
|
||||
</Text>
|
||||
<Text style={styles.header}>Input your address or ens</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
@@ -214,6 +230,13 @@ function App(): JSX.Element {
|
||||
value={address}
|
||||
placeholder="Your Address or ens name"
|
||||
/>
|
||||
<Button title="Generate zk proof" onPress={handleProve} />
|
||||
</View>
|
||||
) : null}
|
||||
{step === 'proofGenerated' ? (
|
||||
<View style={styles.sectionContainer}>
|
||||
<Text style={styles.header}>Zero-knowledge proof generated</Text>
|
||||
<Text style={styles.header}>You can now mint your SBT</Text>
|
||||
<Button title="Mint Proof of Passport" onPress={handleMint} />
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
@@ -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:+'
|
||||
|
||||
@@ -143,11 +143,6 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
return "RNPassportReader"
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun createCalendarEvent(name: String, location: String) {
|
||||
Log.d("CalendarModule", "Create event called with name: $name and location: $location")
|
||||
}
|
||||
|
||||
fun sendDataToJS(passportData: PassportData) {
|
||||
val gson = Gson()
|
||||
|
||||
@@ -242,7 +237,6 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
|
||||
private lateinit var dg1File: DG1File
|
||||
private lateinit var dg2File: DG2File
|
||||
private lateinit var dg2InSave: InputStream
|
||||
private lateinit var dg14File: DG14File
|
||||
private lateinit var sodFile: SODFile
|
||||
private var imageBase64: String? = null
|
||||
@@ -291,67 +285,48 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "============FIRST CONSOLE LOG=============")
|
||||
val gson = Gson()
|
||||
|
||||
|
||||
val dg1In = service.getInputStream(PassportService.EF_DG1)
|
||||
dg1File = DG1File(dg1In)
|
||||
Log.d(TAG, "dg1File: " + gson.toJson(dg1File)) //
|
||||
|
||||
|
||||
dg1File = DG1File(dg1In)
|
||||
val dg2In = service.getInputStream(PassportService.EF_DG2)
|
||||
dg2File = DG2File(dg2In)
|
||||
dg2InSave = dg2In
|
||||
Log.d(TAG, "dg2In:")
|
||||
Log.d(TAG, gson.toJson(dg2In))
|
||||
Log.d(TAG, gson.toJson(dg2File))
|
||||
|
||||
dg2File = DG2File(dg2In)
|
||||
val sodIn = service.getInputStream(PassportService.EF_SOD)
|
||||
|
||||
sodFile = SODFile(sodIn)
|
||||
|
||||
Log.d(TAG, "other data :")
|
||||
|
||||
|
||||
// Log.d(TAG, "============FIRST CONSOLE LOG=============")
|
||||
// Log.d(TAG, "dg1File: " + gson.toJson(dg1File))
|
||||
// Log.d(TAG, "dg2File: " + gson.toJson(dg2File))
|
||||
// Log.d(TAG, "sodFile.docSigningCertificate: ${sodFile.docSigningCertificate}")
|
||||
Log.d(TAG, "publicKey: ${sodFile.docSigningCertificate.publicKey}")
|
||||
Log.d(TAG, "publicKey: ${sodFile.docSigningCertificate.publicKey.toString()}")
|
||||
Log.d(TAG, "publicKey: ${sodFile.docSigningCertificate.publicKey.format}")
|
||||
Log.d(TAG, "publicKey: ${Base64.encodeToString(sodFile.docSigningCertificate.publicKey.encoded, Base64.DEFAULT)}")
|
||||
|
||||
Log.d(TAG, "sodFile.docSigningCertificate: ${gson.toJson(sodFile.docSigningCertificate)}")
|
||||
val hexMap = sodFile.dataGroupHashes.mapValues { (_, value) ->
|
||||
value.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
Log.d(TAG, "hexMap: ${gson.toJson(hexMap)}")
|
||||
Log.d(TAG, "sodFile.dataGroupHashes: ${sodFile.dataGroupHashes}")
|
||||
Log.d(TAG, "sodFile.dataGroupHashes: ${gson.toJson(sodFile.dataGroupHashes)}")
|
||||
|
||||
|
||||
// var concatenated = concatenateHashes(sodFile.dataGroupHashes)
|
||||
// Log.d(TAG, "publicKey: ${sodFile.docSigningCertificate.publicKey}")
|
||||
// Log.d(TAG, "publicKey: ${sodFile.docSigningCertificate.publicKey.toString()}")
|
||||
// Log.d(TAG, "publicKey: ${sodFile.docSigningCertificate.publicKey.format}")
|
||||
// Log.d(TAG, "publicKey: ${Base64.encodeToString(sodFile.docSigningCertificate.publicKey.encoded, Base64.DEFAULT)}")
|
||||
// Log.d(TAG, "sodFile.docSigningCertificate: ${gson.toJson(sodFile.docSigningCertificate)}")
|
||||
// Log.d(TAG, "sodFile.dataGroupHashes: ${sodFile.dataGroupHashes}")
|
||||
// Log.d(TAG, "sodFile.dataGroupHashes: ${gson.toJson(sodFile.dataGroupHashes)}")
|
||||
// Log.d(TAG, "concatenated: $concatenated")
|
||||
// Log.d(TAG, "concatenated: ${gson.toJson(concatenated)}")
|
||||
// Log.d(TAG, "concatenated: ${gson.toJson(concatenated.joinToString("") { "%02x".format(it) })}")
|
||||
Log.d(TAG, "sodFile.eContent: ${sodFile.eContent}")
|
||||
Log.d(TAG, "sodFile.eContent: ${gson.toJson(sodFile.eContent)}")
|
||||
Log.d(TAG, "sodFile.eContent: ${gson.toJson(sodFile.eContent.joinToString("") { "%02x".format(it) })}")
|
||||
Log.d(TAG, "sodFile.encryptedDigest: ${sodFile.encryptedDigest}")
|
||||
Log.d(TAG, "sodFile.encryptedDigest: ${gson.toJson(sodFile.encryptedDigest)}")
|
||||
Log.d(TAG, "sodFile.encryptedDigest: ${gson.toJson(sodFile.encryptedDigest.joinToString("") { "%02x".format(it) })}")
|
||||
// Log.d(TAG, "sodFile.eContent: ${sodFile.eContent}")
|
||||
// Log.d(TAG, "sodFile.eContent: ${gson.toJson(sodFile.eContent)}")
|
||||
// Log.d(TAG, "sodFile.eContent: ${gson.toJson(sodFile.eContent.joinToString("") { "%02x".format(it) })}")
|
||||
// Log.d(TAG, "sodFile.encryptedDigest: ${sodFile.encryptedDigest}")
|
||||
// Log.d(TAG, "sodFile.encryptedDigest: ${gson.toJson(sodFile.encryptedDigest)}")
|
||||
// Log.d(TAG, "sodFile.encryptedDigest: ${gson.toJson(sodFile.encryptedDigest.joinToString("") { "%02x".format(it) })}")
|
||||
// var id = passportNumberView.text.toString()
|
||||
// try {
|
||||
// postData(id, sodFile.eContent.joinToString("") { "%02x".format(it) }, sodFile.encryptedDigest.joinToString("") { "%02x".format(it) }, sodFile.docSigningCertificate.publicKey.toString())
|
||||
// } catch (e: IOException) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
Log.d(TAG, "============LET'S VERIFY THE SIGNATURE=============")
|
||||
// Log.d(TAG, "============LET'S VERIFY THE SIGNATURE=============")
|
||||
|
||||
doChipAuth(service)
|
||||
doPassiveAuth()
|
||||
|
||||
Log.d(TAG, "============SIGNATURE VERIFIED=============")
|
||||
|
||||
// Log.d(TAG, "============SIGNATURE VERIFIED=============")
|
||||
// sendDataToJS(PassportData(dg1File, dg2File, sodFile))
|
||||
|
||||
// Log.d(TAG, "============DATA SENT TO JS=============")
|
||||
|
||||
val allFaceImageInfo: MutableList<FaceImageInfo> = ArrayList()
|
||||
@@ -399,56 +374,34 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
|
||||
private fun doPassiveAuth() {
|
||||
try {
|
||||
fun concatenateHashes(dataGroupHashes: Map<Int, ByteArray>): ByteArray {
|
||||
val allHashes = ArrayList<ByteArray>()
|
||||
|
||||
// Order the data group hashes by their keys and concatenate them
|
||||
for (i in dataGroupHashes.keys.sorted()) {
|
||||
allHashes.add(dataGroupHashes[i]!!)
|
||||
}
|
||||
|
||||
// Combine all the byte arrays into one
|
||||
val combinedSize = allHashes.sumOf { it.size }
|
||||
val result = ByteArray(combinedSize)
|
||||
var pos = 0
|
||||
for (hash in allHashes) {
|
||||
hash.copyInto(result, pos)
|
||||
pos += hash.size
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Log.d(TAG, "Starting passive authentication...")
|
||||
val digest = MessageDigest.getInstance(sodFile.digestAlgorithm)
|
||||
Log.d(TAG, "Using digest algorithm: ${sodFile.digestAlgorithm}")
|
||||
|
||||
val gson = Gson()
|
||||
Log.d(TAG, "Using digest algorithm: ${gson.toJson(sodFile)}")
|
||||
|
||||
val dataHashes = sodFile.dataGroupHashes
|
||||
Log.d(TAG, "dataHashes " + gson.toJson(dataHashes))
|
||||
val hexMap = sodFile.dataGroupHashes.mapValues { (_, value) ->
|
||||
value.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
Log.d(TAG, "hexMap: ${gson.toJson(hexMap)}")
|
||||
var concatenated = concatenateHashes(sodFile.dataGroupHashes)
|
||||
Log.d(TAG, "concatenated: $concatenated")
|
||||
Log.d(TAG, "concatenated: ${gson.toJson(concatenated)}")
|
||||
Log.d(TAG, "concatenated: ${gson.toJson(concatenated.joinToString("") { "%02x".format(it) })}")
|
||||
|
||||
val dg14Hash = if (chipAuthSucceeded) digest.digest(dg14Encoded) else ByteArray(0)
|
||||
val dg1Hash = digest.digest(dg1File.encoded)
|
||||
|
||||
Log.d(TAG, "dg1File.encoded " + gson.toJson(dg1File.encoded))
|
||||
Log.d(TAG, "dg1File.encoded.joinToString " + gson.toJson(dg1File.encoded.joinToString("") { "%02x".format(it) }))
|
||||
Log.d(TAG, "dg1Hash " + gson.toJson(dg1Hash))
|
||||
Log.d(TAG, "dg1Hash.joinToString " + gson.toJson(dg1Hash.joinToString("") { "%02x".format(it) }))
|
||||
val dg2Hash = digest.digest(dg2File.encoded)
|
||||
Log.d(TAG, "dg2File.encoded " + gson.toJson(dg2File.encoded))
|
||||
Log.d(TAG, "dg2File.encoded.joinToString " + gson.toJson(dg2File.encoded.joinToString("") { "%02x".format(it) }))
|
||||
Log.d(TAG, "dg2Hash " + gson.toJson(dg2Hash))
|
||||
Log.d(TAG, "dg2HashjoinToString " + gson.toJson(dg2Hash.joinToString("") { "%02x".format(it) }))
|
||||
|
||||
// Log.d(TAG, "dataHashes " + gson.toJson(dataHashes))
|
||||
// val hexMap = sodFile.dataGroupHashes.mapValues { (_, value) ->
|
||||
// value.joinToString("") { "%02x".format(it) }
|
||||
// }
|
||||
// Log.d(TAG, "hexMap: ${gson.toJson(hexMap)}")
|
||||
// Log.d(TAG, "concatenated: $concatenated")
|
||||
// Log.d(TAG, "concatenated: ${gson.toJson(concatenated)}")
|
||||
// Log.d(TAG, "concatenated: ${gson.toJson(concatenated.joinToString("") { "%02x".format(it) })}")
|
||||
// Log.d(TAG, "dg1File.encoded " + gson.toJson(dg1File.encoded))
|
||||
// Log.d(TAG, "dg1File.encoded.joinToString " + gson.toJson(dg1File.encoded.joinToString("") { "%02x".format(it) }))
|
||||
// Log.d(TAG, "dg1Hash " + gson.toJson(dg1Hash))
|
||||
// Log.d(TAG, "dg1Hash.joinToString " + gson.toJson(dg1Hash.joinToString("") { "%02x".format(it) }))
|
||||
// Log.d(TAG, "dg2File.encoded " + gson.toJson(dg2File.encoded))
|
||||
// Log.d(TAG, "dg2File.encoded.joinToString " + gson.toJson(dg2File.encoded.joinToString("") { "%02x".format(it) }))
|
||||
// Log.d(TAG, "dg2Hash " + gson.toJson(dg2Hash))
|
||||
// Log.d(TAG, "dg2HashjoinToString " + gson.toJson(dg2Hash.joinToString("") { "%02x".format(it) }))
|
||||
|
||||
Log.d(TAG, "Comparing data group hashes...")
|
||||
|
||||
@@ -463,24 +416,20 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
val cf = CertificateFactory.getInstance("X.509")
|
||||
|
||||
var p: ASN1Primitive?
|
||||
Log.d(TAG, "Reading ASN1 sequence...")
|
||||
var obj = asn1InputStream.readObject()
|
||||
|
||||
while (obj != null) {
|
||||
p = obj
|
||||
// Your processing code for ASN1Primitive p goes here
|
||||
val asn1 = ASN1Sequence.getInstance(p)
|
||||
if (asn1 == null || asn1.size() == 0) {
|
||||
throw IllegalArgumentException("Null or empty sequence passed.")
|
||||
}
|
||||
Log.d(TAG, "asn1" + asn1.toString()) //byte sequence
|
||||
|
||||
if (asn1.size() != 2) {
|
||||
throw IllegalArgumentException("Incorrect sequence size: " + asn1.size())
|
||||
}
|
||||
val certSet = ASN1Set.getInstance(asn1.getObjectAt(1))
|
||||
for (i in 0 until certSet.size()) {
|
||||
// Log.d(TAG, "Processing certificate: $i")
|
||||
val certificate = Certificate.getInstance(certSet.getObjectAt(i))
|
||||
val pemCertificate = certificate.encoded
|
||||
val javaCertificate = cf.generateCertificate(ByteArrayInputStream(pemCertificate))
|
||||
@@ -495,7 +444,6 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
for (docSigningCertificate: X509Certificate in docSigningCertificates) {
|
||||
docSigningCertificate.checkValidity()
|
||||
Log.d(TAG, "Certificate: ${docSigningCertificate.subjectDN} is valid.")
|
||||
// Log.d(TAG, docSigningCertificate.toString())
|
||||
}
|
||||
|
||||
val cp = cf.generateCertPath(docSigningCertificates)
|
||||
@@ -509,12 +457,10 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
if ((sodDigestEncryptionAlgorithm == "SSAwithRSA/PSS")) {
|
||||
sodDigestEncryptionAlgorithm = "SHA256withRSA/PSS"
|
||||
isSSA = true
|
||||
//Log.d(TAG, sodDigestEncryptionAlgorithm)
|
||||
|
||||
}
|
||||
val sign = Signature.getInstance(sodDigestEncryptionAlgorithm)
|
||||
if (isSSA) {
|
||||
//Log.d(TAG, isSSA.toString())
|
||||
sign.setParameter(PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1))
|
||||
}
|
||||
sign.initVerify(sodFile.docSigningCertificate)
|
||||
@@ -522,7 +468,6 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
|
||||
passiveAuthSuccess = sign.verify(sodFile.encryptedDigest)
|
||||
Log.d(TAG, "Passive authentication success: $passiveAuthSuccess")
|
||||
Log.d(TAG, "============LAST CONSOLE LOG=============")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Exception in passive authentication", e)
|
||||
@@ -555,50 +500,35 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
val signedDataField = SODFile::class.java.getDeclaredField("signedData")
|
||||
signedDataField.isAccessible = true
|
||||
|
||||
val signedData = signedDataField.get(sodFile)
|
||||
val signedData = signedDataField.get(sodFile) as SignedData
|
||||
|
||||
val eContentAsn1InputStream = ASN1InputStream(sodFile.eContent.inputStream())
|
||||
val eContentDecomposed: ASN1Primitive = eContentAsn1InputStream.readObject()
|
||||
|
||||
val passport = Arguments.createMap()
|
||||
passport.putString("mrzInfo", gson.toJson(mrzInfo))
|
||||
passport.putString("dg2File", gson.toJson(dg2File))
|
||||
passport.putString("publicKey", sodFile.docSigningCertificate.publicKey.toString())
|
||||
passport.putString("publicKeyPEM", Base64.encodeToString(sodFile.docSigningCertificate.publicKey.encoded, Base64.DEFAULT))
|
||||
passport.putString("dataGroupHashes", gson.toJson(sodFile.dataGroupHashes))
|
||||
passport.putString("eContent", gson.toJson(sodFile.eContent))
|
||||
passport.putString("encryptedDigest", gson.toJson(sodFile.encryptedDigest))
|
||||
passport.putString("contentBytes", gson.toJson(signedData.getEncapContentInfo()))
|
||||
passport.putString("eContentDecomposed", gson.toJson(eContentDecomposed))
|
||||
|
||||
// Another way to get signing time is to get into signedData.signerInfos, then search for the ICO identifier 1.2.840.113549.1.9.5
|
||||
// passport.putString("signerInfos", gson.toJson(signedData.signerInfos))
|
||||
|
||||
// Log.d(TAG, "signedData.digestAlgorithms: ${gson.toJson(signedData.digestAlgorithms)}")
|
||||
// Log.d(TAG, "signedData.signerInfos: ${gson.toJson(signedData.signerInfos)}")
|
||||
// Log.d(TAG, "signedData.certificates: ${gson.toJson(signedData.certificates)}")
|
||||
|
||||
val base64 = bitmap?.let { toBase64(it, quality) }
|
||||
val photo = Arguments.createMap()
|
||||
photo.putString("base64", base64 ?: "")
|
||||
photo.putInt("width", bitmap?.width ?: 0)
|
||||
photo.putInt("height", bitmap?.height ?: 0)
|
||||
|
||||
val firstName = mrzInfo.secondaryIdentifier.replace("<", "")
|
||||
val lastName = mrzInfo.primaryIdentifier.replace("<", "")
|
||||
val passport = Arguments.createMap()
|
||||
passport.putString("firstName", firstName)
|
||||
passport.putString("lastName", lastName)
|
||||
passport.putString("nationality", mrzInfo.nationality)
|
||||
passport.putString("gender", mrzInfo.gender.toString())
|
||||
passport.putString("issuer", mrzInfo.issuingState)
|
||||
passport.putMap("photo", photo)
|
||||
passport.putString("dg1File", gson.toJson(dg1File))
|
||||
passport.putString("dg2File", gson.toJson(dg2File))
|
||||
passport.putString("dg2InSave", gson.toJson(dg2InSave))
|
||||
passport.putString("signedData", gson.toJson(signedData))
|
||||
passport.putString("sodFile", gson.toJson(sodFile))
|
||||
passport.putString("publicKey", sodFile.docSigningCertificate.publicKey.toString())
|
||||
passport.putString("publicKeyOldSchool", Base64.encodeToString(sodFile.docSigningCertificate.publicKey.encoded, Base64.DEFAULT))
|
||||
passport.putString("dataGroupHashes", gson.toJson(sodFile.dataGroupHashes))
|
||||
passport.putString("eContent", gson.toJson(sodFile.eContent.joinToString("") { "%02x".format(it) }))
|
||||
passport.putString("eContent", gson.toJson(sodFile.eContent.joinToString("") { "%02x".format(it) }))
|
||||
passport.putString("encryptedDigest", gson.toJson(sodFile.encryptedDigest.joinToString("") { "%02x".format(it) }))
|
||||
|
||||
val asn1InputStream = ASN1InputStream(sodFile.eContent.inputStream())
|
||||
val asn1Primitive: ASN1Primitive = asn1InputStream.readObject()
|
||||
|
||||
// Log.d(TAG, "signedData: ${signedData}")
|
||||
// Log.d(TAG, "signedData: ${signedData.toString()}")
|
||||
// Log.d(TAG, "signedData: ${gson.toJson(signedData)}")
|
||||
|
||||
Log.d(TAG, "asn1Primitive: ${asn1Primitive}")
|
||||
Log.d(TAG, "asn1Primitive: ${asn1Primitive.toString()}")
|
||||
Log.d(TAG, "asn1Primitive: ${gson.toJson(asn1Primitive)}")
|
||||
// Log.d(TAG, "publicKey: ${sodFile.docSigningCertificate.publicKey}")
|
||||
// Log.d(TAG, "publicKey: ${Base64.encodeToString(sodFile.docSigningCertificate.publicKey.encoded, Base64.DEFAULT)}")
|
||||
// Log.d(TAG, "sodFile.dataGroupHashes: ${sodFile.dataGroupHashes}")
|
||||
// Log.d(TAG, "sodFile.eContent: ${gson.toJson(sodFile.eContent.joinToString("") { "%02x".format(it) })}")
|
||||
// Log.d(TAG, "sodFile.encryptedDigest: ${gson.toJson(sodFile.encryptedDigest.joinToString("") { "%02x".format(it) })}")
|
||||
|
||||
scanPromise?.resolve(passport)
|
||||
resetState()
|
||||
|
||||
1
app/declarations.d.ts
vendored
Normal file
1
app/declarations.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare module '@env';
|
||||
@@ -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<HUGUES<JEAN<<<<<<<<<',
|
||||
},
|
||||
tag: 97,
|
||||
};
|
||||
const mrzInfo = dg1File.mrzInfo;
|
||||
|
||||
// 'P<FRATAVERNIER<<FLORENT<HUGUES<JEAN<<<<<<<<<19HA348284FRA0007191M2912095<<<<<<<<<<<<<<02';
|
||||
const mrz =
|
||||
mrzInfo.documentCode +
|
||||
'<' +
|
||||
mrzInfo.issuingState +
|
||||
mrzInfo.primaryIdentifier +
|
||||
'<<' +
|
||||
mrzInfo.secondaryIdentifier +
|
||||
mrzInfo.documentNumber +
|
||||
mrzInfo.documentNumberCheckDigit +
|
||||
mrzInfo.nationality +
|
||||
mrzInfo.dateOfBirth +
|
||||
mrzInfo.dateOfBirthCheckDigit +
|
||||
mrzInfo.gender.substring(0, 1) +
|
||||
mrzInfo.dateOfExpiry +
|
||||
mrzInfo.dateOfExpiryCheckDigit +
|
||||
mrzInfo.optionalData1 +
|
||||
mrzInfo.compositeCheckDigit;
|
||||
|
||||
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 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,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,288 +1,155 @@
|
||||
// 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<HUGUES<JEAN<<<<<<<<<',
|
||||
},
|
||||
tag: 97,
|
||||
};
|
||||
const publicKey =
|
||||
'RSA Public Key [81:f8:a9:ad:98:ce:a1:f8:41:b7:41:73:c8:4e:a9:a8:c9:32:c3:a2],[56:66:d1:a4]';
|
||||
const modulus =
|
||||
'df11ba06d7937a059e8ce7916ab0fb0b094a9b9ecf98e97eda6834a23075f2030072a3c7868f85045af2acb5f5c2bedf6c25614d99232b98bb456e5f8ce32148882f2281537ac7aa80e4cdb79e0cdf4627cd08da32ce263ef54a26c2ca3493f1d02d9fabcd89952058cb0085fa356b13f9e2cc1e9ca4f47678dc49129d55531bd2817dd436d5aef778d4d439d2d659b0cf9d58eeff43ce2cff26d5c66d23164123fc9c3e6cd4902e9d7b54d9509b03f95debfc3fb15ef7b458ac64a2c6e26bf010451eff67ed87f6ca7a946dd7ac86dea2566cbdc9aa0e3cbaad9f5ed4b6886cd08f6baf1487b58f6ba33075968396c216ef65b0eb49c6978464dcde99f9a9a1';
|
||||
const exponent = 10001;
|
||||
const publicKeyOldSchool =
|
||||
'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3xG6BteTegWejOeRarD7CwlKm57PmOl+2mg0ojB18gMAcqPHho+FBFryrLX1wr7fbCVhTZkjK5i7RW5fjOMhSIgvIoFTeseqgOTNt54M30YnzQjaMs4mPvVKJsLKNJPx0C2fq82JlSBYywCF+jVrE/nizB6cpPR2eNxJEp1VUxvSgX3UNtWu93j1DnS1lmwz51Y7v9Dziz/JtXGbSMWQSP8nD5s1JAunXtU2VCbA/ld6/w/sV73tFisZKLG4mvwEEUe/2fth/bKepRt16yG3qJWbL3Jqg48uq2fXtS2iGzQj2uvFIe1j2ujMHWWg5bCFu9lsOtJxpeEZNzemfmpoQIDAQAB';
|
||||
const dataGroupHashes = {
|
||||
'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,
|
||||
const mrzInfo = dg1File.mrzInfo;
|
||||
|
||||
const mrz =
|
||||
mrzInfo.documentCode +
|
||||
'<' +
|
||||
mrzInfo.issuingState +
|
||||
mrzInfo.primaryIdentifier +
|
||||
'<<' +
|
||||
mrzInfo.secondaryIdentifier +
|
||||
mrzInfo.documentNumber +
|
||||
mrzInfo.documentNumberCheckDigit +
|
||||
mrzInfo.nationality +
|
||||
mrzInfo.dateOfBirth +
|
||||
mrzInfo.dateOfBirthCheckDigit +
|
||||
mrzInfo.gender.substring(0, 1) +
|
||||
mrzInfo.dateOfExpiry +
|
||||
mrzInfo.dateOfExpiryCheckDigit +
|
||||
mrzInfo.optionalData1 +
|
||||
mrzInfo.compositeCheckDigit;
|
||||
|
||||
// Transforms the dataHashes object into an array of arrays
|
||||
const dataHashesAsArray = 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));
|
||||
|
||||
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));
|
||||
|
||||
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();
|
||||
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<FRATAVERNIER<<FLORENT<HUGUES<JEAN<<<<<<<<<\n19HA348284FRA0007191M2912095<<<<<<<<<<<<<<02';
|
||||
console.log('constructedEContent', constructedEContent);
|
||||
console.log('eContent', eContent);
|
||||
console.log('Are they equal ?', arraysAreEqual(constructedEContent, eContent));
|
||||
|
||||
// // Convert the MRZ information to a Buffer
|
||||
// const mrzBuffer = Buffer.from(mrz);
|
||||
// now let's verify the signature
|
||||
|
||||
// // Create a SHA-256 hash of the MRZ information
|
||||
// const hash = crypto.createHash('sha256').update(mrzBuffer).digest('hex');
|
||||
// Create the public key
|
||||
const rsa = forge.pki.rsa;
|
||||
const publicKey = rsa.setPublicKey(
|
||||
new forge.jsbn.BigInteger(modulusHex, 16),
|
||||
new forge.jsbn.BigInteger(exponentHex, 16),
|
||||
);
|
||||
|
||||
// console.log(hash);
|
||||
// SHA-256 hash of the eContent
|
||||
const md = forge.md.sha256.create();
|
||||
md.update(forge.util.binary.raw.encode(new Uint8Array(constructedEContent)));
|
||||
const hashOfEContent = md.digest().getBytes();
|
||||
|
||||
// let sodFile = {
|
||||
// digestAlgorithm: 'sha256',
|
||||
// // assuming dataGroupHashes is an array of data groups. Initialize it as needed
|
||||
// dataGroupHashes: [],
|
||||
// };
|
||||
// Signature verification
|
||||
const signatureBytes = encryptedDigest.toString('binary');
|
||||
const valid = publicKey.verify(hashOfEContent, signatureBytes);
|
||||
|
||||
// let dg1File = {
|
||||
// encoded: Buffer.from([
|
||||
// 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,
|
||||
// ]),
|
||||
// };
|
||||
|
||||
// // dataGroupHashes["1"] c'est dg1.encoded (hash du DG1 ?)
|
||||
|
||||
// let digest = crypto.createHash(sodFile.digestAlgorithm);
|
||||
// let dg1Hash = digest.update(dg1File.encoded).digest();
|
||||
|
||||
// console.log('dg1Hash:', dg1Hash.toString('hex'));
|
||||
|
||||
// function encodeDg1File(dg1File: any) {
|
||||
// // Convert the MRZ Info to a string in the MRZ format
|
||||
// let mrzString =
|
||||
// dg1File.mrzInfo.documentCode +
|
||||
// dg1File.mrzInfo.issuingState +
|
||||
// dg1File.mrzInfo.primaryIdentifier +
|
||||
// '<<' +
|
||||
// dg1File.mrzInfo.secondaryIdentifier +
|
||||
// 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;
|
||||
|
||||
// // Replace < characters with ASCII code for <
|
||||
// mrzString = mrzString.replace(/</g, String.fromCharCode(60));
|
||||
|
||||
// // Create a new array of ASCII codes from the MRZ string
|
||||
// let encoded = [];
|
||||
// for (let i = 0; i < mrzString.length; i++) {
|
||||
// encoded.push(mrzString.charCodeAt(i));
|
||||
// }
|
||||
|
||||
// // Return the encoded array
|
||||
// return encoded;
|
||||
// }
|
||||
|
||||
// const encoded = encodeDg1File(dg1File);
|
||||
|
||||
// const encodedString = encoded.map(code => 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<<FLORENT<HUGUES<JEAN<<<<<<<<<19HA34828FRA000719MALE291209<<<<<<<<<<<<<<0
|
||||
// a[_XP<FRATAVERNIER<<FLORENT<HUGUES<JEAN<<<<<<<<<19HA348284FRA0007191M2912095<<<<<<<<<<<<<<02
|
||||
|
||||
@@ -1,151 +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<HUGUES<JEAN<<<<<<<<<',
|
||||
},
|
||||
tag: 97,
|
||||
};
|
||||
const mrzInfo = dg1File.mrzInfo;
|
||||
|
||||
// 'P<FRATAVERNIER<<FLORENT<HUGUES<JEAN<<<<<<<<<19HA348284FRA0007191M2912095<<<<<<<<<<<<<<02';
|
||||
const mrz =
|
||||
mrzInfo.documentCode +
|
||||
'<' +
|
||||
mrzInfo.issuingState +
|
||||
mrzInfo.primaryIdentifier +
|
||||
'<<' +
|
||||
mrzInfo.secondaryIdentifier +
|
||||
mrzInfo.documentNumber +
|
||||
mrzInfo.documentNumberCheckDigit +
|
||||
mrzInfo.nationality +
|
||||
mrzInfo.dateOfBirth +
|
||||
mrzInfo.dateOfBirthCheckDigit +
|
||||
mrzInfo.gender.substring(0, 1) +
|
||||
mrzInfo.dateOfExpiry +
|
||||
mrzInfo.dateOfExpiryCheckDigit +
|
||||
mrzInfo.optionalData1 +
|
||||
mrzInfo.compositeCheckDigit;
|
||||
|
||||
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 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,
|
||||
];
|
||||
|
||||
// Transforms the dataHashes object into an array of arrays
|
||||
const dataHashesAsArray = 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));
|
||||
|
||||
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);
|
||||
@@ -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);
|
||||
14
app/scripts/utils.ts
Normal file
14
app/scripts/utils.ts
Normal file
@@ -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;
|
||||
}
|
||||
2574
app/server/data.json
2574
app/server/data.json
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"length": 2269,
|
||||
"tag": 119
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/body-parser": "^1.19.2",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/node": "^20.4.5",
|
||||
"body-parser": "^1.20.2",
|
||||
"express": "^4.18.2",
|
||||
"fs": "^0.0.1-security",
|
||||
"typescript": "^5.1.6"
|
||||
}
|
||||
}
|
||||
@@ -7,16 +7,25 @@ const app = express();
|
||||
// parse application/json
|
||||
app.use(bodyParser.json());
|
||||
|
||||
app.post('/data', (req: Request, res: Response) => {
|
||||
app.post('/post', (req: Request, res: Response) => {
|
||||
const data = req.body;
|
||||
// console.log('data:', data);
|
||||
console.log('typeof data:', typeof data);
|
||||
fs.writeFile('data2.json', JSON.stringify(data, null, 2), err => {
|
||||
fs.writeFile('passportData.json', JSON.stringify(data, null, 2), err => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
res.status(500).send('An error occurred while writing file');
|
||||
res.status(500).json({message: 'An error occurred while writing file'});
|
||||
} else {
|
||||
res.send('File written successfully');
|
||||
res.json({message: 'File written successfully'});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/passportData', (req: Request, res: Response) => {
|
||||
fs.readFile('passportData.json', (err, data) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
res.status(500).json({message: 'An error occurred while reading file'});
|
||||
} else {
|
||||
res.json(JSON.parse(data.toString()));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
||||
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
||||
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
||||
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
@@ -1,531 +0,0 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/body-parser@*", "@types/body-parser@^1.19.2":
|
||||
version "1.19.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
|
||||
integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==
|
||||
dependencies:
|
||||
"@types/connect" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/connect@*":
|
||||
version "3.4.35"
|
||||
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
|
||||
integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/express-serve-static-core@^4.17.33":
|
||||
version "4.17.35"
|
||||
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz#c95dd4424f0d32e525d23812aa8ab8e4d3906c4f"
|
||||
integrity sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/qs" "*"
|
||||
"@types/range-parser" "*"
|
||||
"@types/send" "*"
|
||||
|
||||
"@types/express@^4.17.17":
|
||||
version "4.17.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4"
|
||||
integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==
|
||||
dependencies:
|
||||
"@types/body-parser" "*"
|
||||
"@types/express-serve-static-core" "^4.17.33"
|
||||
"@types/qs" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/http-errors@*":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65"
|
||||
integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==
|
||||
|
||||
"@types/mime@*":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10"
|
||||
integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
||||
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
|
||||
|
||||
"@types/node@*", "@types/node@^20.4.5":
|
||||
version "20.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.5.tgz#9dc0a5cb1ccce4f7a731660935ab70b9c00a5d69"
|
||||
integrity sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg==
|
||||
|
||||
"@types/qs@*":
|
||||
version "6.9.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
|
||||
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
|
||||
|
||||
"@types/range-parser@*":
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
|
||||
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
|
||||
|
||||
"@types/send@*":
|
||||
version "0.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301"
|
||||
integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==
|
||||
dependencies:
|
||||
"@types/mime" "^1"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/serve-static@*":
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.2.tgz#3e5419ecd1e40e7405d34093f10befb43f63381a"
|
||||
integrity sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==
|
||||
dependencies:
|
||||
"@types/http-errors" "*"
|
||||
"@types/mime" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
accepts@~1.3.8:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
||||
dependencies:
|
||||
mime-types "~2.1.34"
|
||||
negotiator "0.6.3"
|
||||
|
||||
array-flatten@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
|
||||
|
||||
body-parser@1.20.1:
|
||||
version "1.20.1"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
|
||||
integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.4"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
on-finished "2.4.1"
|
||||
qs "6.11.0"
|
||||
raw-body "2.5.1"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
|
||||
body-parser@^1.20.2:
|
||||
version "1.20.2"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
|
||||
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.5"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
on-finished "2.4.1"
|
||||
qs "6.11.0"
|
||||
raw-body "2.5.2"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
|
||||
bytes@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
|
||||
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
||||
|
||||
call-bind@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.0.2"
|
||||
|
||||
content-disposition@0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
|
||||
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
|
||||
dependencies:
|
||||
safe-buffer "5.2.1"
|
||||
|
||||
content-type@~1.0.4, content-type@~1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
|
||||
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
|
||||
|
||||
cookie-signature@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
|
||||
|
||||
cookie@0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
|
||||
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
|
||||
|
||||
debug@2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
depd@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||
|
||||
destroy@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
|
||||
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
|
||||
|
||||
etag@~1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||
|
||||
express@^4.18.2:
|
||||
version "4.18.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
|
||||
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.1"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.5.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "1.2.0"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
merge-descriptors "1.0.1"
|
||||
methods "~1.1.2"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.7"
|
||||
proxy-addr "~2.0.7"
|
||||
qs "6.11.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.2.1"
|
||||
send "0.18.0"
|
||||
serve-static "1.15.0"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
type-is "~1.6.18"
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
finalhandler@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
|
||||
integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
statuses "2.0.1"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
|
||||
|
||||
fs@^0.0.1-security:
|
||||
version "0.0.1-security"
|
||||
resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4"
|
||||
integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
get-intrinsic@^1.0.2:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82"
|
||||
integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-proto "^1.0.1"
|
||||
has-symbols "^1.0.3"
|
||||
|
||||
has-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
|
||||
integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
|
||||
|
||||
has-symbols@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
http-errors@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
|
||||
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
|
||||
dependencies:
|
||||
depd "2.0.0"
|
||||
inherits "2.0.4"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
toidentifier "1.0.1"
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
inherits@2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
|
||||
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@~2.1.24, mime-types@~2.1.34:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mime@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
|
||||
|
||||
ms@2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
negotiator@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
|
||||
|
||||
object-inspect@^1.9.0:
|
||||
version "1.12.3"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
|
||||
integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
|
||||
|
||||
on-finished@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
|
||||
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
parseurl@~1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
|
||||
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
||||
|
||||
proxy-addr@~2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
|
||||
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
|
||||
dependencies:
|
||||
forwarded "0.2.0"
|
||||
ipaddr.js "1.9.1"
|
||||
|
||||
qs@6.11.0:
|
||||
version "6.11.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
||||
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
|
||||
dependencies:
|
||||
side-channel "^1.0.4"
|
||||
|
||||
range-parser@~1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raw-body@2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
|
||||
integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
raw-body@2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
|
||||
integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
safe-buffer@5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
send@0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
|
||||
integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
mime "1.6.0"
|
||||
ms "2.1.3"
|
||||
on-finished "2.4.1"
|
||||
range-parser "~1.2.1"
|
||||
statuses "2.0.1"
|
||||
|
||||
serve-static@1.15.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
|
||||
integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
|
||||
dependencies:
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.3"
|
||||
send "0.18.0"
|
||||
|
||||
setprototypeof@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
|
||||
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
|
||||
|
||||
side-channel@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
get-intrinsic "^1.0.2"
|
||||
object-inspect "^1.9.0"
|
||||
|
||||
statuses@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
|
||||
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
|
||||
|
||||
toidentifier@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
|
||||
|
||||
type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||
dependencies:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typescript@^5.1.6:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
|
||||
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
|
||||
|
||||
utils-merge@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
|
||||
|
||||
vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
@@ -14,3 +14,8 @@ export function checkInputs(
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function getFirstName(mrzInfo: any): string {
|
||||
const firstName = mrzInfo.secondaryIdentifier.split('<')[0];
|
||||
return firstName.charAt(0).toUpperCase() + firstName.slice(1).toLowerCase();
|
||||
}
|
||||
|
||||
@@ -2335,6 +2335,23 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*":
|
||||
version "20.4.4"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-20.4.4.tgz"
|
||||
integrity sha512-CukZhumInROvLq3+b5gLev+vgpsIqC2D0deQr/yS1WnxvmYLlJXZpaQrQiseMY+6xusl79E04UjWoqyr+t1/Ew==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
||||
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
|
||||
|
||||
"@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.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.5.tgz#9dc0a5cb1ccce4f7a731660935ab70b9c00a5d69"
|
||||
@@ -2559,7 +2576,7 @@ abort-controller@^3.0.0:
|
||||
dependencies:
|
||||
event-target-shim "^5.0.0"
|
||||
|
||||
accepts@^1.3.7, accepts@^1.3.8, accepts@~1.3.5, accepts@~1.3.7, accepts@~1.3.8:
|
||||
accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.7, accepts@~1.3.8:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
||||
@@ -2769,15 +2786,6 @@ asap@~2.0.3, asap@~2.0.6:
|
||||
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
|
||||
integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
|
||||
|
||||
asn1js@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38"
|
||||
integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==
|
||||
dependencies:
|
||||
pvtsutils "^1.3.2"
|
||||
pvutils "^1.1.3"
|
||||
tslib "^2.4.0"
|
||||
|
||||
ast-types@0.15.2:
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.15.2.tgz#39ae4809393c4b16df751ee563411423e85fb49d"
|
||||
@@ -3019,7 +3027,7 @@ blueimp-md5@^2.10.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0"
|
||||
integrity sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==
|
||||
|
||||
|
||||
body-parser@1.20.1:
|
||||
version "1.20.1"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
|
||||
@@ -4292,6 +4300,43 @@ express@^4.18.2:
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
express@^4.18.2:
|
||||
version "4.18.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
|
||||
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.1"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.5.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "1.2.0"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
merge-descriptors "1.0.1"
|
||||
methods "~1.1.2"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.7"
|
||||
proxy-addr "~2.0.7"
|
||||
qs "6.11.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.2.1"
|
||||
send "0.18.0"
|
||||
serve-static "1.15.0"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
type-is "~1.6.18"
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
@@ -6036,7 +6081,7 @@ md5hex@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/md5hex/-/md5hex-1.0.0.tgz#ed74b477a2ee9369f75efee2f08d5915e52a42e8"
|
||||
integrity sha512-c2YOUbp33+6thdCUi34xIyOU/a7bvGKj/3DB1iaPMTuPHf/Q2d5s4sn1FaCOO43XkXggnb08y5W2PU8UNYNLKQ==
|
||||
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
@@ -6057,6 +6102,11 @@ merge-descriptors@1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
@@ -7094,7 +7144,7 @@ pump@^3.0.0:
|
||||
dependencies:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||
@@ -7105,13 +7155,6 @@ pure-rand@^6.0.0:
|
||||
resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306"
|
||||
integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==
|
||||
|
||||
pvtsutils@^1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.2.tgz#9f8570d132cdd3c27ab7d51a2799239bf8d8d5de"
|
||||
integrity sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
pvutils@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3"
|
||||
@@ -7216,8 +7259,7 @@ react-native-fs@^2.20.0:
|
||||
resolved "https://registry.yarnpkg.com/react-native-fs/-/react-native-fs-2.20.0.tgz#05a9362b473bfc0910772c0acbb73a78dbc810f6"
|
||||
integrity sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==
|
||||
dependencies:
|
||||
base-64 "^0.1.0"
|
||||
utf8 "^3.0.0"
|
||||
dotenv "^16.3.1"
|
||||
|
||||
react-native-passport-reader@^1.0.3:
|
||||
version "1.0.3"
|
||||
@@ -8381,7 +8423,7 @@ universalify@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
|
||||
universalify@^1.0.0:
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
|
||||
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
|
||||
@@ -8429,11 +8471,6 @@ use-sync-external-store@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
|
||||
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||
|
||||
utf8@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1"
|
||||
integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
|
||||
Reference in New Issue
Block a user