mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
simplify PassportData format
This commit is contained in:
26
app/App.tsx
26
app/App.tsx
@@ -38,7 +38,7 @@ import {computeAndCheckEContent} from './utils/computeEContent';
|
||||
console.log('DEFAULT_PNUMBER', DEFAULT_PNUMBER);
|
||||
|
||||
const CACHE_DATA_IN_LOCAL_SERVER = true;
|
||||
const SKIP_SCAN = true;
|
||||
const SKIP_SCAN = false;
|
||||
|
||||
function App(): JSX.Element {
|
||||
const isDarkMode = useColorScheme() === 'dark';
|
||||
@@ -78,35 +78,26 @@ function App(): JSX.Element {
|
||||
|
||||
async function handleResponse(response: any) {
|
||||
const {
|
||||
mrzInfo,
|
||||
publicKey,
|
||||
publicKeyPEM,
|
||||
mrz,
|
||||
modulus,
|
||||
dataGroupHashes,
|
||||
eContent,
|
||||
encryptedDigest,
|
||||
contentBytes,
|
||||
eContentDecomposed,
|
||||
} = response;
|
||||
|
||||
const passportData: PassportData = {
|
||||
mrzInfo: JSON.parse(mrzInfo),
|
||||
publicKey: publicKey,
|
||||
publicKeyPEM: publicKeyPEM,
|
||||
mrz: mrz,
|
||||
modulus: modulus,
|
||||
dataGroupHashes: dataHashesObjToArray(JSON.parse(dataGroupHashes)),
|
||||
eContent: JSON.parse(eContent),
|
||||
encryptedDigest: JSON.parse(encryptedDigest),
|
||||
contentBytes: JSON.parse(contentBytes),
|
||||
eContentDecomposed: JSON.parse(eContentDecomposed),
|
||||
};
|
||||
|
||||
console.log('mrzInfo', passportData.mrzInfo);
|
||||
console.log('publicKey', passportData.publicKey);
|
||||
console.log('publicKeyPEM', passportData.publicKeyPEM);
|
||||
console.log('mrz', passportData.mrz);
|
||||
console.log('modulus', passportData.modulus);
|
||||
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);
|
||||
|
||||
setPassportData(passportData);
|
||||
|
||||
@@ -143,6 +134,7 @@ function App(): JSX.Element {
|
||||
dateOfBirth: dateOfBirth,
|
||||
dateOfExpiry: dateOfExpiry,
|
||||
});
|
||||
console.log('response', response);
|
||||
console.log('scanned');
|
||||
handleResponse(response);
|
||||
} catch (e) {
|
||||
@@ -265,7 +257,7 @@ function App(): JSX.Element {
|
||||
<View style={styles.sectionContainer}>
|
||||
<Text style={styles.header}>Connection successful</Text>
|
||||
<Text style={styles.header}>
|
||||
Hi {getFirstName(passportData?.mrzInfo)} !{' '}
|
||||
{passportData && `Hi ${getFirstName(passportData.mrz)} ! `}
|
||||
</Text>
|
||||
<Text style={styles.header}>Input your address or ens</Text>
|
||||
<TextInput
|
||||
|
||||
@@ -76,6 +76,7 @@ import java.security.cert.X509Certificate
|
||||
import java.security.spec.MGF1ParameterSpec
|
||||
import java.security.spec.PSSParameterSpec
|
||||
import java.text.ParseException
|
||||
import java.security.interfaces.RSAPublicKey
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.security.PublicKey
|
||||
@@ -505,18 +506,15 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
|
||||
val eContentAsn1InputStream = ASN1InputStream(sodFile.eContent.inputStream())
|
||||
val eContentDecomposed: ASN1Primitive = eContentAsn1InputStream.readObject()
|
||||
val rsaPublicKey = sodFile.docSigningCertificate.publicKey as RSAPublicKey
|
||||
|
||||
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("mrz", mrzInfo.toString())
|
||||
passport.putString("modulus", rsaPublicKey.modulus.toString())
|
||||
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))
|
||||
|
||||
@@ -524,13 +522,14 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
// 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)
|
||||
passport.putMap("photo", photo)
|
||||
|
||||
// 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)
|
||||
// passport.putMap("photo", photo)
|
||||
// passport.putString("dg2File", gson.toJson(dg2File))
|
||||
|
||||
scanPromise?.resolve(passport)
|
||||
resetState()
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import {DataHash} from '../types/passportData';
|
||||
// This script tests the whole flow from MRZ to signature
|
||||
// The passportData is imported from passportData.json written by the server
|
||||
|
||||
const mrz = assembleMrz(passportData.mrzInfo);
|
||||
const mrz = passportData.mrz;
|
||||
|
||||
console.log('mrz: ', mrz);
|
||||
|
||||
@@ -26,9 +26,8 @@ const dataHashes = passportData.dataGroupHashes as DataHash[];
|
||||
const mrzHash = hash(formatMrz(mrz));
|
||||
|
||||
console.log('mrzHash:', mrzHash);
|
||||
console.log('dataHashes[0][1]:', dataHashes[0][1]);
|
||||
console.log(
|
||||
'Are they equal ?',
|
||||
'mrzHash === dataHashes[0][1] ?',
|
||||
arraysAreEqual(mrzHash, dataHashes[0][1] as number[]),
|
||||
);
|
||||
|
||||
@@ -37,50 +36,31 @@ const concatenatedDataHashes = formatAndConcatenateDataHashes(
|
||||
dataHashes,
|
||||
);
|
||||
|
||||
console.log('concatenatedDataHashes', concatenatedDataHashes);
|
||||
console.log(
|
||||
'passportData.contentBytes.content.string',
|
||||
passportData.contentBytes.content.string,
|
||||
);
|
||||
console.log(
|
||||
'Are they equal ?',
|
||||
arraysAreEqual(
|
||||
concatenatedDataHashes,
|
||||
passportData.contentBytes.content.string,
|
||||
),
|
||||
);
|
||||
|
||||
const concatenatedDataHashesHashDigest = hash(concatenatedDataHashes);
|
||||
|
||||
const timeOfSignature = findTimeOfSignature(passportData.eContentDecomposed);
|
||||
// check that concatenatedDataHashesHashDigest is at the right place of passportData.eContent
|
||||
const sliceOfEContent = passportData.eContent.slice(72, 72 + 32);
|
||||
|
||||
const eContent = assembleEContent(
|
||||
concatenatedDataHashesHashDigest,
|
||||
timeOfSignature,
|
||||
);
|
||||
|
||||
console.log('eContent reconstructed', eContent);
|
||||
console.log('passportData.eContent', passportData.eContent);
|
||||
console.log(
|
||||
'Are they equal ?',
|
||||
arraysAreEqual(eContent, passportData.eContent),
|
||||
arraysAreEqual(sliceOfEContent, concatenatedDataHashesHashDigest),
|
||||
);
|
||||
|
||||
// now let's verify the signature
|
||||
const {modulus, exponent} = parsePubKeyString(passportData.publicKey);
|
||||
// const {modulus, exponent} = parsePubKeyString(passportData.publicKey);
|
||||
// Create the public key
|
||||
const rsa = forge.pki.rsa;
|
||||
const publicKey = rsa.setPublicKey(
|
||||
new forge.jsbn.BigInteger(modulus, 16),
|
||||
new forge.jsbn.BigInteger(exponent, 16),
|
||||
new forge.jsbn.BigInteger(passportData.modulus, 10),
|
||||
new forge.jsbn.BigInteger("10001", 16),
|
||||
);
|
||||
|
||||
// SHA-256 hash of the eContent
|
||||
const md = forge.md.sha256.create();
|
||||
md.update(forge.util.binary.raw.encode(new Uint8Array(eContent)));
|
||||
md.update(forge.util.binary.raw.encode(new Uint8Array(passportData.eContent)));
|
||||
const hashOfEContent = md.digest().getBytes();
|
||||
|
||||
console.log('modulus', hexToDecimal(modulus));
|
||||
console.log('modulus', passportData.modulus);
|
||||
console.log('eContent', bytesToBigDecimal(passportData.eContent));
|
||||
console.log('signature', bytesToBigDecimal(passportData.encryptedDigest));
|
||||
// Convert the hash to a single decimal number
|
||||
@@ -106,7 +86,6 @@ function hash(bytesArray: number[]): number[] {
|
||||
hash.update(Buffer.from(bytesArray));
|
||||
return Array.from(hash.digest()).map(x => (x < 128 ? x : x - 256));
|
||||
}
|
||||
|
||||
function bytesToBigDecimal(arr: number[]): string {
|
||||
let result = BigInt(0);
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
|
||||
@@ -19,12 +19,9 @@ export type MrzInfo = {
|
||||
export type DataHash = [number, number[]];
|
||||
|
||||
export type PassportData = {
|
||||
mrzInfo: MrzInfo;
|
||||
publicKey: any;
|
||||
publicKeyPEM: string;
|
||||
mrz: string;
|
||||
modulus: string;
|
||||
dataGroupHashes: DataHash[];
|
||||
eContent: any;
|
||||
encryptedDigest: any;
|
||||
contentBytes: any;
|
||||
eContentDecomposed: any;
|
||||
eContent: number[];
|
||||
encryptedDigest: number[];
|
||||
};
|
||||
|
||||
@@ -15,7 +15,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();
|
||||
}
|
||||
export function getFirstName(mrz: string): string {
|
||||
const names = mrz.split("<<");
|
||||
const firstName = names[1].split("<")[0].trim();
|
||||
return firstName || "Unknown";
|
||||
}
|
||||
Reference in New Issue
Block a user