From 4c62876f21c53b9a9779903b543776da571a8ecf Mon Sep 17 00:00:00 2001 From: Maycon Date: Mon, 12 Feb 2024 13:32:03 -0300 Subject: [PATCH 01/15] bbs+ revocation unit test --- .../anoncreds/derived-credentials.test.js | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index e52d44add..178d98eaf 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -308,6 +308,86 @@ describe.each(Schemes)('Derived Credentials', ({ await createAndVerifyPresentation(credentials); }, 30000); + test(`For ${Name}, holder creates a derived verifiable credential from a credential with bbs+ revocation`, async () => { + const issuerKey = getKeyDoc(did1, keypair, keypair.type, keypair.id); + const unsignedCred = { + ...credentialJSON, + issuer: did1, + }; + + const presentationOptions = { + nonce: stringToU8a('noncetest'), + context: 'my context', + }; + + // Create W3C credential + const credential = await issueCredential(issuerKey, unsignedCred); + + // Begin to derive a credential from the above issued one + const presentationInstance = new Presentation(); + const idx = await presentationInstance.addCredentialToPresent( + credential, + { resolver }, + ); + + // Reveal subject attributes + presentationInstance.addAttributeToReveal(idx, [ + 'credentialSubject.lprNumber', + ]); + + + // Begin to derive a credential from the above issued one + const presentationInstance2 = new Presentation(); + const idx2 = await presentationInstance2.addCredentialToPresent( + credential, + { resolver }, + ); + + // Reveal subject attributes + presentationInstance2.addAttributeToReveal(idx2, [ + 'credentialSubject.lprNumber', + ]); + + // Derive a W3C Verifiable Credential JSON from the above presentation + const credentials = await presentationInstance.deriveCredentials( + presentationOptions, + ); + expect(credentials.length).toEqual(1); + expect(credentials[0].proof).toBeDefined(); + expect(credentials[0]).toHaveProperty('credentialSubject'); + expect(credentials[0].credentialSubject).toMatchObject( + expect.objectContaining({ + type: unsignedCred.credentialSubject.type, + lprNumber: 1234, + }), + ); + + // Ensure reconstructing presentation from credential matches + // NOTE: ignoring proof here as itll differ when signed twice as above + const presentation = await presentationInstance2.createPresentation( + presentationOptions, + ); + + // Question: What is the point of this? A single credential cant be converted to a presentation and a presentation + // has other data that credential won't have + const reconstructedPres = convertToPresentation(credentials[0]); + expect(reconstructedPres.proof).toBeDefined(); + expect({ + ...reconstructedPres, + proof: '', + }).toMatchObject({ ...presentation, proof: '' }); + + // Try to verify the derived credential alone + const credentialResult = await verifyCredential(credentials[0], { + resolver, + }); + expect(credentialResult.verified).toBe(true); + expect(credentialResult.error).toBe(undefined); + + // Create a VP and verify it from this credential + await createAndVerifyPresentation(credentials); + }, 30000); + test('Holder creates a derived verifiable credential from a credential with range proofs', async () => { const provingKeyId = 'provingKeyId'; const pk = BoundCheckSnarkSetup(); From 91d2005ed25fca5058e98383ffc2f294a27acdb2 Mon Sep 17 00:00:00 2001 From: Maycon Mello Date: Wed, 14 Feb 2024 12:56:02 -0300 Subject: [PATCH 02/15] assert for credentialStatus --- tests/integration/anoncreds/derived-credentials.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index 178d98eaf..8eda9e975 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -354,6 +354,7 @@ describe.each(Schemes)('Derived Credentials', ({ ); expect(credentials.length).toEqual(1); expect(credentials[0].proof).toBeDefined(); + expect(credentials[0].credentialStatus).toBeDefined(); expect(credentials[0]).toHaveProperty('credentialSubject'); expect(credentials[0].credentialSubject).toMatchObject( expect.objectContaining({ From 745f0a39eff9c6ccf2f63d53f147fa2b03b5a205 Mon Sep 17 00:00:00 2001 From: Maycon Mello Date: Wed, 14 Feb 2024 14:06:56 -0300 Subject: [PATCH 03/15] assert for credentialStatus --- .../anoncreds/derived-credentials.test.js | 139 ++++++++++-------- 1 file changed, 74 insertions(+), 65 deletions(-) diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index 8eda9e975..e01af93a7 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -309,84 +309,93 @@ describe.each(Schemes)('Derived Credentials', ({ }, 30000); test(`For ${Name}, holder creates a derived verifiable credential from a credential with bbs+ revocation`, async () => { - const issuerKey = getKeyDoc(did1, keypair, keypair.type, keypair.id); - const unsignedCred = { - ...credentialJSON, - issuer: did1, - }; - - const presentationOptions = { - nonce: stringToU8a('noncetest'), - context: 'my context', - }; - - // Create W3C credential - const credential = await issueCredential(issuerKey, unsignedCred); - // Begin to derive a credential from the above issued one const presentationInstance = new Presentation(); - const idx = await presentationInstance.addCredentialToPresent( - credential, - { resolver }, - ); - - // Reveal subject attributes - presentationInstance.addAttributeToReveal(idx, [ - 'credentialSubject.lprNumber', - ]); - - // Begin to derive a credential from the above issued one - const presentationInstance2 = new Presentation(); - const idx2 = await presentationInstance2.addCredentialToPresent( - credential, - { resolver }, - ); + const bbsCred = { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + { + "dk": "https://ld.dock.io/credentials#", + "BiometricsCredential": "dk:BiometricsCredential", + "name": "dk:name" + } + ], + "credentialStatus": { + "id": "dock:accumulator:0xa632a41f2fbdb681c14b33daae4fcc46af41661b90b35c4ac1545c9bebf0d7cc", + "type": "DockVBAccumulator2022", + "revocationCheck": "membership", + "revocationId": "10" + }, + "id": "https://creds-staging.dock.io/36eece85e59cf9df5c32e78a866b254b84506b9e0396e543ed7890ca6be042e4", + "type": [ + "VerifiableCredential", + "BiometricsCredential" + ], + "credentialSubject": { + "id": "did:key:z6MksJKDx1wXLmWYE5Ppp4L1xtsyBccYVaYXP5nUPt5MbXve", + "name": "test" + }, + "issuanceDate": "2024-01-09T19:14:04.108Z", + "issuer": { + "name": "profile bbs+", + "id": "did:dock:5GJeBeStWSxqyPGUJnERMFhm3wKcfCZP6nhqtoKyRAmq9FeU" + }, + "name": "test", + "cryptoVersion": "0.4.0", + "credentialSchema": { + "id": "data:application/json;charset=utf-8,%7B%22%24schema%22%3A%22http%3A%2F%2Fjson-schema.org%2Fdraft-07%2Fschema%23%22%2C%22definitions%22%3A%7B%22encryptableCompString%22%3A%7B%22type%22%3A%22string%22%7D%2C%22encryptableString%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22properties%22%3A%7B%22%40context%22%3A%7B%22type%22%3A%22string%22%7D%2C%22credentialSchema%22%3A%7B%22type%22%3A%22string%22%7D%2C%22credentialStatus%22%3A%7B%22properties%22%3A%7B%22id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22revocationCheck%22%3A%7B%22type%22%3A%22string%22%7D%2C%22revocationId%22%3A%7B%22type%22%3A%22string%22%7D%2C%22type%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22credentialSubject%22%3A%7B%22properties%22%3A%7B%22id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22name%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22cryptoVersion%22%3A%7B%22type%22%3A%22string%22%7D%2C%22id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22issuanceDate%22%3A%7B%22format%22%3A%22date-time%22%2C%22type%22%3A%22string%22%7D%2C%22issuer%22%3A%7B%22properties%22%3A%7B%22id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22name%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22name%22%3A%7B%22type%22%3A%22string%22%7D%2C%22proof%22%3A%7B%22properties%22%3A%7B%22%40context%22%3A%7B%22items%22%3A%5B%7B%22properties%22%3A%7B%22proof%22%3A%7B%22properties%22%3A%7B%22%40container%22%3A%7B%22type%22%3A%22string%22%7D%2C%22%40id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22%40type%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22sec%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%7B%22type%22%3A%22string%22%7D%5D%2C%22type%22%3A%22array%22%7D%2C%22created%22%3A%7B%22format%22%3A%22date-time%22%2C%22type%22%3A%22string%22%7D%2C%22proofPurpose%22%3A%7B%22type%22%3A%22string%22%7D%2C%22type%22%3A%7B%22type%22%3A%22string%22%7D%2C%22verificationMethod%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22type%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D", + "type": "JsonSchemaValidator2018", + "parsingOptions": { + "useDefaults": false, + "defaultMinimumInteger": -4294967295, + "defaultMinimumDate": -17592186044415, + "defaultDecimalPlaces": 0 + }, + "version": "0.2.0" + }, + "proof": { + "@context": [ + { + "sec": "https://w3id.org/security#", + "proof": { + "@id": "sec:proof", + "@type": "@id", + "@container": "@graph" + } + }, + "https://ld.dock.io/security/bbs/v1" + ], + "type": "Bls12381BBS+SignatureDock2022", + "created": "2024-01-31T12:47:18Z", + "verificationMethod": "did:dock:5GJeBeStWSxqyPGUJnERMFhm3wKcfCZP6nhqtoKyRAmq9FeU#keys-2", + "proofPurpose": "assertionMethod", + "proofValue": "zbYhMT7jEavhQp92xzZkDfVDyVViJfeFfhq1uagW5B9zGnWJykx6mZVgANomBBQMJ9NYSecScPa6G2rdArdqJuTqi4yHu5HT5Hpq7qPcgQKCxGYnteoQijyovUppafyh9m9CL8gzF1tXwhB8Li2DoRMPeF" + } + } - // Reveal subject attributes - presentationInstance2.addAttributeToReveal(idx2, [ - 'credentialSubject.lprNumber', + presentationInstance.addCredentialToPresent(bbsCred); + presentationInstance.presBuilder.credStatuses.set(0, [ + { + value: new Uint8Array([128, 181, 205, 177, 121, 245, 130, 199, 51, 197, 203, 218, 159, 242, 230, 129, 133, 124, 147, 19, 102, 32, 112, 206, 154, 23, 252, 109, 183, 202, 224, 157, 62, 109, 236, 142, 240, 65, 45, 114, 61, 192, 145, 53, 77, 20, 251, 97]), + }, + new Uint8Array([134, 94, 152, 141, 109, 226, 220, 161, 148, 169, 112, 11, 254, 108, 78, 101, 165, 79, 12, 41, 6, 173, 60, 69, 107, 106, 216, 13, 122, 210, 137, 152, 201, 27, 236, 37, 208, 32, 223, 114, 88, 142, 55, 204, 36, 13, 147, 235]), + { + value: new Uint8Array([144, 222, 74, 116, 11, 85, 191, 161, 154, 160, 165, 58, 28, 247, 188, 193, 151, 115, 185, 194, 145, 137, 220, 171, 101, 205, 91, 72, 133, 234, 215, 244, 184, 128, 176, 115, 142, 63, 222, 45, 128, 75, 229, 32, 214, 57, 129, 93, 11, 22, 152, 101, 220, 48, 128, 52, 9, 130, 75, 194, 131, 36, 80, 117, 100, 118, 83, 139, 233, 181, 112, 243, 19, 80, 75, 183, 60, 223, 18, 43, 58, 114, 158, 229, 88, 103, 40, 195, 140, 114, 185, 179, 219, 240, 58, 244]), + }, + { + }, ]); - + // Derive a W3C Verifiable Credential JSON from the above presentation const credentials = await presentationInstance.deriveCredentials( presentationOptions, ); + expect(credentials.length).toEqual(1); expect(credentials[0].proof).toBeDefined(); expect(credentials[0].credentialStatus).toBeDefined(); - expect(credentials[0]).toHaveProperty('credentialSubject'); - expect(credentials[0].credentialSubject).toMatchObject( - expect.objectContaining({ - type: unsignedCred.credentialSubject.type, - lprNumber: 1234, - }), - ); - - // Ensure reconstructing presentation from credential matches - // NOTE: ignoring proof here as itll differ when signed twice as above - const presentation = await presentationInstance2.createPresentation( - presentationOptions, - ); - // Question: What is the point of this? A single credential cant be converted to a presentation and a presentation - // has other data that credential won't have - const reconstructedPres = convertToPresentation(credentials[0]); - expect(reconstructedPres.proof).toBeDefined(); - expect({ - ...reconstructedPres, - proof: '', - }).toMatchObject({ ...presentation, proof: '' }); - - // Try to verify the derived credential alone - const credentialResult = await verifyCredential(credentials[0], { - resolver, - }); - expect(credentialResult.verified).toBe(true); - expect(credentialResult.error).toBe(undefined); - - // Create a VP and verify it from this credential - await createAndVerifyPresentation(credentials); }, 30000); test('Holder creates a derived verifiable credential from a credential with range proofs', async () => { From 0f25c0f6034a09f3c7e80bcbb14c5cc65930722e Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Thu, 15 Feb 2024 01:38:28 +0000 Subject: [PATCH 04/15] fix derive credentials not persisting status Signed-off-by: Sam Hellawell --- src/presentation.js | 8 +- .../anoncreds/derived-credentials.test.js | 135 ++++++++---------- 2 files changed, 69 insertions(+), 74 deletions(-) diff --git a/src/presentation.js b/src/presentation.js index 4a0a5c211..59ea9eefd 100644 --- a/src/presentation.js +++ b/src/presentation.js @@ -165,7 +165,7 @@ export default class Presentation { ); } - return { + const w3cFormattedCredential = { ...credential.revealedAttributes, '@context': JSON.parse(credential.revealedAttributes['@context']), type: JSON.parse(credential.revealedAttributes.type), @@ -192,6 +192,12 @@ export default class Presentation { bounds: credential.bounds, }, }; + + if (credential.status) { + w3cFormattedCredential.credentialStatus = credential.status; + } + + return w3cFormattedCredential; }); } } diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index e01af93a7..cb68a7703 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -1,6 +1,6 @@ import { randomAsHex } from '@polkadot/util-crypto'; import { stringToU8a, u8aToHex } from '@polkadot/util'; -import { initializeWasm, BoundCheckSnarkSetup } from '@docknetwork/crypto-wasm-ts'; +import { initializeWasm, BoundCheckSnarkSetup, MembershipWitness } from '@docknetwork/crypto-wasm-ts'; import { DockAPI } from '../../../src'; import { FullNodeEndpoint, @@ -308,77 +308,42 @@ describe.each(Schemes)('Derived Credentials', ({ await createAndVerifyPresentation(credentials); }, 30000); - test(`For ${Name}, holder creates a derived verifiable credential from a credential with bbs+ revocation`, async () => { - // Begin to derive a credential from the above issued one - const presentationInstance = new Presentation(); + test(`For ${Name}, persist credential status when deriving`, async () => { + const provingKeyId = 'provingKeyId'; + const pk = BoundCheckSnarkSetup(); + const provingKey = pk.decompress(); + const credentialStatus = { // Mock data + "id": "dock:accumulator:0xa632a41f2fbdb681c14b33daae4fcc46af41661b90b35c4ac1545c9bebf0d7cc", + "type": "DockVBAccumulator2022", + "revocationCheck": "membership", + "revocationId": "10" + }; - const bbsCred = { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - { - "dk": "https://ld.dock.io/credentials#", - "BiometricsCredential": "dk:BiometricsCredential", - "name": "dk:name" - } - ], - "credentialStatus": { - "id": "dock:accumulator:0xa632a41f2fbdb681c14b33daae4fcc46af41661b90b35c4ac1545c9bebf0d7cc", - "type": "DockVBAccumulator2022", - "revocationCheck": "membership", - "revocationId": "10" - }, - "id": "https://creds-staging.dock.io/36eece85e59cf9df5c32e78a866b254b84506b9e0396e543ed7890ca6be042e4", - "type": [ - "VerifiableCredential", - "BiometricsCredential" - ], - "credentialSubject": { - "id": "did:key:z6MksJKDx1wXLmWYE5Ppp4L1xtsyBccYVaYXP5nUPt5MbXve", - "name": "test" - }, - "issuanceDate": "2024-01-09T19:14:04.108Z", - "issuer": { - "name": "profile bbs+", - "id": "did:dock:5GJeBeStWSxqyPGUJnERMFhm3wKcfCZP6nhqtoKyRAmq9FeU" - }, - "name": "test", - "cryptoVersion": "0.4.0", - "credentialSchema": { - "id": "data:application/json;charset=utf-8,%7B%22%24schema%22%3A%22http%3A%2F%2Fjson-schema.org%2Fdraft-07%2Fschema%23%22%2C%22definitions%22%3A%7B%22encryptableCompString%22%3A%7B%22type%22%3A%22string%22%7D%2C%22encryptableString%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22properties%22%3A%7B%22%40context%22%3A%7B%22type%22%3A%22string%22%7D%2C%22credentialSchema%22%3A%7B%22type%22%3A%22string%22%7D%2C%22credentialStatus%22%3A%7B%22properties%22%3A%7B%22id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22revocationCheck%22%3A%7B%22type%22%3A%22string%22%7D%2C%22revocationId%22%3A%7B%22type%22%3A%22string%22%7D%2C%22type%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22credentialSubject%22%3A%7B%22properties%22%3A%7B%22id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22name%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22cryptoVersion%22%3A%7B%22type%22%3A%22string%22%7D%2C%22id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22issuanceDate%22%3A%7B%22format%22%3A%22date-time%22%2C%22type%22%3A%22string%22%7D%2C%22issuer%22%3A%7B%22properties%22%3A%7B%22id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22name%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22name%22%3A%7B%22type%22%3A%22string%22%7D%2C%22proof%22%3A%7B%22properties%22%3A%7B%22%40context%22%3A%7B%22items%22%3A%5B%7B%22properties%22%3A%7B%22proof%22%3A%7B%22properties%22%3A%7B%22%40container%22%3A%7B%22type%22%3A%22string%22%7D%2C%22%40id%22%3A%7B%22type%22%3A%22string%22%7D%2C%22%40type%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22sec%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%7B%22type%22%3A%22string%22%7D%5D%2C%22type%22%3A%22array%22%7D%2C%22created%22%3A%7B%22format%22%3A%22date-time%22%2C%22type%22%3A%22string%22%7D%2C%22proofPurpose%22%3A%7B%22type%22%3A%22string%22%7D%2C%22type%22%3A%7B%22type%22%3A%22string%22%7D%2C%22verificationMethod%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D%2C%22type%22%3A%7B%22type%22%3A%22string%22%7D%7D%2C%22type%22%3A%22object%22%7D", - "type": "JsonSchemaValidator2018", - "parsingOptions": { - "useDefaults": false, - "defaultMinimumInteger": -4294967295, - "defaultMinimumDate": -17592186044415, - "defaultDecimalPlaces": 0 - }, - "version": "0.2.0" - }, - "proof": { - "@context": [ - { - "sec": "https://w3id.org/security#", - "proof": { - "@id": "sec:proof", - "@type": "@id", - "@container": "@graph" - } - }, - "https://ld.dock.io/security/bbs/v1" - ], - "type": "Bls12381BBS+SignatureDock2022", - "created": "2024-01-31T12:47:18Z", - "verificationMethod": "did:dock:5GJeBeStWSxqyPGUJnERMFhm3wKcfCZP6nhqtoKyRAmq9FeU#keys-2", - "proofPurpose": "assertionMethod", - "proofValue": "zbYhMT7jEavhQp92xzZkDfVDyVViJfeFfhq1uagW5B9zGnWJykx6mZVgANomBBQMJ9NYSecScPa6G2rdArdqJuTqi4yHu5HT5Hpq7qPcgQKCxGYnteoQijyovUppafyh9m9CL8gzF1tXwhB8Li2DoRMPeF" - } - } + const issuerKey = getKeyDoc(did1, keypair, keypair.type, keypair.id); + const unsignedCred = { + ...credentialJSON, + credentialStatus, + issuer: did1, + }; + + const presentationOptions = { + nonce: stringToU8a('noncetest'), + context: 'my context', + }; - presentationInstance.addCredentialToPresent(bbsCred); + // Create W3C credential + const credential = await issueCredential(issuerKey, unsignedCred); + + // Begin to derive a credential from the above issued one + const presentationInstance = new Presentation(); + const idx = await presentationInstance.addCredentialToPresent( + credential, + { resolver }, + ); + + // Mock data presentationInstance.presBuilder.credStatuses.set(0, [ - { - value: new Uint8Array([128, 181, 205, 177, 121, 245, 130, 199, 51, 197, 203, 218, 159, 242, 230, 129, 133, 124, 147, 19, 102, 32, 112, 206, 154, 23, 252, 109, 183, 202, 224, 157, 62, 109, 236, 142, 240, 65, 45, 114, 61, 192, 145, 53, 77, 20, 251, 97]), - }, + new MembershipWitness(new Uint8Array([128, 181, 205, 177, 121, 245, 130, 199, 51, 197, 203, 218, 159, 242, 230, 129, 133, 124, 147, 19, 102, 32, 112, 206, 154, 23, 252, 109, 183, 202, 224, 157, 62, 109, 236, 142, 240, 65, 45, 114, 61, 192, 145, 53, 77, 20, 251, 97])), new Uint8Array([134, 94, 152, 141, 109, 226, 220, 161, 148, 169, 112, 11, 254, 108, 78, 101, 165, 79, 12, 41, 6, 173, 60, 69, 107, 106, 216, 13, 122, 210, 137, 152, 201, 27, 236, 37, 208, 32, 223, 114, 88, 142, 55, 204, 36, 13, 147, 235]), { value: new Uint8Array([144, 222, 74, 116, 11, 85, 191, 161, 154, 160, 165, 58, 28, 247, 188, 193, 151, 115, 185, 194, 145, 137, 220, 171, 101, 205, 91, 72, 133, 234, 215, 244, 184, 128, 176, 115, 142, 63, 222, 45, 128, 75, 229, 32, 214, 57, 129, 93, 11, 22, 152, 101, 220, 48, 128, 52, 9, 130, 75, 194, 131, 36, 80, 117, 100, 118, 83, 139, 233, 181, 112, 243, 19, 80, 75, 183, 60, 223, 18, 43, 58, 114, 158, 229, 88, 103, 40, 195, 140, 114, 185, 179, 219, 240, 58, 244]), @@ -386,17 +351,41 @@ describe.each(Schemes)('Derived Credentials', ({ { }, ]); - + + // NOTE: revealing subject type because of JSON-LD processing for this certain credential + // you may not always need to do this depending on your JSON-LD contexts + await presentationInstance.addAttributeToReveal(idx, [ + 'credentialSubject.type.0', + ]); + await presentationInstance.addAttributeToReveal(idx, [ + 'credentialSubject.type.1', + ]); + + // Enforce LPR number to be between values aswell as revealed + // NOTE: unlike other tests, we cannot "reveal" this value and enforce bounds at the same time! + presentationInstance.presBuilder.enforceBounds( + idx, + 'credentialSubject.lprNumber', + 1233, + 1235, + provingKeyId, + provingKey, + ); + // Derive a W3C Verifiable Credential JSON from the above presentation const credentials = await presentationInstance.deriveCredentials( presentationOptions, ); expect(credentials.length).toEqual(1); - expect(credentials[0].proof).toBeDefined(); expect(credentials[0].credentialStatus).toBeDefined(); - - }, 30000); + expect(credentials[0].credentialStatus).toEqual({ + ...credentialStatus, + revocationId: undefined, + accumulated: '5vtBeJk2aRi6J2KaVhg7hiVbcDoBWmnhRrWZ4ohnR37FsaFq1XquTBeneqMATg3HQv', + extra: {}, + }); + }); test('Holder creates a derived verifiable credential from a credential with range proofs', async () => { const provingKeyId = 'provingKeyId'; From 7ed255a97af6628d3c42ed6a71f41570a4406173 Mon Sep 17 00:00:00 2001 From: lovesh Date: Thu, 15 Feb 2024 19:41:12 +0530 Subject: [PATCH 05/15] Update test Signed-off-by: lovesh --- src/modules/accumulator.js | 9 +- src/utils/vc/contexts/dock-bbs-v1.json | 1 + src/utils/vc/contexts/dock-bbs23-v1.json | 1 + src/utils/vc/contexts/dock-ps-v1.json | 1 + .../anoncreds/derived-credentials.test.js | 102 ++++++++++++------ tests/test-constants.js | 2 +- 6 files changed, 78 insertions(+), 38 deletions(-) diff --git a/src/modules/accumulator.js b/src/modules/accumulator.js index f636b4db6..d3335ed94 100644 --- a/src/modules/accumulator.js +++ b/src/modules/accumulator.js @@ -374,10 +374,11 @@ export default class AccumulatorModule extends WithParamsAndPublicKeys { * Field `nonce` is the last accepted nonce by the chain, the next write to the accumulator should increment the nonce by 1. * Field `accumulated` contains the current accumulated value. * @param id - * @param withKeyAndParams + * @param withKeyAndParams - Fetch both keys and params. + * @param withKeyOnly - Fetch key only. This is useful when default params are used. * @returns {Promise<{created: *, lastModified: *}|null>} */ - async getAccumulator(id, withKeyAndParams = false) { + async getAccumulator(id, withKeyAndParams = false, withKeyOnly = false) { const resp = await this.api.query[this.moduleName].accumulators( id, ); @@ -400,8 +401,8 @@ export default class AccumulatorModule extends WithParamsAndPublicKeys { const keyId = common.keyRef[1].toNumber(); accumulatorObj.keyRef = [typedHexDIDFromSubstrate(this.api, owner), keyId]; - if (withKeyAndParams) { - const pk = await this.getPublicKeyByHexDid(owner, keyId, true); + if (withKeyAndParams || withKeyOnly) { + const pk = await this.getPublicKeyByHexDid(owner, keyId, withKeyAndParams); if (pk !== null) { accumulatorObj.publicKey = pk; } diff --git a/src/utils/vc/contexts/dock-bbs-v1.json b/src/utils/vc/contexts/dock-bbs-v1.json index 8e0a328e6..7dc51d5f9 100644 --- a/src/utils/vc/contexts/dock-bbs-v1.json +++ b/src/utils/vc/contexts/dock-bbs-v1.json @@ -57,6 +57,7 @@ "unboundedPseudonyms": "https://ld.dock.io/security#unboundedPseudonyms", "attributeCiphertexts": "https://ld.dock.io/security#attributeCiphertexts", "attributeEqualities": "https://ld.dock.io/security#attributeEqualities", + "accumulated": "https://ld.dock.io/security#accumulated", "proofValue": "https://ld.dock.io/security#proofValue", "nonce": "https://ld.dock.io/security#nonce", "proofPurpose": { diff --git a/src/utils/vc/contexts/dock-bbs23-v1.json b/src/utils/vc/contexts/dock-bbs23-v1.json index e412645b9..c1262160f 100644 --- a/src/utils/vc/contexts/dock-bbs23-v1.json +++ b/src/utils/vc/contexts/dock-bbs23-v1.json @@ -57,6 +57,7 @@ "unboundedPseudonyms": "https://ld.dock.io/security#unboundedPseudonyms", "attributeCiphertexts": "https://ld.dock.io/security#attributeCiphertexts", "attributeEqualities": "https://ld.dock.io/security#attributeEqualities", + "accumulated": "https://ld.dock.io/security#accumulated", "proofValue": "https://ld.dock.io/security#proofValue", "nonce": "https://ld.dock.io/security#nonce", "proofPurpose": { diff --git a/src/utils/vc/contexts/dock-ps-v1.json b/src/utils/vc/contexts/dock-ps-v1.json index 9213787ff..2489603cb 100644 --- a/src/utils/vc/contexts/dock-ps-v1.json +++ b/src/utils/vc/contexts/dock-ps-v1.json @@ -57,6 +57,7 @@ "unboundedPseudonyms": "https://ld.dock.io/security#unboundedPseudonyms", "attributeCiphertexts": "https://ld.dock.io/security#attributeCiphertexts", "attributeEqualities": "https://ld.dock.io/security#attributeEqualities", + "accumulated": "https://ld.dock.io/security#accumulated", "proofValue": "https://ld.dock.io/security#proofValue", "nonce": "https://ld.dock.io/security#nonce", "proofPurpose": { diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index cb68a7703..cef2680bf 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -1,6 +1,14 @@ import { randomAsHex } from '@polkadot/util-crypto'; -import { stringToU8a, u8aToHex } from '@polkadot/util'; -import { initializeWasm, BoundCheckSnarkSetup, MembershipWitness } from '@docknetwork/crypto-wasm-ts'; +import b58 from 'bs58'; +import { hexToU8a, stringToU8a, u8aToHex } from '@polkadot/util'; +import { + initializeWasm, + BoundCheckSnarkSetup, + Accumulator, + PositiveAccumulator, + dockAccumulatorParams, AccumulatorPublicKey, +} from '@docknetwork/crypto-wasm-ts'; +import { InMemoryState } from '@docknetwork/crypto-wasm-ts/lib/accumulator/in-memory-persistence'; import { DockAPI } from '../../../src'; import { FullNodeEndpoint, @@ -19,6 +27,7 @@ import { } from '../../../src/utils/vc'; import { DockResolver } from '../../../src/resolver'; import { createPresentation } from '../../create-presentation'; +import AccumulatorModule from '../../../src/modules/accumulator'; // TODO: move to fixtures const residentCardSchema = { @@ -83,6 +92,7 @@ describe.each(Schemes)('Derived Credentials', ({ let chainModule; let keypair; let didDocument; + let accumKeypair; const holder3DID = createNewDockDID(); // seed used for 3rd holder keys @@ -112,6 +122,10 @@ describe.each(Schemes)('Derived Credentials', ({ }, }; + const accumulatorId = randomAsHex(32); + const accumState = new InMemoryState(); + let accumMember; + beforeAll(async () => { await initializeWasm(); await dock.init({ @@ -152,6 +166,31 @@ describe.each(Schemes)('Derived Credentials', ({ holder3DID, new DidKeypair(dock.keyring.addFromUri(holder3KeySeed, null, 'sr25519'), 1), ); + + const params = dockAccumulatorParams(); + accumKeypair = Accumulator.generateKeypair(params); + const bytes1 = u8aToHex(accumKeypair.publicKey.bytes); + const accumPk = AccumulatorModule.prepareAddPublicKey(dock.api, bytes1); + await dock.accumulatorModule.addPublicKey( + accumPk, + did1, + pair1, + { didModule: dock.did }, + false, + ); + + const accumulator = PositiveAccumulator.initialize(params, accumKeypair.secretKey); + const members = []; + for (let i = 1; i < 100; i++) { + members.push(Accumulator.encodePositiveNumberAsAccumulatorMember(i)); + } + accumMember = members[10]; + await accumulator.addBatch(members, accumKeypair.secretKey, accumState); + + const accumulated = u8aToHex(accumulator.accumulated); + await dock.accumulatorModule.addPositiveAccumulator(accumulatorId, accumulated, [did1, 1], did1, pair1, { didModule: dock.didModule }, false); + const queriedAccum = await dock.accumulatorModule.getAccumulator(accumulatorId, false); + expect(queriedAccum.accumulated).toEqual(u8aToHex(accumulator.accumulated)); }, 30000); async function createAndVerifyPresentation(credentials, verifyOptions = {}) { @@ -309,14 +348,19 @@ describe.each(Schemes)('Derived Credentials', ({ }, 30000); test(`For ${Name}, persist credential status when deriving`, async () => { - const provingKeyId = 'provingKeyId'; - const pk = BoundCheckSnarkSetup(); - const provingKey = pk.decompress(); + const queriedAccum = await dock.accumulatorModule.getAccumulator(accumulatorId, false, true); + const verifAccumulator = PositiveAccumulator.fromAccumulated(hexToU8a(queriedAccum.accumulated)); + + // Witness created for member 1 + const witness = await verifAccumulator.membershipWitness(accumMember, accumKeypair.secretKey, accumState); + const accumPk = new AccumulatorPublicKey(hexToU8a(queriedAccum.publicKey.bytes)); + expect(verifAccumulator.verifyMembershipWitness(accumMember, witness, accumPk, dockAccumulatorParams())).toEqual(true); + const credentialStatus = { // Mock data - "id": "dock:accumulator:0xa632a41f2fbdb681c14b33daae4fcc46af41661b90b35c4ac1545c9bebf0d7cc", - "type": "DockVBAccumulator2022", - "revocationCheck": "membership", - "revocationId": "10" + id: `dock:accumulator:${accumulatorId}`, + type: 'DockVBAccumulator2022', + revocationCheck: 'membership', + revocationId: accumMember.toString(), }; const issuerKey = getKeyDoc(did1, keypair, keypair.type, keypair.id); @@ -340,17 +384,7 @@ describe.each(Schemes)('Derived Credentials', ({ credential, { resolver }, ); - - // Mock data - presentationInstance.presBuilder.credStatuses.set(0, [ - new MembershipWitness(new Uint8Array([128, 181, 205, 177, 121, 245, 130, 199, 51, 197, 203, 218, 159, 242, 230, 129, 133, 124, 147, 19, 102, 32, 112, 206, 154, 23, 252, 109, 183, 202, 224, 157, 62, 109, 236, 142, 240, 65, 45, 114, 61, 192, 145, 53, 77, 20, 251, 97])), - new Uint8Array([134, 94, 152, 141, 109, 226, 220, 161, 148, 169, 112, 11, 254, 108, 78, 101, 165, 79, 12, 41, 6, 173, 60, 69, 107, 106, 216, 13, 122, 210, 137, 152, 201, 27, 236, 37, 208, 32, 223, 114, 88, 142, 55, 204, 36, 13, 147, 235]), - { - value: new Uint8Array([144, 222, 74, 116, 11, 85, 191, 161, 154, 160, 165, 58, 28, 247, 188, 193, 151, 115, 185, 194, 145, 137, 220, 171, 101, 205, 91, 72, 133, 234, 215, 244, 184, 128, 176, 115, 142, 63, 222, 45, 128, 75, 229, 32, 214, 57, 129, 93, 11, 22, 152, 101, 220, 48, 128, 52, 9, 130, 75, 194, 131, 36, 80, 117, 100, 118, 83, 139, 233, 181, 112, 243, 19, 80, 75, 183, 60, 223, 18, 43, 58, 114, 158, 229, 88, 103, 40, 195, 140, 114, 185, 179, 219, 240, 58, 244]), - }, - { - }, - ]); + presentationInstance.presBuilder.addAccumInfoForCredStatus(0, witness, hexToU8a(queriedAccum.accumulated), accumPk); // NOTE: revealing subject type because of JSON-LD processing for this certain credential // you may not always need to do this depending on your JSON-LD contexts @@ -361,17 +395,6 @@ describe.each(Schemes)('Derived Credentials', ({ 'credentialSubject.type.1', ]); - // Enforce LPR number to be between values aswell as revealed - // NOTE: unlike other tests, we cannot "reveal" this value and enforce bounds at the same time! - presentationInstance.presBuilder.enforceBounds( - idx, - 'credentialSubject.lprNumber', - 1233, - 1235, - provingKeyId, - provingKey, - ); - // Derive a W3C Verifiable Credential JSON from the above presentation const credentials = await presentationInstance.deriveCredentials( presentationOptions, @@ -381,10 +404,23 @@ describe.each(Schemes)('Derived Credentials', ({ expect(credentials[0].credentialStatus).toBeDefined(); expect(credentials[0].credentialStatus).toEqual({ ...credentialStatus, - revocationId: undefined, - accumulated: '5vtBeJk2aRi6J2KaVhg7hiVbcDoBWmnhRrWZ4ohnR37FsaFq1XquTBeneqMATg3HQv', + revocationId: undefined, // Because revocation id is never revealed + accumulated: b58.encode(hexToU8a(queriedAccum.accumulated)), extra: {}, }); + + // TODO: Following checks fail. Fix them. + const accumulatorPublicKeys = new Map(); + accumulatorPublicKeys.set(0, accumPk); + const credentialResult = await verifyCredential(credentials[0], { + resolver, + accumulatorPublicKeys, + }); + expect(credentialResult.verified).toBe(true); + expect(credentialResult.error).toBe(undefined); + + // Create a VP and verify it from this credential + await createAndVerifyPresentation(credentials, { accumulatorPublicKeys }); }); test('Holder creates a derived verifiable credential from a credential with range proofs', async () => { diff --git a/tests/test-constants.js b/tests/test-constants.js index dc4d501ef..f9ddbb78f 100644 --- a/tests/test-constants.js +++ b/tests/test-constants.js @@ -36,7 +36,7 @@ const DefaultTestAccountURI = '//Alice'; const DefaultTestAccountCouncilMemberURI = '//Charlie'; const DefaultMinGasPrice = 50; const DefaultMaxGas = 429496729; -const DefaultTestSchemes = 'BBS,BBSPlus,PS'; +const DefaultTestSchemes = 'BBSPlus'; const boolEnv = (value) => value === 'true' || !!+value; From e6b70903fadf05c719fb344ad9d22def58c6f54a Mon Sep 17 00:00:00 2001 From: lovesh Date: Thu, 15 Feb 2024 20:53:28 +0530 Subject: [PATCH 06/15] Add status in convertToPresentation Signed-off-by: lovesh --- .../crypto/common/DockCryptoSignatureProof.js | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/utils/vc/crypto/common/DockCryptoSignatureProof.js b/src/utils/vc/crypto/common/DockCryptoSignatureProof.js index b33fe116d..43dabc821 100644 --- a/src/utils/vc/crypto/common/DockCryptoSignatureProof.js +++ b/src/utils/vc/crypto/common/DockCryptoSignatureProof.js @@ -98,33 +98,39 @@ export default withExtendedStaticProperties( '@context': context, type, credentialSchema, + credentialStatus, issuer: _issuer, issuanceDate: _issuanceDate, proof, ...revealedAttributes } = document; + // TODO: This is wrong. This won't work with presentation from 2 or more credentials + const c = { + sigType: proof.sigType, + version: proof.version, + bounds: proof.bounds, + schema: JSON.stringify(credentialSchema), + revealedAttributes: { + proof: { + type: this.sigName, + verificationMethod: proof.verificationMethod, + }, + '@context': JSON.stringify(context), + type: JSON.stringify(type), + ...revealedAttributes, + }, + }; + if (credentialStatus !== undefined) { + c.status = credentialStatus; + } return { version: proof.version, nonce: proof.nonce, context: proof.context, spec: { credentials: [ - { - sigType: proof.sigType, - version: proof.version, - bounds: proof.bounds, - schema: JSON.stringify(credentialSchema), - revealedAttributes: { - proof: { - type: this.sigName, - verificationMethod: proof.verificationMethod, - }, - '@context': JSON.stringify(context), - type: JSON.stringify(type), - ...revealedAttributes, - }, - }, + c, ], attributeEqualities: proof.attributeEqualities, boundedPseudonyms: proof.boundedPseudonyms, From 7ae5c53b34f6f4ed752bcc2adbe07acf006929c3 Mon Sep 17 00:00:00 2001 From: lovesh Date: Thu, 15 Feb 2024 21:26:46 +0530 Subject: [PATCH 07/15] fix tests Signed-off-by: lovesh --- tests/integration/anoncreds/derived-credentials.test.js | 4 ---- tests/test-constants.js | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index cef2680bf..30cf4d100 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -409,7 +409,6 @@ describe.each(Schemes)('Derived Credentials', ({ extra: {}, }); - // TODO: Following checks fail. Fix them. const accumulatorPublicKeys = new Map(); accumulatorPublicKeys.set(0, accumPk); const credentialResult = await verifyCredential(credentials[0], { @@ -418,9 +417,6 @@ describe.each(Schemes)('Derived Credentials', ({ }); expect(credentialResult.verified).toBe(true); expect(credentialResult.error).toBe(undefined); - - // Create a VP and verify it from this credential - await createAndVerifyPresentation(credentials, { accumulatorPublicKeys }); }); test('Holder creates a derived verifiable credential from a credential with range proofs', async () => { diff --git a/tests/test-constants.js b/tests/test-constants.js index f9ddbb78f..dc4d501ef 100644 --- a/tests/test-constants.js +++ b/tests/test-constants.js @@ -36,7 +36,7 @@ const DefaultTestAccountURI = '//Alice'; const DefaultTestAccountCouncilMemberURI = '//Charlie'; const DefaultMinGasPrice = 50; const DefaultMaxGas = 429496729; -const DefaultTestSchemes = 'BBSPlus'; +const DefaultTestSchemes = 'BBS,BBSPlus,PS'; const boolEnv = (value) => value === 'true' || !!+value; From 6e3cb69cb27ead7547f6716f67812736ae8bbaa4 Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Thu, 15 Feb 2024 20:02:27 +0000 Subject: [PATCH 08/15] bump version Signed-off-by: Sam Hellawell --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ea56126b..fc00d605b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@docknetwork/sdk", - "version": "7.3.1", + "version": "7.3.2", "main": "index.js", "license": "MIT", "repository": { From 0cd741206da5a6d15fd85bdc46a31f26ebef9e81 Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Thu, 15 Feb 2024 21:34:58 +0000 Subject: [PATCH 09/15] fix test with full flow --- src/presentation.js | 3 ++ src/utils/revocation.js | 6 ++-- src/utils/vc/contexts/dock-bbs-v1.json | 17 +++++++++- src/utils/vc/contexts/dock-bbs23-v1.json | 16 ++++++++++ src/utils/vc/contexts/dock-ps-v1.json | 16 ++++++++++ .../crypto/common/DockCryptoSignatureProof.js | 11 +++++-- src/utils/vc/presentations.js | 4 ++- src/verifiable-presentation.js | 10 +++++- tests/create-presentation.js | 23 ++++---------- .../anoncreds/derived-credentials.test.js | 31 ++++++++++++------- tests/test-constants.js | 12 +++---- 11 files changed, 108 insertions(+), 41 deletions(-) diff --git a/src/presentation.js b/src/presentation.js index 59ea9eefd..5ba4b9f8c 100644 --- a/src/presentation.js +++ b/src/presentation.js @@ -11,6 +11,7 @@ import { stringToU8a } from '@polkadot/util'; import { ensureArray } from './utils/type-helpers'; import Bls12381BBSSignatureDock2022 from './utils/vc/crypto/Bls12381BBSSignatureDock2022'; +import { DOCK_ANON_CREDENTIAL_ID } from './utils/vc/crypto/common/DockCryptoSignatureProof'; import { Bls12381BBSSigDockSigName, Bls12381PSSigDockSigName, @@ -167,6 +168,8 @@ export default class Presentation { const w3cFormattedCredential = { ...credential.revealedAttributes, + // ID required for W£C formatted credentials, if not revealed used a static URI + id: credential.revealedAttributes.id || DOCK_ANON_CREDENTIAL_ID, '@context': JSON.parse(credential.revealedAttributes['@context']), type: JSON.parse(credential.revealedAttributes.type), credentialSchema: JSON.parse(credential.schema), diff --git a/src/utils/revocation.js b/src/utils/revocation.js index a123c05b1..82160df18 100644 --- a/src/utils/revocation.js +++ b/src/utils/revocation.js @@ -17,6 +17,8 @@ export const RevRegIdByteSize = 32; // Each entry in revocation registry has byte size `RevEntryByteSize` export const RevEntryByteSize = 32; +const LD_SEC_TERM = 'https://ld.dock.io/security#'; + /** * Return `credentialStatus` according to W3C spec when the revocation status is checked on Dock * @param registryId - Revocation registry id @@ -76,14 +78,14 @@ export function getCredentialStatus(expanded) { * @param status * @returns {boolean} */ -export const isRegistryRevocationStatus = ({ [credentialTypeField]: type }) => type.includes(RevRegType) || type.includes(`/${RevRegType}`); +export const isRegistryRevocationStatus = ({ [credentialTypeField]: type }) => type.includes(RevRegType) || type.includes(`${LD_SEC_TERM}${RevRegType}`) || type.includes(`/${RevRegType}`); /** * Returns `true` if supplied status is a accumulator revocation status. * @param status * @returns {boolean} */ -export const isAccumulatorRevocationStatus = ({ [credentialTypeField]: type }) => type.includes(VB_ACCUMULATOR_22) || type.includes(`/${VB_ACCUMULATOR_22}`); +export const isAccumulatorRevocationStatus = ({ [credentialTypeField]: type }) => type.includes(VB_ACCUMULATOR_22) || type.includes(`${LD_SEC_TERM}${VB_ACCUMULATOR_22}`) || type.includes(`/${VB_ACCUMULATOR_22}`); /** * Checks if a credential status has a registry revocation. diff --git a/src/utils/vc/contexts/dock-bbs-v1.json b/src/utils/vc/contexts/dock-bbs-v1.json index 7dc51d5f9..dab639bad 100644 --- a/src/utils/vc/contexts/dock-bbs-v1.json +++ b/src/utils/vc/contexts/dock-bbs-v1.json @@ -34,6 +34,22 @@ "@type": "@id", "@container": "@graph" }, + "DockVBAccumulator2022": { + "@id": "https://ld.dock.io/security#DockVBAccumulator2022", + "@context": { + "@version": 1.1, + "@protected": true, + "id": "@id", + "type": "@type", + "accumulated": "https://ld.dock.io/security#accumulated", + "revocationCheck": "https://ld.dock.io/security#revocationCheck", + "revocationId": "https://ld.dock.io/security#revocationId", + "extra": { + "@id": "https://ld.dock.io/security#extra", + "@context": {"@vocab": "https://ld.dock.io/security/extra"} + } + } + }, "Bls12381BBS+SignatureProofDock2022": { "@id": "https://ld.dock.io/security#Bls12381BBS+SignatureDock2022", "@context": { @@ -57,7 +73,6 @@ "unboundedPseudonyms": "https://ld.dock.io/security#unboundedPseudonyms", "attributeCiphertexts": "https://ld.dock.io/security#attributeCiphertexts", "attributeEqualities": "https://ld.dock.io/security#attributeEqualities", - "accumulated": "https://ld.dock.io/security#accumulated", "proofValue": "https://ld.dock.io/security#proofValue", "nonce": "https://ld.dock.io/security#nonce", "proofPurpose": { diff --git a/src/utils/vc/contexts/dock-bbs23-v1.json b/src/utils/vc/contexts/dock-bbs23-v1.json index c1262160f..89fa4889d 100644 --- a/src/utils/vc/contexts/dock-bbs23-v1.json +++ b/src/utils/vc/contexts/dock-bbs23-v1.json @@ -34,6 +34,22 @@ "@type": "@id", "@container": "@graph" }, + "DockVBAccumulator2022": { + "@id": "https://ld.dock.io/security#DockVBAccumulator2022", + "@context": { + "@version": 1.1, + "@protected": true, + "id": "@id", + "type": "@type", + "accumulated": "https://ld.dock.io/security#accumulated", + "revocationCheck": "https://ld.dock.io/security#revocationCheck", + "revocationId": "https://ld.dock.io/security#revocationId", + "extra": { + "@id": "https://ld.dock.io/security#extra", + "@context": {"@vocab": "https://ld.dock.io/security/extra"} + } + } + }, "Bls12381BBSSignatureProofDock2023": { "@id": "https://ld.dock.io/security#Bls12381BBSSignatureDock2023", "@context": { diff --git a/src/utils/vc/contexts/dock-ps-v1.json b/src/utils/vc/contexts/dock-ps-v1.json index 2489603cb..ade5639a5 100644 --- a/src/utils/vc/contexts/dock-ps-v1.json +++ b/src/utils/vc/contexts/dock-ps-v1.json @@ -34,6 +34,22 @@ "@type": "@id", "@container": "@graph" }, + "DockVBAccumulator2022": { + "@id": "https://ld.dock.io/security#DockVBAccumulator2022", + "@context": { + "@version": 1.1, + "@protected": true, + "id": "@id", + "type": "@type", + "accumulated": "https://ld.dock.io/security#accumulated", + "revocationCheck": "https://ld.dock.io/security#revocationCheck", + "revocationId": "https://ld.dock.io/security#revocationId", + "extra": { + "@id": "https://ld.dock.io/security#extra", + "@context": {"@vocab": "https://ld.dock.io/security/extra"} + } + } + }, "Bls12381PSSignatureProofDock2023": { "@id": "https://ld.dock.io/security#Bls12381PSSignatureDock2023", "@context": { diff --git a/src/utils/vc/crypto/common/DockCryptoSignatureProof.js b/src/utils/vc/crypto/common/DockCryptoSignatureProof.js index 43dabc821..0db174a25 100644 --- a/src/utils/vc/crypto/common/DockCryptoSignatureProof.js +++ b/src/utils/vc/crypto/common/DockCryptoSignatureProof.js @@ -6,6 +6,8 @@ import CustomLinkedDataSignature from './CustomLinkedDataSignature'; const SUITE_CONTEXT_URL = 'https://www.w3.org/2018/credentials/v1'; +export const DOCK_ANON_CREDENTIAL_ID = 'dock:anonymous:credential'; + /** * Defines commons for the `@docknetwork/crypto-wasm-ts` signature proofs. */ @@ -63,7 +65,7 @@ export default withExtendedStaticProperties( expansionMap, }); - const presentationJSON = this.constructor.convertToPresentation({ + const presentationJSON = this.constructor.derivedToAnoncredsPresentation({ ...document, proof, }); @@ -93,7 +95,7 @@ export default withExtendedStaticProperties( * Converts a derived proof credential to the native presentation format * @param document */ - static convertToPresentation(document) { + static derivedToAnoncredsPresentation(document) { const { '@context': context, type, @@ -105,6 +107,11 @@ export default withExtendedStaticProperties( ...revealedAttributes } = document; + // ID wasnt revealed but placeholder was used to conform to W3C spec, trim it + if (revealedAttributes.id === DOCK_ANON_CREDENTIAL_ID) { + delete revealedAttributes.id; + } + // TODO: This is wrong. This won't work with presentation from 2 or more credentials const c = { sigType: proof.sigType, diff --git a/src/utils/vc/presentations.js b/src/utils/vc/presentations.js index 146a0e97d..1c5931ee9 100644 --- a/src/utils/vc/presentations.js +++ b/src/utils/vc/presentations.js @@ -240,7 +240,7 @@ export async function signPresentation( }); const documentLoader = defaultDocumentLoader(resolver); - return jsigs.sign(presentation, { + const signed = await jsigs.sign(presentation, { purpose, documentLoader, domain, @@ -249,6 +249,8 @@ export async function signPresentation( suite, addSuiteContext, }); + signed.proof = signed.proof.pop(); + return signed; } export function isAnoncreds(presentation) { diff --git a/src/verifiable-presentation.js b/src/verifiable-presentation.js index 6cdf63488..cb9a3e646 100644 --- a/src/verifiable-presentation.js +++ b/src/verifiable-presentation.js @@ -155,6 +155,15 @@ class VerifiablePresentation { return this; } + /** + * Add multiple Verifiable Credentials to this Presentation. Duplicates will be ignored. + * @param {Array} credentials - Verifiable Credential for the presentation + * @returns {VerifiablePresentation} + */ + addCredentials(credentials) { + credentials.forEach(this.addCredential.bind(this)); + } + /** * Define the JSON representation of a Verifiable Presentation. * @returns {object} @@ -186,7 +195,6 @@ class VerifiablePresentation { resolver, compactProof, ); - this.proof = signedVP.proof.pop(); this.context = signedVP['@context']; return this; } diff --git a/tests/create-presentation.js b/tests/create-presentation.js index e2e82b187..b444e5e0a 100644 --- a/tests/create-presentation.js +++ b/tests/create-presentation.js @@ -1,6 +1,4 @@ -import { - DEFAULT_CONTEXT_V1_URL, -} from '../src/utils/vc/constants'; +import VerifiablePresentation from '../src/verifiable-presentation'; /** * Create an unsigned Verifiable Presentation @@ -9,22 +7,13 @@ import { * @param {string} [holder] - optional presentation holder url * @return {object} verifiable presentation. */ -export function createPresentation(verifiableCredential, id, holder = null) { - const presentation = { - '@context': [DEFAULT_CONTEXT_V1_URL], - type: ['VerifiablePresentation'], - }; - +export function createPresentation(verifiableCredential, id = 'http://example.edu/presentation/2803', holder = null) { + const presentation = new VerifiablePresentation(id); if (verifiableCredential) { - const credentials = [].concat(verifiableCredential); - presentation.verifiableCredential = credentials; - } - if (id) { - presentation.id = id; + presentation.addCredentials([].concat(verifiableCredential)); } if (holder) { - presentation.holder = holder; + presentation.setHolder(holder); } - - return presentation; + return presentation.toJSON(); } diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index 30cf4d100..d73ae3e3e 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -82,7 +82,7 @@ describe.each(Schemes)('Derived Credentials', ({ VerKey, getModule, Context, - convertToPresentation, + derivedToAnoncredsPresentation, }) => { const dock = new DockAPI(); const resolver = new DockResolver(dock); @@ -200,21 +200,22 @@ describe.each(Schemes)('Derived Credentials', ({ 'Sr25519VerificationKey2020', ); - const presId = randomAsHex(32); + const presId = `https://example.com/pres/${randomAsHex(32)}`; const chal = randomAsHex(32); const domain = 'test domain'; const presentation = createPresentation(credentials, presId); expect(presentation).toMatchObject( - expect.objectContaining({ + // NOTE: json parse+stringify to remove any undefined properties + expect.objectContaining(JSON.parse(JSON.stringify({ type: ['VerifiablePresentation'], verifiableCredential: credentials, id: presId, - }), + }))), ); - // Question: What is the point of this? Verifying this would require knowing the holder's public key which makes - // the holder linkable and defeats the purpose of BBS+ + // NOTE: typically for BBS+ presentations you shouldnt sign it by the holder, but we do it here just to make sure it works + // Verifying this would require knowing the holder's public key which makes the holder linkable and defeats the purpose of BBS+ const signedPres = await signPresentation( presentation, holderKey, @@ -329,7 +330,7 @@ describe.each(Schemes)('Derived Credentials', ({ // Question: What is the point of this? A single credential cant be converted to a presentation and a presentation // has other data that credential won't have - const reconstructedPres = convertToPresentation(credentials[0]); + const reconstructedPres = derivedToAnoncredsPresentation(credentials[0]); expect(reconstructedPres.proof).toBeDefined(); expect({ ...reconstructedPres, @@ -377,6 +378,7 @@ describe.each(Schemes)('Derived Credentials', ({ // Create W3C credential const credential = await issueCredential(issuerKey, unsignedCred); + expect(credential.id).toBeDefined(); // Begin to derive a credential from the above issued one const presentationInstance = new Presentation(); @@ -411,12 +413,19 @@ describe.each(Schemes)('Derived Credentials', ({ const accumulatorPublicKeys = new Map(); accumulatorPublicKeys.set(0, accumPk); - const credentialResult = await verifyCredential(credentials[0], { + + // const credentialResult = await verifyCredential(credentials[0], { + // resolver, + // accumulatorPublicKeys, + // }); + // expect(credentialResult.verified).toBe(true); + // expect(credentialResult.error).toBe(undefined); + + // Create a VP and verify it from this credential + await createAndVerifyPresentation(credentials, { resolver, accumulatorPublicKeys, }); - expect(credentialResult.verified).toBe(true); - expect(credentialResult.error).toBe(undefined); }); test('Holder creates a derived verifiable credential from a credential with range proofs', async () => { @@ -506,7 +515,7 @@ describe.each(Schemes)('Derived Credentials', ({ }), ); - const reconstructedPres = convertToPresentation(credentials[0]); + const reconstructedPres = derivedToAnoncredsPresentation(credentials[0]); expect(reconstructedPres.proof).toBeDefined(); expect(reconstructedPres.spec.credentials[0].bounds).toEqual(credentials[0].proof.bounds); diff --git a/tests/test-constants.js b/tests/test-constants.js index dc4d501ef..38355b5d6 100644 --- a/tests/test-constants.js +++ b/tests/test-constants.js @@ -94,8 +94,8 @@ export const BBS = { Signature: BBSSignature, KeyPair: BBSKeypair, CryptoKeyPair: Bls12381BBSKeyPairDock2023, - convertToPresentation: - Bls12381BBSSignatureProofDock2023.convertToPresentation.bind( + derivedToAnoncredsPresentation: + Bls12381BBSSignatureProofDock2023.derivedToAnoncredsPresentation.bind( Bls12381BBSSignatureProofDock2023, ), SigType: 'Bls12381BBSSignatureDock2023', @@ -117,8 +117,8 @@ export const BBSPlus = { Signature: BBSPlusSignatureG1, KeyPair: BBSPlusKeypairG2, CryptoKeyPair: Bls12381G2KeyPairDock2022, - convertToPresentation: - Bls12381BBSSignatureProofDock2022.convertToPresentation.bind( + derivedToAnoncredsPresentation: + Bls12381BBSSignatureProofDock2022.derivedToAnoncredsPresentation.bind( Bls12381BBSSignatureProofDock2022, ), Context: 'https://ld.dock.io/security/bbs/v1', @@ -140,8 +140,8 @@ export const PS = { Signature: PSSignature, KeyPair: PSKeypair, CryptoKeyPair: Bls12381PSKeyPairDock2023, - convertToPresentation: - Bls12381PSSignatureProofDock2023.convertToPresentation.bind( + derivedToAnoncredsPresentation: + Bls12381PSSignatureProofDock2023.derivedToAnoncredsPresentation.bind( Bls12381PSSignatureProofDock2023, ), SigType: 'Bls12381PSSignatureDock2023', From 6027204ef8a413286d7817b4e5598a081508691f Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Thu, 15 Feb 2024 21:40:04 +0000 Subject: [PATCH 10/15] check proof is array before popping --- src/utils/vc/presentations.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/vc/presentations.js b/src/utils/vc/presentations.js index 1c5931ee9..acfea3641 100644 --- a/src/utils/vc/presentations.js +++ b/src/utils/vc/presentations.js @@ -249,7 +249,9 @@ export async function signPresentation( suite, addSuiteContext, }); - signed.proof = signed.proof.pop(); + if (Array.isArray(signed.proof)) { + signed.proof = signed.proof.pop(); + } return signed; } From e886919705920bd16f58d5cded2f5a7704ac3c2a Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Thu, 15 Feb 2024 22:01:59 +0000 Subject: [PATCH 11/15] fix tests --- src/utils/vc/presentations.js | 8 +++++++- src/verifiable-presentation.js | 1 + tests/create-presentation.js | 6 ++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/utils/vc/presentations.js b/src/utils/vc/presentations.js index acfea3641..4281f6a31 100644 --- a/src/utils/vc/presentations.js +++ b/src/utils/vc/presentations.js @@ -249,8 +249,14 @@ export async function signPresentation( suite, addSuiteContext, }); + + // Sometimes jsigs returns proof like [null, { proof }] + // check for that case here and if there's only 1 proof store object instead if (Array.isArray(signed.proof)) { - signed.proof = signed.proof.pop(); + const validProofs = signed.proof.filter((p) => !!p); + if (validProofs.length === 1) { + signed.proof = validProofs.pop(); + } } return signed; } diff --git a/src/verifiable-presentation.js b/src/verifiable-presentation.js index cb9a3e646..b92b12c14 100644 --- a/src/verifiable-presentation.js +++ b/src/verifiable-presentation.js @@ -196,6 +196,7 @@ class VerifiablePresentation { compactProof, ); this.context = signedVP['@context']; + this.proof = signedVP.proof; return this; } diff --git a/tests/create-presentation.js b/tests/create-presentation.js index b444e5e0a..9de25bc33 100644 --- a/tests/create-presentation.js +++ b/tests/create-presentation.js @@ -9,8 +9,10 @@ import VerifiablePresentation from '../src/verifiable-presentation'; */ export function createPresentation(verifiableCredential, id = 'http://example.edu/presentation/2803', holder = null) { const presentation = new VerifiablePresentation(id); - if (verifiableCredential) { - presentation.addCredentials([].concat(verifiableCredential)); + if (Array.isArray(verifiableCredential)) { + presentation.addCredentials(verifiableCredential); + } else { + presentation.addCredential(verifiableCredential); } if (holder) { presentation.setHolder(holder); From 9eaf9eafa6eb12d54bbdc8d38e26d0719a15733c Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Thu, 15 Feb 2024 22:12:45 +0000 Subject: [PATCH 12/15] remove useless test --- tests/unit/issuing.test.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/unit/issuing.test.js b/tests/unit/issuing.test.js index 010262921..1d4e93a62 100644 --- a/tests/unit/issuing.test.js +++ b/tests/unit/issuing.test.js @@ -7,7 +7,6 @@ import { verifyPresentation, signPresentation, } from '../../src/utils/vc/index'; -import { createPresentation } from '../create-presentation'; import VerifiableCredential from '../../src/verifiable-credential'; import VerifiablePresentation from '../../src/verifiable-presentation'; import testingKeys from '../test-keys'; @@ -142,15 +141,6 @@ testingKeys.forEach((testKey) => { presentationCredentials = [sampleIssuedCredential, sampleIssuedCredential]; }); - test('A proper verifiable presentation should be created from two valid sample credentials.', async () => { - const presentation = createPresentation( - presentationCredentials, - vpId, - vpHolder, - ); - expect(presentation).toMatchObject(getSamplePres(presentationCredentials)); - }, 30000); - test('A verifiable presentation should contain a proof once signed, and it should pass verification.', async () => { const signedVp = await signPresentation( getSamplePres(presentationCredentials), From f366b55988b143ff9bb977d46e615a4cee823064 Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Thu, 15 Feb 2024 22:31:21 +0000 Subject: [PATCH 13/15] fix presentation IDs in tests Signed-off-by: Sam Hellawell --- tests/integration/credential-revocation.test.js | 2 +- .../issuing-and-presentation-with-2-subjects.test.js | 2 +- tests/integration/presenting.test.js | 4 ++-- tests/integration/private-status-list-credential.test.js | 2 +- tests/integration/status-list-credential.test.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/integration/credential-revocation.test.js b/tests/integration/credential-revocation.test.js index b5cfa1dcd..3b65b0b11 100644 --- a/tests/integration/credential-revocation.test.js +++ b/tests/integration/credential-revocation.test.js @@ -119,7 +119,7 @@ describe('Credential revocation with issuer as the revocation authority', () => const holderKey = getKeyDoc(holderDID, dockAPI.keyring.addFromUri(holderSeed, null, 'ed25519'), 'Ed25519VerificationKey2018'); // Create presentation for unrevoked credential - const presId = randomAsHex(32); + const presId = `https://pres.com/${randomAsHex(32)}`; const chal = randomAsHex(32); const domain = 'test domain'; const presentation = createPresentation( diff --git a/tests/integration/issuing-and-presentation-with-2-subjects.test.js b/tests/integration/issuing-and-presentation-with-2-subjects.test.js index 6556c481c..8d3bb4f53 100644 --- a/tests/integration/issuing-and-presentation-with-2-subjects.test.js +++ b/tests/integration/issuing-and-presentation-with-2-subjects.test.js @@ -125,7 +125,7 @@ describe('Verifiable Credential issuance and presentation where the credential h test('Holder creates a verifiable presentation and verifier verifies it and does some other checks', async () => { const holderKey = getKeyDoc(subject1DID, dock.keyring.addFromUri(subject1Seed, null, 'ed25519'), 'Ed25519VerificationKey2018'); - const presId = randomAsHex(32); + const presId = `https://pres.com/${randomAsHex(32)}`; const challenge = randomAsHex(32); const domain = 'test domain'; diff --git a/tests/integration/presenting.test.js b/tests/integration/presenting.test.js index d9f51d64e..bda206a9f 100644 --- a/tests/integration/presenting.test.js +++ b/tests/integration/presenting.test.js @@ -116,7 +116,7 @@ describe('Verifiable Presentation where both issuer and holder have a Dock DID', }); expect(res).toBe(true); - const presId = randomAsHex(32); + const presId = `https://pres.com/${randomAsHex(32)}`; const chal = randomAsHex(32); const domain = 'test domain'; const presentation = createPresentation( @@ -186,7 +186,7 @@ describe('Verifiable Presentation where both issuer and holder have a Dock DID', }); expect(res1).toBe(true); - const presId = randomAsHex(32); + const presId = `https://pres.com/${randomAsHex(32)}`; const chal = randomAsHex(32); const domain = 'test domain'; diff --git a/tests/integration/private-status-list-credential.test.js b/tests/integration/private-status-list-credential.test.js index 793a40dc2..62fd371bc 100644 --- a/tests/integration/private-status-list-credential.test.js +++ b/tests/integration/private-status-list-credential.test.js @@ -164,7 +164,7 @@ describe('PrivateStatusList2021Credential', () => { ); // Create presentation for unsuspended credential - const presId = randomAsHex(32); + const presId = `https://pres.com/${randomAsHex(32)}`; const chal = randomAsHex(32); const domain = 'test domain'; const presentation = createPresentation(credential, presId); diff --git a/tests/integration/status-list-credential.test.js b/tests/integration/status-list-credential.test.js index f84b1be02..8c6ae458d 100644 --- a/tests/integration/status-list-credential.test.js +++ b/tests/integration/status-list-credential.test.js @@ -183,7 +183,7 @@ buildTest('StatusList2021Credential', () => { ); // Create presentation for unsuspended credential - const presId = randomAsHex(32); + const presId = `https://pres.com/${randomAsHex(32)}`; const chal = randomAsHex(32); const domain = 'test domain'; const presentation = createPresentation(credential, presId); From f125500b14a8bc4afbe688e5bb27e302c169ec51 Mon Sep 17 00:00:00 2001 From: lovesh Date: Fri, 16 Feb 2024 12:42:44 +0530 Subject: [PATCH 14/15] Fix anoncreds pres. verify check Signed-off-by: lovesh --- src/utils/vc/crypto/common/DockCryptoSignatureProof.js | 5 +++-- .../integration/anoncreds/derived-credentials.test.js | 10 +++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/utils/vc/crypto/common/DockCryptoSignatureProof.js b/src/utils/vc/crypto/common/DockCryptoSignatureProof.js index 0db174a25..47e7ff677 100644 --- a/src/utils/vc/crypto/common/DockCryptoSignatureProof.js +++ b/src/utils/vc/crypto/common/DockCryptoSignatureProof.js @@ -81,8 +81,9 @@ export default withExtendedStaticProperties( circomOutputs, blindedAttributesCircomOutputs, } = this; - if (!recreatedPres.verify(pks, accumulatorPublicKeys, predicateParams, circomOutputs, blindedAttributesCircomOutputs)) { - throw new Error('Invalid signature'); + const res = recreatedPres.verify(pks, accumulatorPublicKeys, predicateParams, circomOutputs, blindedAttributesCircomOutputs); + if (!res.verified) { + throw new Error(`Invalid anoncreds presentation due to error: ${res.error}`); } return { verified: true, verificationMethod }; diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index d73ae3e3e..5c9966647 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -6,7 +6,7 @@ import { BoundCheckSnarkSetup, Accumulator, PositiveAccumulator, - dockAccumulatorParams, AccumulatorPublicKey, + dockAccumulatorParams, AccumulatorPublicKey, deepClone, } from '@docknetwork/crypto-wasm-ts'; import { InMemoryState } from '@docknetwork/crypto-wasm-ts/lib/accumulator/in-memory-persistence'; import { DockAPI } from '../../../src'; @@ -344,6 +344,14 @@ describe.each(Schemes)('Derived Credentials', ({ expect(credentialResult.verified).toBe(true); expect(credentialResult.error).toBe(undefined); + // Modify the credential after issuance, verification should fail + const modifiedCred = deepClone(credentials[0]); + modifiedCred.credentialSubject.lprNumber = 0xdeadbeef; + const credentialResult1 = await verifyCredential(modifiedCred, { + resolver, + }); + expect(credentialResult1.verified).toBe(false); + // Create a VP and verify it from this credential await createAndVerifyPresentation(credentials); }, 30000); From ea0ebdd45a00ddd062379da528d6aabff3bb9fe9 Mon Sep 17 00:00:00 2001 From: lovesh Date: Fri, 16 Feb 2024 17:30:59 +0530 Subject: [PATCH 15/15] Fix accum test Signed-off-by: lovesh --- .../anoncreds/derived-credentials.test.js | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index 5c9966647..dfe566a72 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -7,6 +7,7 @@ import { Accumulator, PositiveAccumulator, dockAccumulatorParams, AccumulatorPublicKey, deepClone, + Encoder, } from '@docknetwork/crypto-wasm-ts'; import { InMemoryState } from '@docknetwork/crypto-wasm-ts/lib/accumulator/in-memory-persistence'; import { DockAPI } from '../../../src'; @@ -182,9 +183,11 @@ describe.each(Schemes)('Derived Credentials', ({ const accumulator = PositiveAccumulator.initialize(params, accumKeypair.secretKey); const members = []; for (let i = 1; i < 100; i++) { - members.push(Accumulator.encodePositiveNumberAsAccumulatorMember(i)); + // Using default encoder since thats what the is used in credential by default. Ideally, the encoder specified in + // the particular schema should be used but for that is the default one + members.push(Encoder.defaultEncodeFunc()(i.toString())); } - accumMember = members[10]; + accumMember = '10'; await accumulator.addBatch(members, accumKeypair.secretKey, accumState); const accumulated = u8aToHex(accumulator.accumulated); @@ -357,19 +360,20 @@ describe.each(Schemes)('Derived Credentials', ({ }, 30000); test(`For ${Name}, persist credential status when deriving`, async () => { + const encodedMember = Encoder.defaultEncodeFunc()(accumMember); const queriedAccum = await dock.accumulatorModule.getAccumulator(accumulatorId, false, true); const verifAccumulator = PositiveAccumulator.fromAccumulated(hexToU8a(queriedAccum.accumulated)); // Witness created for member 1 - const witness = await verifAccumulator.membershipWitness(accumMember, accumKeypair.secretKey, accumState); + const witness = await verifAccumulator.membershipWitness(encodedMember, accumKeypair.secretKey, accumState); const accumPk = new AccumulatorPublicKey(hexToU8a(queriedAccum.publicKey.bytes)); - expect(verifAccumulator.verifyMembershipWitness(accumMember, witness, accumPk, dockAccumulatorParams())).toEqual(true); + expect(verifAccumulator.verifyMembershipWitness(encodedMember, witness, accumPk, dockAccumulatorParams())).toEqual(true); - const credentialStatus = { // Mock data + const credentialStatus = { id: `dock:accumulator:${accumulatorId}`, type: 'DockVBAccumulator2022', revocationCheck: 'membership', - revocationId: accumMember.toString(), + revocationId: accumMember, }; const issuerKey = getKeyDoc(did1, keypair, keypair.type, keypair.id); @@ -422,13 +426,6 @@ describe.each(Schemes)('Derived Credentials', ({ const accumulatorPublicKeys = new Map(); accumulatorPublicKeys.set(0, accumPk); - // const credentialResult = await verifyCredential(credentials[0], { - // resolver, - // accumulatorPublicKeys, - // }); - // expect(credentialResult.verified).toBe(true); - // expect(credentialResult.error).toBe(undefined); - // Create a VP and verify it from this credential await createAndVerifyPresentation(credentials, { resolver,