From 6f2268a12e3d80189eca13ff1aca337cddfd0d65 Mon Sep 17 00:00:00 2001 From: vmidyllic <74898029+vmidyllic@users.noreply.github.com> Date: Fri, 9 Feb 2024 12:11:17 +0200 Subject: [PATCH 1/2] fix sd for v3 circuit --- package-lock.json | 4 +-- package.json | 2 +- src/circuits/atomicMtpV2.ts | 2 +- src/circuits/atomicSigV2.ts | 2 +- src/circuits/atomicV3.ts | 5 ++-- src/circuits/query.ts | 54 ++++++++++++++++++++++++++----------- test/query.test.ts | 31 +++++++++++++++++++-- 7 files changed, 76 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8d5ace6..8ee9452 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@iden3/js-iden3-auth", - "version": "1.1.0", + "version": "1.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@iden3/js-iden3-auth", - "version": "1.1.0", + "version": "1.1.1", "license": "AGPL-3.0", "dependencies": { "@0xpolygonid/js-sdk": "1.7.4", diff --git a/package.json b/package.json index b2d2fba..3e362fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@iden3/js-iden3-auth", - "version": "1.1.0", + "version": "1.1.1", "description": "iden3-auth implementation in JavaScript", "main": "dist/cjs/index.js", "source": "./src/index.ts", diff --git a/src/circuits/atomicMtpV2.ts b/src/circuits/atomicMtpV2.ts index 3948229..8e5b209 100644 --- a/src/circuits/atomicMtpV2.ts +++ b/src/circuits/atomicMtpV2.ts @@ -52,7 +52,7 @@ export class AtomicQueryMTPV2PubSignalsVerifier valueArraySize: valuesSize, isRevocationChecked: this.pubSignals.isRevocationChecked }; - await checkQueryRequest(query, outs, schemaLoader, verifiablePresentation, opts); + await checkQueryRequest(query, outs, schemaLoader, verifiablePresentation, false, opts); return this.pubSignals; } diff --git a/src/circuits/atomicSigV2.ts b/src/circuits/atomicSigV2.ts index b5708f8..cb139a3 100644 --- a/src/circuits/atomicSigV2.ts +++ b/src/circuits/atomicSigV2.ts @@ -45,7 +45,7 @@ export class AtomicQuerySigV2PubSignalsVerifier valueArraySize: valuesSize, isRevocationChecked: this.pubSignals.isRevocationChecked }; - await checkQueryRequest(query, outs, schemaLoader, verifiablePresentation, opts); + await checkQueryRequest(query, outs, schemaLoader, verifiablePresentation, false, opts); return this.pubSignals; } diff --git a/src/circuits/atomicV3.ts b/src/circuits/atomicV3.ts index 1c48e9f..2406fbe 100644 --- a/src/circuits/atomicV3.ts +++ b/src/circuits/atomicV3.ts @@ -54,9 +54,10 @@ export class AtomicQueryV3PubSignalsVerifier claimPathKey: this.pubSignals.claimPathKey, claimPathNotExists: this.pubSignals.claimPathNotExists, valueArraySize: valuesSize, - isRevocationChecked: this.pubSignals.isRevocationChecked + isRevocationChecked: this.pubSignals.isRevocationChecked, + operatorOutput: this.pubSignals.operatorOutput }; - await checkQueryRequest(query, outs, schemaLoader, verifiablePresentation, opts); + await checkQueryRequest(query, outs, schemaLoader, verifiablePresentation, true, opts); const { proofType, verifierID, nullifier, nullifierSessionID, linkID } = this.pubSignals; diff --git a/src/circuits/query.ts b/src/circuits/query.ts index 47e6980..25cd5a0 100644 --- a/src/circuits/query.ts +++ b/src/circuits/query.ts @@ -40,6 +40,7 @@ export interface ClaimOutputs { claimPathNotExists?: number; valueArraySize: number; isRevocationChecked: number; + operatorOutput?: bigint; } export async function checkQueryRequest( @@ -47,6 +48,7 @@ export async function checkQueryRequest( outputs: ClaimOutputs, schemaLoader?: DocumentLoader, verifiablePresentation?: JSON, + supportsSDOperator?: boolean, opts?: VerifyOpts ): Promise { // validate issuer @@ -93,7 +95,13 @@ export async function checkQueryRequest( if (!verifiablePresentation) { throw new Error(`no vp present in selective disclosure request`); } - await validateDisclosure(verifiablePresentation, cq, outputs, schemaLoader); + await validateDisclosure( + verifiablePresentation, + cq, + outputs, + schemaLoader, + supportsSDOperator + ); } catch (e) { throw new Error(`failed to validate selective disclosure: ${(e as Error).message}`); } @@ -188,22 +196,13 @@ async function validateDisclosure( verifiablePresentation: JSON, cq: CircuitQuery, outputs: ClaimOutputs, - ldLoader?: DocumentLoader + ldLoader?: DocumentLoader, + supportsSDOperator?: boolean ) { if (!verifiablePresentation) { throw new Error(`verifiablePresentation is required for selective disclosure request`); } - if (outputs.operator !== 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`); - } - } - let mz: Merklizer; const strVerifiablePresentation: string = JSON.stringify(verifiablePresentation); try { @@ -240,10 +239,35 @@ async function validateDisclosure( `path [${merklizedPath.parts}] doesn't exist in verifiablePresentation document` ); } - const bi = await value.mtEntry(); - if (bi !== outputs.value[0]) { - throw new Error(`value that was used is not equal to requested in query`); + + if (supportsSDOperator) { + if (outputs.operator !== Operators.SD) { + throw new Error(`operator for selective disclosure must be $sd`); + } + + if (!outputs.operatorOutput || bi !== outputs.operatorOutput) { + throw new Error(`operator output must be equal to disclosed value`); + } + + for (let index = 0; index < outputs.value.length; index++) { + if (outputs.value[index] !== 0n) { + throw new Error(`in selective disclosure, comparing values must be zero for $sd operator`); + } + } + } else { + if (outputs.operator !== 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`); + } + } + if (bi !== outputs.value[0]) { + throw new Error(`value that was used is not equal to requested in query`); + } } return; diff --git a/test/query.test.ts b/test/query.test.ts index 06e0767..362522e 100644 --- a/test/query.test.ts +++ b/test/query.test.ts @@ -60,7 +60,7 @@ const KYCAgeNonMerklizedSchema = createSchemaHash( 'https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-nonmerklized.jsonld#KYCAgeCredential' ) ); -describe('Query', () => { +describe.only('Query', () => { it('Check merklized query', async () => { const query: Query = { allowedIssuers: ['*'], @@ -112,7 +112,7 @@ describe('Query', () => { await expect(checkQueryRequest(query, pubSig, defaultLoader)).resolves.not.toThrow(); }); - it('Selective disclosure', async () => { + it('Selective disclosure V2', async () => { const query: Query = { allowedIssuers: ['*'], credentialSubject: { @@ -138,6 +138,33 @@ describe('Query', () => { await expect(checkQueryRequest(query, pubSig, defaultLoader, vp)).resolves.not.toThrow(); }); + it('Selective disclosure V3', async () => { + const query: Query = { + allowedIssuers: ['*'], + credentialSubject: { + countryCode: {} + }, + context: + 'https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v3.json-ld', + type: 'KYCCountryOfResidenceCredential' + }; + const pubSig: ClaimOutputs = { + issuerId: issuerID, + schemaHash: KYCCountrySchema, + claimPathKey: BigInt( + '17002437119434618783545694633038537380726339994244684348913844923422470806844' + ), + operator: 16, + value: [], + merklized: 1, + isRevocationChecked: 1, + valueArraySize: 64, + timestamp: getUnixTimestamp(new Date()), + operatorOutput: BigInt(800) + }; + await expect(checkQueryRequest(query, pubSig, defaultLoader, vp, true)).resolves.not.toThrow(); + }); + it('Query with boolean type', async () => { const query: Query = { allowedIssuers: ['*'], From febe407baede1b0bf4a6e1e7f93efcea26b2056a Mon Sep 17 00:00:00 2001 From: vmidyllic <74898029+vmidyllic@users.noreply.github.com> Date: Fri, 9 Feb 2024 13:00:45 +0200 Subject: [PATCH 2/2] fix only --- test/query.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/query.test.ts b/test/query.test.ts index 362522e..b8b77b6 100644 --- a/test/query.test.ts +++ b/test/query.test.ts @@ -60,7 +60,7 @@ const KYCAgeNonMerklizedSchema = createSchemaHash( 'https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-nonmerklized.jsonld#KYCAgeCredential' ) ); -describe.only('Query', () => { +describe('Query', () => { it('Check merklized query', async () => { const query: Query = { allowedIssuers: ['*'],