mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
clean scripts and frontend
This commit is contained in:
138
app/scripts/mrzToSig.ts
Normal file
138
app/scripts/mrzToSig.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import * as crypto from 'crypto';
|
||||
import {
|
||||
arraysAreEqual,
|
||||
dataHashesObjToArray,
|
||||
formatMrz,
|
||||
assembleMrz,
|
||||
findTimeOfSignature,
|
||||
parsePubKeyString,
|
||||
} from '../utils/utils';
|
||||
import * as forge from 'node-forge';
|
||||
import passportData from '../server/passportData.json';
|
||||
|
||||
// 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);
|
||||
|
||||
console.log('mrz: ', mrz);
|
||||
|
||||
// Transforms the dataHashes object into an array of arrays
|
||||
const dataHashesAsArray = dataHashesObjToArray(passportData.dataGroupHashes);
|
||||
|
||||
const formmattedMrz = formatMrz(mrz);
|
||||
|
||||
const hash = crypto.createHash('sha256');
|
||||
hash.update(Buffer.from(formmattedMrz));
|
||||
const mrzHash = Array.from(hash.digest()).map(x => (x < 128 ? x : x - 256));
|
||||
|
||||
console.log('mrzHash:', mrzHash);
|
||||
console.log('dataHashesAsArray[0][1]:', dataHashesAsArray[0][1]);
|
||||
console.log(
|
||||
'Are they equal ?',
|
||||
arraysAreEqual(mrzHash, dataHashesAsArray[0][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,
|
||||
],
|
||||
);
|
||||
|
||||
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,
|
||||
),
|
||||
);
|
||||
|
||||
// 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));
|
||||
|
||||
// Now let's reconstruct the eContent
|
||||
|
||||
const constructedEContent = [];
|
||||
|
||||
// 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]);
|
||||
|
||||
// 1.2.840.113549.1.9.3 is RFC_3369_CONTENT_TYPE_OID
|
||||
constructedEContent.push(
|
||||
...[48, 21, 6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 3],
|
||||
);
|
||||
// 2.23.136.1.1.1 is ldsSecurityObject
|
||||
constructedEContent.push(...[49, 8, 6, 6, 103, -127, 8, 1, 1, 1]);
|
||||
|
||||
// 1.2.840.113549.1.9.5 is signing-time
|
||||
constructedEContent.push(
|
||||
...[48, 28, 6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 5],
|
||||
);
|
||||
// time of the signature
|
||||
constructedEContent.push(
|
||||
...findTimeOfSignature(passportData.eContentDecomposed),
|
||||
);
|
||||
// 1.2.840.113549.1.9.4 is RFC_3369_MESSAGE_DIGEST_OID
|
||||
constructedEContent.push(
|
||||
...[48, 47, 6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 4],
|
||||
);
|
||||
// TAG and length of the message digest
|
||||
constructedEContent.push(...[49, 34, 4, 32]);
|
||||
|
||||
constructedEContent.push(...concatenatedDataHashesHashDigest);
|
||||
|
||||
console.log('constructedEContent', constructedEContent);
|
||||
console.log('passportData.eContent', passportData.eContent);
|
||||
console.log(
|
||||
'Are they equal ?',
|
||||
arraysAreEqual(constructedEContent, passportData.eContent),
|
||||
);
|
||||
|
||||
// now let's verify the signature
|
||||
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),
|
||||
);
|
||||
|
||||
// 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();
|
||||
|
||||
// Signature verification
|
||||
const signatureBytes = Buffer.from(passportData.encryptedDigest).toString(
|
||||
'binary',
|
||||
);
|
||||
const valid = publicKey.verify(hashOfEContent, signatureBytes);
|
||||
|
||||
if (valid) {
|
||||
console.log('The signature is valid.');
|
||||
} else {
|
||||
console.log('The signature is not valid.');
|
||||
}
|
||||
Reference in New Issue
Block a user