feat: mock data sha1_ecdsa p256

This commit is contained in:
0xvikasrushi
2024-07-16 23:27:15 +05:30
parent 55ed0fe9a2
commit d359122984
3 changed files with 664 additions and 83 deletions

View 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));

View File

@@ -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
]
];

View File

@@ -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]));
}