mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
feat: mock data sha1_ecdsa p256
This commit is contained in:
136
common/scripts/passportData/sha1_ecdsa.ts
Normal file
136
common/scripts/passportData/sha1_ecdsa.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import assert from 'assert';
|
||||
import { PassportData } from '../../../common/src/utils/types';
|
||||
import {
|
||||
hash,
|
||||
assembleEContent,
|
||||
formatAndConcatenateDataHashes,
|
||||
formatMrz,
|
||||
arraysAreEqual,
|
||||
findSubarrayIndex,
|
||||
} from '../../../common/src/utils/utils';
|
||||
import * as forge from 'node-forge';
|
||||
import { writeFileSync } from 'fs';
|
||||
import elliptic from 'elliptic';
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
const sampleMRZ =
|
||||
'P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02';
|
||||
const sampleDataHashes = [
|
||||
[
|
||||
2,
|
||||
[
|
||||
-66, 82, -76, -21, -34, 33, 79, 50, -104, -120, -114, 35, 116, -32, 6, -14, -100, -115, -128,
|
||||
-8, 10, 61, 98, 86, -8, 45, -49, -46, 90, -24, -81, 38,
|
||||
],
|
||||
],
|
||||
[
|
||||
3,
|
||||
[
|
||||
0, -62, 104, 108, -19, -10, 97, -26, 116, -58, 69, 110, 26, 87, 17, 89, 110, -57, 108, -6, 36,
|
||||
21, 39, 87, 110, 102, -6, -43, -82, -125, -85, -82,
|
||||
],
|
||||
],
|
||||
[
|
||||
11,
|
||||
[
|
||||
-120, -101, 87, -112, 111, 15, -104, 127, 85, 25, -102, 81, 20, 58, 51, 75, -63, 116, -22, 0,
|
||||
60, 30, 29, 30, -73, -115, 72, -9, -1, -53, 100, 124,
|
||||
],
|
||||
],
|
||||
[
|
||||
12,
|
||||
[
|
||||
41, -22, 106, 78, 31, 11, 114, -119, -19, 17, 92, 71, -122, 47, 62, 78, -67, -23, -55, -42,
|
||||
53, 4, 47, -67, -55, -123, 6, 121, 34, -125, 64, -114,
|
||||
],
|
||||
],
|
||||
[
|
||||
13,
|
||||
[
|
||||
91, -34, -46, -63, 62, -34, 104, 82, 36, 41, -118, -3, 70, 15, -108, -48, -100, 45, 105, -85,
|
||||
-15, -61, -71, 43, -39, -94, -110, -55, -34, 89, -18, 38,
|
||||
],
|
||||
],
|
||||
[
|
||||
14,
|
||||
[
|
||||
76, 123, -40, 13, 51, -29, 72, -11, 59, -63, -18, -90, 103, 49, 23, -92, -85, -68, -62, -59,
|
||||
-100, -69, -7, 28, -58, 95, 69, 15, -74, 56, 54, 38,
|
||||
],
|
||||
],
|
||||
] as [number, number[]][];
|
||||
const signatureAlgorithm = 'ecdsa-with-SHA1';
|
||||
const hashLen = 20;
|
||||
|
||||
export function genMockPassportData_sha1WithECDSA(): PassportData {
|
||||
const mrzHash = hash(signatureAlgorithm, formatMrz(sampleMRZ));
|
||||
sampleDataHashes.unshift([1, mrzHash]);
|
||||
const concatenatedDataHashes = formatAndConcatenateDataHashes(
|
||||
[[1, mrzHash], ...sampleDataHashes],
|
||||
hashLen,
|
||||
33 // ? TODO replace with original dg1HashOffset
|
||||
);
|
||||
const eContent = assembleEContent(hash(signatureAlgorithm, concatenatedDataHashes));
|
||||
|
||||
const ec = new elliptic.ec('p256');
|
||||
const keyPair = ec.genKeyPair();
|
||||
const pubKey = keyPair.getPublic();
|
||||
|
||||
const md = forge.md.sha1.create();
|
||||
md.update(forge.util.binary.raw.encode(new Uint8Array(eContent)));
|
||||
const signature = keyPair.sign(md.digest().toHex(), 'hex');
|
||||
const signatureBytes = Array.from(Buffer.from(signature.toDER(), 'hex'));
|
||||
|
||||
const Qx = pubKey.getX().toString(16);
|
||||
const Qy = pubKey.getY().toString(16);
|
||||
|
||||
return {
|
||||
mrz: sampleMRZ,
|
||||
signatureAlgorithm: signatureAlgorithm,
|
||||
pubKey: {
|
||||
publicKeyQ: `(${Qx},${Qy},1,fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc)`,
|
||||
},
|
||||
dataGroupHashes: concatenatedDataHashes,
|
||||
eContent: eContent,
|
||||
encryptedDigest: signatureBytes,
|
||||
photoBase64: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3...',
|
||||
};
|
||||
}
|
||||
|
||||
function verify(passportData: PassportData): boolean {
|
||||
const { mrz, signatureAlgorithm, pubKey, dataGroupHashes, eContent, encryptedDigest } =
|
||||
passportData;
|
||||
const formattedMrz = formatMrz(mrz);
|
||||
const mrzHash = hash(signatureAlgorithm, formattedMrz);
|
||||
const dg1HashOffset = findSubarrayIndex(dataGroupHashes, mrzHash);
|
||||
console.log('dg1HashOffset', dg1HashOffset);
|
||||
assert(dg1HashOffset !== -1, 'MRZ hash index not found in dataGroupHashes');
|
||||
|
||||
const concatHash = hash(signatureAlgorithm, dataGroupHashes);
|
||||
assert(
|
||||
arraysAreEqual(concatHash, eContent.slice(eContent.length - concatHash.length)),
|
||||
'concatHash is not at the right place in eContent'
|
||||
);
|
||||
|
||||
const cleanPublicKeyQ = pubKey.publicKeyQ.replace(/[()]/g, '').split(',');
|
||||
const Qx = cleanPublicKeyQ[0];
|
||||
const Qy = cleanPublicKeyQ[1];
|
||||
|
||||
const ec = new elliptic.ec('p256');
|
||||
const key = ec.keyFromPublic({ x: Qx, y: Qy }, 'hex');
|
||||
|
||||
const messageBuffer = Buffer.from(eContent);
|
||||
const msgHash = crypto.createHash('sha1').update(messageBuffer).digest();
|
||||
|
||||
const signature = Buffer.from(encryptedDigest).toString('hex');
|
||||
|
||||
const isValid = key.verify(msgHash, signature);
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
const mockPassportData = genMockPassportData_sha1WithECDSA();
|
||||
console.log('Passport Data:', JSON.stringify(mockPassportData, null, 2));
|
||||
console.log('Signature valid:', verify(mockPassportData));
|
||||
|
||||
writeFileSync(__dirname + '/passportData.json', JSON.stringify(mockPassportData, null, 2));
|
||||
@@ -1,4 +1,5 @@
|
||||
// Sample passport data used for testing
|
||||
// prettier-ignore
|
||||
export const mockPassportData_sha256_rsa_65537 = {
|
||||
"mrz": "P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02",
|
||||
"signatureAlgorithm": "sha256WithRSAEncryption",
|
||||
@@ -629,7 +630,7 @@ export const mockPassportData_sha256_rsa_65537 = {
|
||||
],
|
||||
"photoBase64": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3..."
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
export const mockPassportData_sha1_rsa_65537 = {
|
||||
"mrz": "P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02",
|
||||
"signatureAlgorithm": "sha1WithRSAEncryption",
|
||||
@@ -1105,6 +1106,7 @@ export const mockPassportData_sha1_rsa_65537 = {
|
||||
"photoBase64": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3..."
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
export const mockPassportData_sha256_rsapss_65537 = {
|
||||
"mrz": "P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02",
|
||||
"signatureAlgorithm": "sha256WithRSASSAPSS",
|
||||
@@ -1735,6 +1737,7 @@ export const mockPassportData_sha256_rsapss_65537 = {
|
||||
"photoBase64": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3..."
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
export const mockPassportData_sha384_ecdsa = {
|
||||
"mrz": "P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA04021111M3111115<<<<<<<<<<<<<<02",
|
||||
"signatureAlgorithm": "SHA384withECDSA",
|
||||
@@ -1784,9 +1787,454 @@ export const mockPassportData_sha384_ecdsa = {
|
||||
"photoBase64": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3..."
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
export const mockPassPortData_sha1_ecdsa = {
|
||||
"mrz": "P<FRADUPONT<<ALPHONSE<HUGUES<ALBERT<<<<<<<<<24HB818324FRA0402111M3111115<<<<<<<<<<<<<<02",
|
||||
"signatureAlgorithm": "ecdsa-with-SHA1",
|
||||
"pubKey": {
|
||||
"publicKeyQ": "(da3b0e6d85de52725134db8f916885bb008335d3f5f1b667a3c0daedf0118440,9e18de2795c22a0083600d5b8cd11910beb2774ef090de80f97be85c7bdf5da3,1,fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc)"
|
||||
},
|
||||
"dataGroupHashes": [
|
||||
99,
|
||||
97,
|
||||
54,
|
||||
-115,
|
||||
-13,
|
||||
-30,
|
||||
71,
|
||||
36,
|
||||
-84,
|
||||
41,
|
||||
-81,
|
||||
118,
|
||||
-34,
|
||||
100,
|
||||
-35,
|
||||
26,
|
||||
-55,
|
||||
-124,
|
||||
63,
|
||||
-99,
|
||||
31,
|
||||
-107,
|
||||
-108,
|
||||
40,
|
||||
62,
|
||||
-100,
|
||||
-55,
|
||||
103,
|
||||
-108,
|
||||
115,
|
||||
51,
|
||||
61,
|
||||
-15,
|
||||
-96,
|
||||
114,
|
||||
-93,
|
||||
25,
|
||||
75,
|
||||
70,
|
||||
94,
|
||||
85,
|
||||
95,
|
||||
40,
|
||||
-11,
|
||||
-101,
|
||||
88,
|
||||
-85,
|
||||
-108,
|
||||
-10,
|
||||
-44,
|
||||
104,
|
||||
-62,
|
||||
-117,
|
||||
-96,
|
||||
114,
|
||||
-93,
|
||||
25,
|
||||
75,
|
||||
70,
|
||||
94,
|
||||
85,
|
||||
95,
|
||||
40,
|
||||
-11,
|
||||
-101,
|
||||
88,
|
||||
-85,
|
||||
-108,
|
||||
-10,
|
||||
-44,
|
||||
104,
|
||||
-62,
|
||||
-117,
|
||||
-66,
|
||||
82,
|
||||
-76,
|
||||
-21,
|
||||
-34,
|
||||
33,
|
||||
79,
|
||||
50,
|
||||
-104,
|
||||
-120,
|
||||
-114,
|
||||
35,
|
||||
116,
|
||||
-32,
|
||||
6,
|
||||
-14,
|
||||
-100,
|
||||
-115,
|
||||
-128,
|
||||
-8,
|
||||
10,
|
||||
61,
|
||||
98,
|
||||
86,
|
||||
-8,
|
||||
45,
|
||||
-49,
|
||||
-46,
|
||||
90,
|
||||
-24,
|
||||
-81,
|
||||
38,
|
||||
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,
|
||||
-120,
|
||||
-101,
|
||||
87,
|
||||
-112,
|
||||
111,
|
||||
15,
|
||||
-104,
|
||||
127,
|
||||
85,
|
||||
25,
|
||||
-102,
|
||||
81,
|
||||
20,
|
||||
58,
|
||||
51,
|
||||
75,
|
||||
-63,
|
||||
116,
|
||||
-22,
|
||||
0,
|
||||
60,
|
||||
30,
|
||||
29,
|
||||
30,
|
||||
-73,
|
||||
-115,
|
||||
72,
|
||||
-9,
|
||||
-1,
|
||||
-53,
|
||||
100,
|
||||
124,
|
||||
41,
|
||||
-22,
|
||||
106,
|
||||
78,
|
||||
31,
|
||||
11,
|
||||
114,
|
||||
-119,
|
||||
-19,
|
||||
17,
|
||||
92,
|
||||
71,
|
||||
-122,
|
||||
47,
|
||||
62,
|
||||
78,
|
||||
-67,
|
||||
-23,
|
||||
-55,
|
||||
-42,
|
||||
53,
|
||||
4,
|
||||
47,
|
||||
-67,
|
||||
-55,
|
||||
-123,
|
||||
6,
|
||||
121,
|
||||
34,
|
||||
-125,
|
||||
64,
|
||||
-114,
|
||||
91,
|
||||
-34,
|
||||
-46,
|
||||
-63,
|
||||
62,
|
||||
-34,
|
||||
104,
|
||||
82,
|
||||
36,
|
||||
41,
|
||||
-118,
|
||||
-3,
|
||||
70,
|
||||
15,
|
||||
-108,
|
||||
-48,
|
||||
-100,
|
||||
45,
|
||||
105,
|
||||
-85,
|
||||
-15,
|
||||
-61,
|
||||
-71,
|
||||
43,
|
||||
-39,
|
||||
-94,
|
||||
-110,
|
||||
-55,
|
||||
-34,
|
||||
89,
|
||||
-18,
|
||||
38,
|
||||
76,
|
||||
123,
|
||||
-40,
|
||||
13,
|
||||
51,
|
||||
-29,
|
||||
72,
|
||||
-11,
|
||||
59,
|
||||
-63,
|
||||
-18,
|
||||
-90,
|
||||
103,
|
||||
49,
|
||||
23,
|
||||
-92,
|
||||
-85,
|
||||
-68,
|
||||
-62,
|
||||
-59,
|
||||
-100,
|
||||
-69,
|
||||
-7,
|
||||
28,
|
||||
-58,
|
||||
95,
|
||||
69,
|
||||
15,
|
||||
-74,
|
||||
56,
|
||||
54,
|
||||
38
|
||||
],
|
||||
"eContent": [
|
||||
49,
|
||||
102,
|
||||
48,
|
||||
21,
|
||||
6,
|
||||
9,
|
||||
42,
|
||||
-122,
|
||||
72,
|
||||
-122,
|
||||
-9,
|
||||
13,
|
||||
1,
|
||||
9,
|
||||
3,
|
||||
49,
|
||||
8,
|
||||
6,
|
||||
6,
|
||||
103,
|
||||
-127,
|
||||
8,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
48,
|
||||
28,
|
||||
6,
|
||||
9,
|
||||
42,
|
||||
-122,
|
||||
72,
|
||||
-122,
|
||||
-9,
|
||||
13,
|
||||
1,
|
||||
9,
|
||||
5,
|
||||
49,
|
||||
15,
|
||||
23,
|
||||
13,
|
||||
49,
|
||||
57,
|
||||
49,
|
||||
50,
|
||||
49,
|
||||
54,
|
||||
49,
|
||||
55,
|
||||
50,
|
||||
50,
|
||||
51,
|
||||
56,
|
||||
90,
|
||||
48,
|
||||
47,
|
||||
6,
|
||||
9,
|
||||
42,
|
||||
-122,
|
||||
72,
|
||||
-122,
|
||||
-9,
|
||||
13,
|
||||
1,
|
||||
9,
|
||||
4,
|
||||
49,
|
||||
34,
|
||||
4,
|
||||
32,
|
||||
95,
|
||||
-126,
|
||||
77,
|
||||
-22,
|
||||
-46,
|
||||
-65,
|
||||
-73,
|
||||
-24,
|
||||
-47,
|
||||
-36,
|
||||
51,
|
||||
-41,
|
||||
-72,
|
||||
-31,
|
||||
-41,
|
||||
-103,
|
||||
-84,
|
||||
-102,
|
||||
-26,
|
||||
-89
|
||||
],
|
||||
"encryptedDigest": [
|
||||
48,
|
||||
69,
|
||||
2,
|
||||
32,
|
||||
97,
|
||||
200,
|
||||
107,
|
||||
237,
|
||||
56,
|
||||
23,
|
||||
80,
|
||||
12,
|
||||
29,
|
||||
163,
|
||||
177,
|
||||
12,
|
||||
251,
|
||||
95,
|
||||
128,
|
||||
248,
|
||||
142,
|
||||
153,
|
||||
227,
|
||||
85,
|
||||
133,
|
||||
14,
|
||||
144,
|
||||
57,
|
||||
240,
|
||||
195,
|
||||
131,
|
||||
135,
|
||||
118,
|
||||
81,
|
||||
124,
|
||||
214,
|
||||
2,
|
||||
33,
|
||||
0,
|
||||
145,
|
||||
109,
|
||||
54,
|
||||
3,
|
||||
120,
|
||||
193,
|
||||
246,
|
||||
48,
|
||||
166,
|
||||
167,
|
||||
62,
|
||||
22,
|
||||
22,
|
||||
125,
|
||||
211,
|
||||
120,
|
||||
51,
|
||||
81,
|
||||
83,
|
||||
132,
|
||||
132,
|
||||
199,
|
||||
205,
|
||||
109,
|
||||
56,
|
||||
232,
|
||||
30,
|
||||
169,
|
||||
251,
|
||||
239,
|
||||
59,
|
||||
2
|
||||
],
|
||||
"photoBase64": "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIw3..."
|
||||
}
|
||||
|
||||
export const mockPassportDatas = [
|
||||
mockPassportData_sha256_rsa_65537,
|
||||
mockPassportData_sha1_rsa_65537,
|
||||
mockPassportData_sha256_rsapss_65537,
|
||||
mockPassPortData_sha1_ecdsa,
|
||||
// mockPassportData_SHA384withECDSA // temp cause formatting of ecdsa key is not done well now
|
||||
]
|
||||
];
|
||||
|
||||
@@ -4,7 +4,7 @@ import { sha1 } from 'js-sha1';
|
||||
import { sha384 } from 'js-sha512';
|
||||
|
||||
export function formatMrz(mrz: string) {
|
||||
const mrzCharcodes = [...mrz].map(char => char.charCodeAt(0));
|
||||
const mrzCharcodes = [...mrz].map((char) => char.charCodeAt(0));
|
||||
|
||||
mrzCharcodes.unshift(88); // the length of the mrz data
|
||||
mrzCharcodes.unshift(95, 31); // the MRZ_INFO_TAG
|
||||
@@ -37,9 +37,10 @@ export function formatAndConcatenateDataHashes(
|
||||
dg1HashOffset: number
|
||||
) {
|
||||
// concatenating dataHashes :
|
||||
let concat: number[] = []
|
||||
let concat: number[] = [];
|
||||
|
||||
const startingSequence = Array.from({length: dg1HashOffset},
|
||||
const startingSequence = Array.from(
|
||||
{ length: dg1HashOffset },
|
||||
() => Math.floor(Math.random() * 256) - 128
|
||||
);
|
||||
|
||||
@@ -69,7 +70,7 @@ export function formatAndConcatenateDataHashes(
|
||||
// 96, -122, 72, 1, 101, 3, 4, 2, 1,
|
||||
// // NULL tag + SEQUENCE + length (117 bytes)
|
||||
// 5, 0, 48, 117,
|
||||
|
||||
|
||||
// SHA384withECDSA (index of mrzhash is 33)
|
||||
// // SEQUENCE + long form indicator + length (313 bytes)
|
||||
// 48, -126, 1, 57,
|
||||
@@ -87,12 +88,12 @@ export function formatAndConcatenateDataHashes(
|
||||
|
||||
// console.log(`startingSequence`, startingSequence.map(byte => (byte < 0 ? byte + 256 : byte).toString(16).padStart(2, '0')).join(''));
|
||||
|
||||
concat.push(...startingSequence)
|
||||
concat.push(...startingSequence);
|
||||
|
||||
for (const dataHash of dataHashes) {
|
||||
// console.log(`dataHash ${dataHash[0]}`, dataHash[1].map(byte => (byte < 0 ? byte + 256 : byte).toString(16).padStart(2, '0')).join(''));
|
||||
|
||||
concat.push(...dataHash[1])
|
||||
concat.push(...dataHash[1]);
|
||||
// concat.push(...[48, hashLen + 5, 2, 1, dataHash[0], 4, hashLen, ...dataHash[1]])
|
||||
// 48, 37, 2, 1, 1, 4, 32,
|
||||
// 48, 53, 2, 1, 1, 4, 48,
|
||||
@@ -101,9 +102,7 @@ export function formatAndConcatenateDataHashes(
|
||||
return concat;
|
||||
}
|
||||
|
||||
export function assembleEContent(
|
||||
messageDigest: number[],
|
||||
) {
|
||||
export function assembleEContent(messageDigest: number[]) {
|
||||
const constructedEContent = [];
|
||||
|
||||
// Detailed description is in private file r&d.ts for now
|
||||
@@ -111,22 +110,16 @@ export function assembleEContent(
|
||||
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],
|
||||
);
|
||||
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],
|
||||
);
|
||||
constructedEContent.push(...[48, 28, 6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 5]);
|
||||
// mock time of signature
|
||||
constructedEContent.push(...[49, 15, 23, 13, 49, 57, 49, 50, 49, 54, 49, 55, 50, 50, 51, 56, 90]);
|
||||
// 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],
|
||||
);
|
||||
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]);
|
||||
|
||||
@@ -139,10 +132,7 @@ export function toUnsigned(byte: number) {
|
||||
}
|
||||
|
||||
export function arraysAreEqual(array1: number[], array2: number[]) {
|
||||
return (
|
||||
array1.length === array2.length &&
|
||||
array1.every((value, index) => value === array2[index])
|
||||
);
|
||||
return array1.length === array2.length && array1.every((value, index) => value === array2[index]);
|
||||
}
|
||||
|
||||
export function toSigned(byte: number) {
|
||||
@@ -150,29 +140,23 @@ export function toSigned(byte: number) {
|
||||
}
|
||||
|
||||
export const toBinaryString = (byte: any) => {
|
||||
const binary = (parseInt(byte, 10) & 0xFF).toString(2).padStart(8, '0');
|
||||
const binary = (parseInt(byte, 10) & 0xff).toString(2).padStart(8, '0');
|
||||
return binary;
|
||||
};
|
||||
|
||||
export function splitToWords(
|
||||
number: bigint,
|
||||
wordsize: bigint,
|
||||
numberElement: bigint
|
||||
) {
|
||||
let t = number
|
||||
const words: string[] = []
|
||||
export function splitToWords(number: bigint, wordsize: bigint, numberElement: bigint) {
|
||||
let t = number;
|
||||
const words: string[] = [];
|
||||
for (let i = BigInt(0); i < numberElement; ++i) {
|
||||
const baseTwo = BigInt(2)
|
||||
const baseTwo = BigInt(2);
|
||||
|
||||
words.push(`${t % BigInt(Math.pow(Number(baseTwo), Number(wordsize)))}`)
|
||||
t = BigInt(t / BigInt(Math.pow(Number(BigInt(2)), Number(wordsize))))
|
||||
words.push(`${t % BigInt(Math.pow(Number(baseTwo), Number(wordsize)))}`);
|
||||
t = BigInt(t / BigInt(Math.pow(Number(BigInt(2)), Number(wordsize))));
|
||||
}
|
||||
if (!(t == BigInt(0))) {
|
||||
throw `Number ${number} does not fit in ${(
|
||||
wordsize * numberElement
|
||||
).toString()} bits`
|
||||
throw `Number ${number} does not fit in ${(wordsize * numberElement).toString()} bits`;
|
||||
}
|
||||
return words
|
||||
return words;
|
||||
}
|
||||
|
||||
export function bytesToBigDecimal(arr: number[]): string {
|
||||
@@ -188,16 +172,31 @@ export function hexToDecimal(hex: string): string {
|
||||
}
|
||||
|
||||
// hash logic here because the one in utils.ts only works with node
|
||||
export function hash(signatureAlgorithm: string, bytesArray: number[]) {
|
||||
const unsignedBytesArray = bytesArray.map(toUnsignedByte);
|
||||
const hash = (signatureAlgorithm == 'sha1WithRSAEncryption')
|
||||
? sha1(unsignedBytesArray)
|
||||
: (signatureAlgorithm == 'SHA384withECDSA')
|
||||
? sha384(unsignedBytesArray)
|
||||
: (signatureAlgorithm == 'sha256WithRSAEncryption' || signatureAlgorithm == 'sha256WithRSASSAPSS')
|
||||
? sha256(unsignedBytesArray)
|
||||
: sha256(unsignedBytesArray); // defaults to sha256
|
||||
return hexToSignedBytes(hash);
|
||||
|
||||
export function hash(signatureAlgorithm: string, bytesArray: number[]): number[] {
|
||||
const unsignedBytesArray = bytesArray.map((byte) => byte & 0xff);
|
||||
let hashResult: string;
|
||||
|
||||
switch (signatureAlgorithm) {
|
||||
case 'sha1WithRSAEncryption':
|
||||
hashResult = sha1(unsignedBytesArray);
|
||||
break;
|
||||
case 'SHA384withECDSA':
|
||||
hashResult = sha384(unsignedBytesArray);
|
||||
break;
|
||||
case 'sha256WithRSAEncryption':
|
||||
hashResult = sha256(unsignedBytesArray);
|
||||
break;
|
||||
case 'sha256WithRSASSAPSS':
|
||||
hashResult = sha256(unsignedBytesArray);
|
||||
break;
|
||||
case 'ecdsa-with-SHA1':
|
||||
hashResult = sha1(unsignedBytesArray);
|
||||
break;
|
||||
default:
|
||||
hashResult = sha256(unsignedBytesArray); // Default to sha256
|
||||
}
|
||||
return hexToSignedBytes(hashResult);
|
||||
}
|
||||
|
||||
export function hexToSignedBytes(hexString: string): number[] {
|
||||
@@ -213,19 +212,20 @@ export function toUnsignedByte(signedByte: number) {
|
||||
return signedByte < 0 ? signedByte + 256 : signedByte;
|
||||
}
|
||||
|
||||
export function formatSigAlgNameForCircuit(
|
||||
sigAlg: string,
|
||||
exponent?: string
|
||||
) {
|
||||
export function formatSigAlgNameForCircuit(sigAlg: string, exponent?: string) {
|
||||
// replace - by _, for instance for ecdsa-with-SHA256
|
||||
sigAlg = sigAlg.replace(/-/g, '_')
|
||||
sigAlg = sigAlg.replace(/-/g, '_');
|
||||
// add exponent, for instance for sha256WithRSAEncryption
|
||||
return exponent ? `${sigAlg}_${exponent}` : sigAlg
|
||||
return exponent ? `${sigAlg}_${exponent}` : sigAlg;
|
||||
}
|
||||
|
||||
export function bigIntToChunkedBytes(num: BigInt | bigint, bytesPerChunk: number, numChunks: number) {
|
||||
export function bigIntToChunkedBytes(
|
||||
num: BigInt | bigint,
|
||||
bytesPerChunk: number,
|
||||
numChunks: number
|
||||
) {
|
||||
const res: string[] = [];
|
||||
const bigintNum: bigint = typeof num == "bigint" ? num : num.valueOf();
|
||||
const bigintNum: bigint = typeof num == 'bigint' ? num : num.valueOf();
|
||||
const msk = (1n << BigInt(bytesPerChunk)) - 1n;
|
||||
for (let i = 0; i < numChunks; ++i) {
|
||||
res.push(((bigintNum >> BigInt(i * bytesPerChunk)) & msk).toString());
|
||||
@@ -240,11 +240,11 @@ export function hexStringToSignedIntArray(hexString: string) {
|
||||
result.push(byte > 127 ? byte - 256 : byte);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export function formatRoot(root: string): string {
|
||||
let rootHex = BigInt(root).toString(16);
|
||||
return rootHex.length % 2 === 0 ? "0x" + rootHex : "0x0" + rootHex;
|
||||
return rootHex.length % 2 === 0 ? '0x' + rootHex : '0x0' + rootHex;
|
||||
}
|
||||
|
||||
export function getCurrentDateYYMMDD(dayDiff: number = 0): number[] {
|
||||
@@ -253,28 +253,28 @@ export function getCurrentDateYYMMDD(dayDiff: number = 0): number[] {
|
||||
const year = date.getUTCFullYear();
|
||||
const month = date.getUTCMonth() + 1;
|
||||
const day = date.getUTCDate();
|
||||
const YY = (`0${year % 100}`).slice(-2);
|
||||
const MM = (`0${month}`).slice(-2);
|
||||
const DD = (`0${day}`).slice(-2);
|
||||
const YY = `0${year % 100}`.slice(-2);
|
||||
const MM = `0${month}`.slice(-2);
|
||||
const DD = `0${day}`.slice(-2);
|
||||
|
||||
const yymmdd = `${YY}${MM}${DD}`;
|
||||
return Array.from(yymmdd).map(char => parseInt(char));
|
||||
return Array.from(yymmdd).map((char) => parseInt(char));
|
||||
}
|
||||
|
||||
export function getHashLen(signatureAlgorithm: string) {
|
||||
switch (signatureAlgorithm) {
|
||||
case "sha1WithRSAEncryption":
|
||||
case "ecdsa-with-SHA1":
|
||||
case 'sha1WithRSAEncryption':
|
||||
case 'ecdsa-with-SHA1':
|
||||
return 20;
|
||||
case "sha256WithRSAEncryption":
|
||||
case "rsassaPss":
|
||||
case "ecdsa-with-SHA256":
|
||||
case 'sha256WithRSAEncryption':
|
||||
case 'rsassaPss':
|
||||
case 'ecdsa-with-SHA256':
|
||||
return 32;
|
||||
case "sha384WithRSAEncryption":
|
||||
case "ecdsa-with-SHA384":
|
||||
case 'sha384WithRSAEncryption':
|
||||
case 'ecdsa-with-SHA384':
|
||||
return 48;
|
||||
case "sha512WithRSAEncryption":
|
||||
case "ecdsa-with-SHA512":
|
||||
case 'sha512WithRSAEncryption':
|
||||
case 'ecdsa-with-SHA512':
|
||||
return 64;
|
||||
default:
|
||||
console.log(`${signatureAlgorithm} not found in getHashLen`);
|
||||
@@ -298,27 +298,24 @@ export function packBytes(unpacked) {
|
||||
return packed;
|
||||
}
|
||||
|
||||
|
||||
export function generateMerkleProof(imt: LeanIMT, _index: number, maxDepth: number) {
|
||||
const { siblings: merkleProofSiblings, index } = imt.generateProof(_index)
|
||||
const depthForThisOne = merkleProofSiblings.length
|
||||
const { siblings: merkleProofSiblings, index } = imt.generateProof(_index);
|
||||
const depthForThisOne = merkleProofSiblings.length;
|
||||
// The index must be converted to a list of indices, 1 for each tree level.
|
||||
// The circuit tree depth is 20, so the number of siblings must be 20, even if
|
||||
// the tree depth is actually 3. The missing siblings can be set to 0, as they
|
||||
// won't be used to calculate the root in the circuit.
|
||||
const merkleProofIndices: number[] = []
|
||||
const merkleProofIndices: number[] = [];
|
||||
|
||||
for (let i = 0; i < maxDepth; i += 1) {
|
||||
merkleProofIndices.push((index >> i) & 1)
|
||||
merkleProofIndices.push((index >> i) & 1);
|
||||
if (merkleProofSiblings[i] === undefined) {
|
||||
merkleProofSiblings[i] = BigInt(0)
|
||||
merkleProofSiblings[i] = BigInt(0);
|
||||
}
|
||||
}
|
||||
return { merkleProofSiblings, merkleProofIndices, depthForThisOne }
|
||||
return { merkleProofSiblings, merkleProofIndices, depthForThisOne };
|
||||
}
|
||||
|
||||
export function findSubarrayIndex(arr: any[], subarray: any[]): number {
|
||||
return arr.findIndex((_, index) =>
|
||||
subarray.every((element, i) => element === arr[index + i])
|
||||
);
|
||||
}
|
||||
return arr.findIndex((_, index) => subarray.every((element, i) => element === arr[index + i]));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user