UNPKG

@iden3/js-iden3-auth

Version:

iden3-auth implementation in JavaScript

75 lines (74 loc) 3.42 kB
import { Path } from '@iden3/js-jsonld-merklization'; import { LinkedMultiQueryPubSignals, byteEncoder, cacheLoader, parseQueriesMetadata, calculateQueryHashV3, calculateCoreSchemaHash, LinkedMultiQueryInputs, Operators, fieldValueFromVerifiablePresentation } from '@0xpolygonid/js-sdk'; /** * Verifies the linked multi-query circuit. * @beta */ export class LinkedMultiQueryVerifier { constructor(pubSignals) { this.pubSignals = new LinkedMultiQueryPubSignals(); this.bigIntCompare = (a, b) => { if (a < b) return -1; if (a > b) return 1; return 0; }; this.pubSignals = this.pubSignals.pubSignalsUnmarshal(byteEncoder.encode(JSON.stringify(pubSignals))); } verifyIdOwnership() { return Promise.resolve(); } async verifyQuery(query, schemaLoader, verifiablePresentation) { let schema; const ldOpts = { documentLoader: schemaLoader ?? cacheLoader() }; try { schema = (await ldOpts.documentLoader(query.context)).document; } catch (e) { throw new Error(`can't load schema for request query`); } const ldContextJSON = JSON.stringify(schema); const credentialSubject = query.credentialSubject; const schemaId = await Path.getTypeIDFromContext(ldContextJSON, query.type, ldOpts); const schemaHash = calculateCoreSchemaHash(byteEncoder.encode(schemaId)); const queriesMetadata = await parseQueriesMetadata(query.type, ldContextJSON, credentialSubject, ldOpts); const request = []; const merklized = queriesMetadata[0]?.merklizedSchema ? 1 : 0; for (let i = 0; i < LinkedMultiQueryInputs.queryCount; i++) { const queryMeta = queriesMetadata[i]; const values = queryMeta?.values ?? []; const valArrSize = values.length; const queryHash = calculateQueryHashV3(values, schemaHash, queryMeta?.slotIndex ?? 0, queryMeta?.operator ?? 0, queryMeta?.claimPathKey.toString() ?? 0, valArrSize, merklized, 0, 0, 0); request.push({ queryHash, queryMeta }); } const queryHashCompare = (a, b) => { if (a.queryHash < b.queryHash) return -1; if (a.queryHash > b.queryHash) return 1; return 0; }; const pubSignalsMeta = this.pubSignals.circuitQueryHash.map((queryHash, index) => ({ queryHash, operatorOutput: this.pubSignals.operatorOutput[index] })); pubSignalsMeta.sort(queryHashCompare); request.sort(queryHashCompare); for (let i = 0; i < LinkedMultiQueryInputs.queryCount; i++) { if (request[i].queryHash != pubSignalsMeta[i].queryHash) { throw new Error('query hashes do not match'); } if (request[i].queryMeta?.operator === Operators.SD) { const disclosedValue = await fieldValueFromVerifiablePresentation(request[i].queryMeta.fieldName, verifiablePresentation, schemaLoader); if (disclosedValue != pubSignalsMeta[i].operatorOutput) { throw new Error('disclosed value is not in the proof outputs'); } } } return this.pubSignals; } async verifyStates() { return Promise.resolve(); } }