Use secret from keychain (#108)

This commit is contained in:
turboblitz
2025-02-14 05:30:14 -08:00
committed by GitHub
parent 7e70b6ffbc
commit c6db61b2c0
29 changed files with 146 additions and 570 deletions

View File

@@ -16,7 +16,7 @@ export interface CertificateData {
| PublicKeyDetailsECDSA
| PublicKeyDetailsRSAPSS
| undefined;
tbsBytes: Uint8Array | undefined;
tbsBytes: number[] | undefined;
tbsBytesLength: string;
rawPem: string;
rawTxt: string;

View File

@@ -344,14 +344,8 @@ export function getCertificateFromPem(pemContent: string): Certificate {
return new Certificate({ schema: asn1.result })
}
export function getTBSBytes(pemContent: string): Uint8Array {
const certificate = getCertificateFromPem(pemContent);
return Uint8Array.from(
certificate.tbsView.map((byte) => parseInt(byte.toString(16), 16))
);
}
export function getTBSBytesForge(certificate: Certificate): Uint8Array {
return Uint8Array.from(
export function getTBSBytesForge(certificate: Certificate): number[] {
return Array.from(
certificate.tbsView.map((byte) => parseInt(byte.toString(16), 16))
);
}

View File

@@ -30,17 +30,16 @@ import { generateMerkleProof, generateSMTProof } from '../trees';
import { parseCertificateSimple } from '../certificate_parsing/parseCertificateSimple';
import { parseDscCertificateData } from '../passports/passport_parsing/parseDscCertificateData';
export async function generateCircuitInputsDSC(
export function generateCircuitInputsDSC(
dscCertificate: string,
devMode: boolean = true
serializedCscaTree: string[][],
) {
const serialized_csca_tree = (await getCSCATree(devMode) as any);
const dscParsed = parseCertificateSimple(dscCertificate);
const dscMetadata = parseDscCertificateData(dscParsed);
const cscaParsed = parseCertificateSimple(dscMetadata.csca);
// CSCA is padded with 0s to max_csca_bytes
const cscaTbsBytesPadded = padWithZeroes(Array.from(cscaParsed.tbsBytes), max_csca_bytes);
const cscaTbsBytesPadded = padWithZeroes(cscaParsed.tbsBytes, max_csca_bytes);
const dscTbsBytes = dscParsed.tbsBytes;
// DSC is padded using sha padding because it will be hashed in the circuit
@@ -50,7 +49,7 @@ export async function generateCircuitInputsDSC(
);
const leaf = getLeafCscaTree(cscaParsed);
const [root, path, siblings] = getCscaTreeInclusionProof(leaf, serialized_csca_tree);
const [root, path, siblings] = getCscaTreeInclusionProof(leaf, serializedCscaTree);
// Parse CSCA certificate and get its public key
const csca_pubKey_formatted = getCertificatePubKey(
@@ -86,16 +85,11 @@ export async function generateCircuitInputsDSC(
};
}
export async function generateCircuitInputsRegister(
export function generateCircuitInputsRegister(
secret: string,
passportData: PassportData,
devMode: boolean = false
serializedDscTree: string,
) {
const serialized_dsc_tree = await getDSCTree(devMode);
if (!passportData.parsed) {
throw new Error('Passport data is not parsed');
}
const { mrz, eContent, signedAttr } = passportData;
const passportMetadata = passportData.passportMetadata;
const dscParsed = passportData.dsc_parsed;
@@ -118,23 +112,23 @@ export async function generateCircuitInputsRegister(
}
const [eContentPadded, eContentLen] = pad(passportMetadata.eContentHashFunction)(
new Uint8Array(eContent),
eContent,
MAX_PADDED_ECONTENT_LEN[passportMetadata.dg1HashFunction]
);
const [signedAttrPadded, signedAttrPaddedLen] = pad(passportMetadata.signedAttrHashFunction)(
new Uint8Array(signedAttr),
signedAttr,
MAX_PADDED_SIGNED_ATTR_LEN[passportMetadata.eContentHashFunction]
);
const dsc_leaf = getLeafDscTree(dscParsed, passportData.csca_parsed); // TODO: WRONG
const [root, path, siblings, leaf_depth] = getDscTreeInclusionProof(dsc_leaf, serialized_dsc_tree);
const [root, path, siblings, leaf_depth] = getDscTreeInclusionProof(dsc_leaf, serializedDscTree);
const csca_tree_leaf = getLeafCscaTree(passportData.csca_parsed);
// Get start index of DSC pubkey based on algorithm
const [startIndex, keyLength] = findStartPubKeyIndex(dscParsed, dscTbsBytesPadded, dscParsed.signatureAlgorithm);
const inputs = {
raw_dsc: Array.from(dscTbsBytesPadded).map(x => x.toString()),
raw_dsc: dscTbsBytesPadded.map(x => x.toString()),
raw_dsc_actual_length: [BigInt(dscParsed.tbsBytes.length).toString()],
dsc_pubKey_offset: startIndex,
dsc_pubKey_actual_size: [BigInt(keyLength).toString()],

View File

@@ -6,7 +6,7 @@ import { SKI_PEM, SKI_PEM_DEV } from '../constants/skiPem';
import { splitToWords } from './bytes';
import path from 'path';
export function findStartIndexEC(modulus: string, messagePadded: Uint8Array): [number, number] {
export function findStartIndexEC(modulus: string, messagePadded: number[]): [number, number] {
const modulusNumArray = [];
for (let i = 0; i < modulus.length; i += 2) {
modulusNumArray.push(parseInt(modulus.slice(i, i + 2), 16));
@@ -38,7 +38,7 @@ export function findStartIndexEC(modulus: string, messagePadded: Uint8Array): [n
}
// @returns [startIndex, length] where startIndex is the index of the first byte of the modulus in the message and length is the length of the modulus in bytes
export function findStartIndex(modulus: string, messagePadded: Uint8Array): [number, number] {
export function findStartIndex(modulus: string, messagePaddedNumber: number[]): [number, number] {
const modulusNumArray = [];
for (let i = 0; i < modulus.length; i += 2) {
const hexPair = modulus.slice(i, i + 2);
@@ -46,8 +46,6 @@ export function findStartIndex(modulus: string, messagePadded: Uint8Array): [num
modulusNumArray.push(number);
}
const messagePaddedNumber = Array.from(messagePadded);
// console.log('Modulus length:', modulusNumArray.length);
// console.log('Message length:', messagePaddedNumber.length);
// console.log('Modulus (hex):', modulusNumArray.map(n => n.toString(16).padStart(2, '0')).join(''));
@@ -71,7 +69,7 @@ export function findStartIndex(modulus: string, messagePadded: Uint8Array): [num
export function findOIDPosition(
oid: string,
message: Uint8Array
message: number[]
): { oid_index: number; oid_length: number } {
// Convert OID string like "1.2.840.113549" to byte array
const oidParts = oid.split('.').map(Number);

View File

@@ -14,6 +14,7 @@ import {
import { getCurveForElliptic } from '../certificate_parsing/curves';
import { formatAndConcatenateDataHashes, formatMrz } from './format';
import { generateSignedAttr } from './format';
import { initPassportDataParsing } from './passport';
function generateRandomBytes(length: number): number[] {
// Generate numbers between -128 and 127 to match the existing signed byte format
@@ -259,7 +260,7 @@ export function genMockPassportData(
const signature = sign(privateKeyPem, dsc, hashAlgo, signedAttr);
const signatureBytes = Array.from(signature, (byte) => (byte < 128 ? byte : byte - 256));
return {
return initPassportDataParsing({
dsc: dsc,
mrz: mrz,
dg2Hash: dataGroupHashes.find(([dgNum]) => dgNum === 2)?.[1] || [],
@@ -267,9 +268,7 @@ export function genMockPassportData(
signedAttr: signedAttr,
encryptedDigest: signatureBytes,
photoBase64: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABjElEQVR42mL8//8/AyUYiBQYmIy3...',
mockUser: true,
parsed: false,
};
});
}
function sign(

View File

@@ -35,7 +35,7 @@ import { findStartIndex, findStartIndexEC } from '../csca';
import { formatInput } from '../circuits/generateInputs';
import { getLeafDscTree } from '../trees';
/// @dev will brutforce passport and dsc signature — needs to be trigerred after generating mock passport data
/// @dev will bruteforce passport and dsc signature
export function initPassportDataParsing(passportData: PassportData) {
const passportMetadata = parsePassportData(passportData);
passportData.passportMetadata = passportMetadata;
@@ -45,7 +45,6 @@ export function initPassportDataParsing(passportData: PassportData) {
const cscaParsed = parseCertificateSimple(passportData.passportMetadata.csca);
passportData.csca_parsed = cscaParsed;
}
passportData.parsed = true;
return passportData;
}
@@ -101,18 +100,9 @@ export function padWithZeroes(bytes: number[], length: number) {
return bytes.concat(new Array(length - bytes.length).fill(0));
}
function validatePassportMetadata(passportData: PassportData): void {
if (!passportData.parsed) {
throw new Error('Passport data is not parsed');
}
}
/// @notice Get the signature of the passport and the public key of the DSC
/// @dev valid for only for the passport/dsc chain
export function getPassportSignatureInfos(passportData: PassportData) {
if (!passportData.parsed) {
throw new Error('Passport data is not parsed');
}
const passportMetadata = passportData.passportMetadata;
const signatureAlgorithmFullName = getSignatureAlgorithmFullName(
passportData.dsc_parsed,
@@ -257,7 +247,6 @@ export function getSignatureAlgorithmFullName(
/*** retrieve pubKey bytes - will be used in generateCircuitsInputsCSCA ***/
export function getPubKeyBytes(passportData: PassportData, type: 'dsc' | 'csca'): number[] {
validatePassportMetadata(passportData);
if (type === 'dsc') {
return getDscPubKeyBytes(passportData);
} else if (type === 'csca') {

View File

@@ -1,7 +1,8 @@
// Copied from zk-email cuz it uses crypto so can't import it here.
// Puts an end selector, a bunch of 0s, then the length, then fill the rest with 0s.
export function shaPad(prehash_prepad_m: Uint8Array, maxShaBytes: number): [Uint8Array, number] {
export function shaPad(prehash_prepad_m_array: number[], maxShaBytes: number): [number[], number] {
let prehash_prepad_m = new Uint8Array(prehash_prepad_m_array);
let length_bits = prehash_prepad_m.length * 8; // bytes to bits
let length_in_bytes = int64toBytes(length_bits);
prehash_prepad_m = mergeUInt8Arrays(prehash_prepad_m, int8toBytes(2 ** 7)); // Add the 1 on the end, length 505
@@ -18,13 +19,14 @@ export function shaPad(prehash_prepad_m: Uint8Array, maxShaBytes: number): [Uint
prehash_prepad_m.length === maxShaBytes,
`Padding to max length did not complete properly! Your padded message is ${prehash_prepad_m.length} long but max is ${maxShaBytes}!`
);
return [prehash_prepad_m, messageLen];
return [Array.from(prehash_prepad_m), messageLen];
}
export function sha384_512Pad(
prehash_prepad_m: Uint8Array,
prehash_prepad_m_array: number[],
maxShaBytes: number
): [Uint8Array, number] {
): [number[], number] {
let prehash_prepad_m = new Uint8Array(prehash_prepad_m_array);
// Length in bits before padding
let length_bits = prehash_prepad_m.length * 8;
@@ -57,7 +59,7 @@ export function sha384_512Pad(
`Padding to max length did not complete properly! Your padded message is ${prehash_prepad_m.length} long but max is ${maxShaBytes}!`
);
return [prehash_prepad_m, messageLen];
return [Array.from(prehash_prepad_m), messageLen];
}
// Helper function to convert 128-bit length to bytes

View File

@@ -16,22 +16,13 @@ import { pad } from './passports/passport';
import countries from "i18n-iso-countries";
import en from "i18n-iso-countries/langs/en.json";
countries.registerLocale(en);
import serialized_csca_tree from '../../pubkeys/serialized_csca_tree.json';
import serialized_dsc_tree from '../../pubkeys/serialized_dsc_tree.json';
export async function getCSCATree(devMode: boolean): Promise<string[][]> {
if (devMode) {
return serialized_csca_tree;
}
export async function getCSCATree(): Promise<string[][]> {
const response = await fetch(CSCA_TREE_URL);
return await response.json().then(data => data.data ? JSON.parse(data.data) : data);
}
export async function getDSCTree(devMode: boolean): Promise<string> {
if (devMode) {
return serialized_dsc_tree;
}
export async function getDSCTree(): Promise<string> {
const response = await fetch(DSC_TREE_URL);
return await response.json().then(data => data.data ? data.data : data);
}
@@ -112,6 +103,7 @@ export function getCscaTreeInclusionProof(leaf: string, _serialized_csca_tree: a
const proof = tree.createProof(index);
return [tree.root, proof.pathIndices.map(index => index.toString()), proof.siblings.flat().map(sibling => sibling.toString())];
}
export function getCscaTreeRoot(serialized_csca_tree: any[][]) {
let tree = new IMT(poseidon2, CSCA_TREE_DEPTH, 0, 2);
tree.setNodes(serialized_csca_tree);

View File

@@ -1,3 +1,4 @@
import { CertificateData } from "./certificate_parsing/dataStructure";
import { PassportMetadata } from "./passports/passport_parsing/parsePassportData";
export type PassportData = {
@@ -10,11 +11,9 @@ export type PassportData = {
signedAttr: number[];
encryptedDigest: number[];
photoBase64: string;
mockUser?: boolean;
parsed: boolean;
passportMetadata?: PassportMetadata;
dsc_parsed?: any;
csca_parsed?: any;
dsc_parsed?: CertificateData;
csca_parsed?: CertificateData;
};
// Define the signature algorithm in "algorithm_hashfunction_domainPapameter_keyLength"