UNPKG

@0xpolygonid/js-sdk

Version:
214 lines (213 loc) 9.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fieldValueFromVerifiablePresentation = exports.validateEmptyCredentialSubjectNoopNativeSupport = exports.validateDisclosureNativeSDSupport = exports.validateDisclosureV2Circuit = exports.validateOperators = exports.validateEmptyCredentialSubjectV2Circuit = exports.verifyFieldValueInclusionNativeExistsSupport = exports.verifyFieldValueInclusionV2 = exports.checkCircuitOperator = exports.checkCircuitQueriesLength = exports.checkQueryRequest = void 0; const js_iden3_core_1 = require("@iden3/js-iden3-core"); const js_jsonld_merklization_1 = require("@iden3/js-jsonld-merklization"); const utils_1 = require("../../utils"); const comparer_1 = require("../../circuits/comparer"); const verifiable_1 = require("../../verifiable"); const provers_1 = require("../provers"); const defaultProofGenerationDelayOpts = 24 * 60 * 60 * 1000; // 24 hours async function checkQueryRequest(query, queriesMetadata, ldContext, outputs, circuitId, schemaLoader, opts) { // validate issuer const userDID = js_iden3_core_1.DID.parseFromId(outputs.issuerId); const issuerAllowed = !query.allowedIssuers || query.allowedIssuers?.some((issuer) => issuer === '*' || issuer === userDID.string()); if (!issuerAllowed) { throw new Error('issuer is not in allowed list'); } if (!query.type) { throw new Error('query type is missing'); } const schemaId = await js_jsonld_merklization_1.Path.getTypeIDFromContext(JSON.stringify(ldContext), query.type, { documentLoader: schemaLoader }); const schemaHash = (0, verifiable_1.calculateCoreSchemaHash)(utils_1.byteEncoder.encode(schemaId)); if (schemaHash.bigInt() !== outputs.schemaHash.bigInt()) { throw new Error(`schema that was used is not equal to requested in query`); } if (!query.skipClaimRevocationCheck && outputs.isRevocationChecked === 0) { throw new Error(`check revocation is required`); } checkCircuitQueriesLength(circuitId, queriesMetadata); // verify timestamp let acceptedProofGenerationDelay = defaultProofGenerationDelayOpts; if (opts?.acceptedProofGenerationDelay) { acceptedProofGenerationDelay = opts.acceptedProofGenerationDelay; } const timeDiff = Date.now() - (0, js_iden3_core_1.getDateFromUnixTimestamp)(Number(outputs.timestamp)).getTime(); if (timeDiff > acceptedProofGenerationDelay) { throw new Error('generated proof is outdated'); } return; } exports.checkQueryRequest = checkQueryRequest; function checkCircuitQueriesLength(circuitId, queriesMetadata) { const circuitValidationData = provers_1.circuitValidator[circuitId]; if (queriesMetadata.length > circuitValidationData.maxQueriesCount) { throw new Error(`circuit ${circuitId} supports only ${provers_1.circuitValidator[circuitId].maxQueriesCount} queries`); } } exports.checkCircuitQueriesLength = checkCircuitQueriesLength; function checkCircuitOperator(circuitId, operator) { const circuitValidationData = provers_1.circuitValidator[circuitId]; if (!circuitValidationData.supportedOperations.includes(operator)) { throw new Error(`circuit ${circuitId} not support ${(0, comparer_1.getOperatorNameByValue)(operator)} operator`); } } exports.checkCircuitOperator = checkCircuitOperator; function verifyFieldValueInclusionV2(outputs, metadata) { if (outputs.operator == comparer_1.QueryOperators.$noop) { return; } if (outputs.merklized === 1) { if (outputs.claimPathNotExists === 1) { throw new Error(`proof doesn't contains target query key`); } if (outputs.claimPathKey !== metadata.claimPathKey) { throw new Error(`proof was generated for another path`); } } else { if (outputs.slotIndex !== metadata.slotIndex) { throw new Error(`wrong claim slot was used in claim`); } } } exports.verifyFieldValueInclusionV2 = verifyFieldValueInclusionV2; function verifyFieldValueInclusionNativeExistsSupport(outputs, metadata) { if (outputs.operator == comparer_1.Operators.NOOP) { return; } if (outputs.operator === comparer_1.Operators.EXISTS && !outputs.merklized) { throw new Error('$exists operator is not supported for non-merklized credential'); } if (outputs.merklized === 1) { if (outputs.claimPathKey !== metadata.claimPathKey) { throw new Error(`proof was generated for another path`); } } else { if (outputs.slotIndex !== metadata.slotIndex) { throw new Error(`wrong claim slot was used in claim`); } } } exports.verifyFieldValueInclusionNativeExistsSupport = verifyFieldValueInclusionNativeExistsSupport; async function validateEmptyCredentialSubjectV2Circuit(cq, outputs) { if (outputs.operator !== comparer_1.Operators.EQ) { throw new Error('empty credentialSubject request available only for equal operation'); } for (let index = 1; index < outputs.value.length; index++) { if (outputs.value[index] !== 0n) { throw new Error(`empty credentialSubject request not available for array of values`); } } const path = js_jsonld_merklization_1.Path.newPath([verifiable_1.VerifiableConstants.CREDENTIAL_SUBJECT_PATH]); const subjectEntry = await path.mtEntry(); if (outputs.claimPathKey !== subjectEntry) { throw new Error(`proof doesn't contain credentialSubject in claimPathKey`); } return; } exports.validateEmptyCredentialSubjectV2Circuit = validateEmptyCredentialSubjectV2Circuit; async function validateOperators(cq, outputs) { if (outputs.operator !== cq.operator) { throw new Error(`operator that was used is not equal to request`); } if (outputs.operator === comparer_1.Operators.NOOP) { // for noop operator slot and value are not used in this case return; } for (let index = 0; index < outputs.value.length; index++) { if (outputs.value[index] !== cq.values[index]) { if (outputs.value[index] === 0n && cq.values[index] === undefined) { continue; } throw new Error(`comparison value that was used is not equal to requested in query`); } } } exports.validateOperators = validateOperators; async function validateDisclosureV2Circuit(cq, outputs, verifiablePresentation, ldLoader) { const bi = await (0, exports.fieldValueFromVerifiablePresentation)(cq.fieldName, verifiablePresentation, ldLoader); if (bi !== outputs.value[0]) { throw new Error(`value that was used is not equal to requested in query`); } if (outputs.operator !== comparer_1.Operators.EQ) { throw new Error(`operator for selective disclosure must be $eq`); } for (let index = 1; index < outputs.value.length; index++) { if (outputs.value[index] !== 0n) { throw new Error(`selective disclosure not available for array of values`); } } } exports.validateDisclosureV2Circuit = validateDisclosureV2Circuit; async function validateDisclosureNativeSDSupport(cq, outputs, verifiablePresentation, ldLoader) { const bi = await (0, exports.fieldValueFromVerifiablePresentation)(cq.fieldName, verifiablePresentation, ldLoader); if (bi !== outputs.operatorOutput) { throw new Error(`operator output should be equal to disclosed value`); } if (outputs.operator !== comparer_1.Operators.SD) { throw new Error(`operator for selective disclosure must be $sd`); } for (let index = 0; index < outputs.value.length; index++) { if (outputs.value[index] !== 0n) { throw new Error(`public signal values must be zero`); } } } exports.validateDisclosureNativeSDSupport = validateDisclosureNativeSDSupport; async function validateEmptyCredentialSubjectNoopNativeSupport(outputs) { if (outputs.operator !== comparer_1.Operators.NOOP) { throw new Error('empty credentialSubject request available only for $noop operation'); } for (let index = 1; index < outputs.value.length; index++) { if (outputs.value[index] !== 0n) { throw new Error(`empty credentialSubject request not available for array of values`); } } } exports.validateEmptyCredentialSubjectNoopNativeSupport = validateEmptyCredentialSubjectNoopNativeSupport; const fieldValueFromVerifiablePresentation = async (fieldName, verifiablePresentation, ldLoader) => { if (!verifiablePresentation) { throw new Error(`verifiablePresentation is required for selective disclosure request`); } let mz; const strVerifiablePresentation = JSON.stringify(verifiablePresentation); try { mz = await js_jsonld_merklization_1.Merklizer.merklizeJSONLD(strVerifiablePresentation, { documentLoader: ldLoader }); } catch (e) { throw new Error(`can't merklize verifiablePresentation`); } let merklizedPath; try { const p = `verifiableCredential.credentialSubject.${fieldName}`; merklizedPath = await js_jsonld_merklization_1.Path.fromDocument(null, strVerifiablePresentation, p, { documentLoader: ldLoader }); } catch (e) { throw new Error(`can't build path to '${fieldName}' key`); } let proof; let value; try { ({ proof, value } = await mz.proof(merklizedPath)); } catch (e) { throw new Error(`can't get value by path '${fieldName}'`); } if (!value) { throw new Error(`can't get merkle value for field '${fieldName}'`); } if (!proof.existence) { throw new Error(`path [${merklizedPath.parts}] doesn't exist in verifiablePresentation document`); } return await value.mtEntry(); }; exports.fieldValueFromVerifiablePresentation = fieldValueFromVerifiablePresentation;