From db5b9e0bf3ead27399391597c626d97f5e0e021a Mon Sep 17 00:00:00 2001 From: lovesh Date: Sat, 29 Jun 2024 12:27:49 +0530 Subject: [PATCH] Change schema format from data-uri to object Signed-off-by: lovesh --- example/bbs-dock.js | 7 +- package.json | 7 +- src/presentation.js | 3 +- src/utils/vc/contexts/dock-bbs-v1.json | 5 + src/utils/vc/contexts/dock-bbs23-v1.json | 5 + src/utils/vc/contexts/dock-bddt16-v1.json | 5 + src/utils/vc/contexts/dock-ps-v1.json | 5 + src/utils/vc/credentials.js | 5 +- .../vc/crypto/common/DockCryptoSignature.js | 66 +++++++++---- .../crypto/common/DockCryptoSignatureProof.js | 7 +- src/utils/vc/presentations.js | 7 +- .../anoncreds/derived-credentials.test.js | 10 +- tests/integration/anoncreds/issuing.test.js | 96 +++++++++---------- tests/integration/anoncreds/utils.js | 19 ++-- yarn.lock | 16 +--- 15 files changed, 160 insertions(+), 103 deletions(-) diff --git a/example/bbs-dock.js b/example/bbs-dock.js index 32f5f5225..d2706c2ee 100644 --- a/example/bbs-dock.js +++ b/example/bbs-dock.js @@ -2,6 +2,7 @@ import { initializeWasm } from '@docknetwork/crypto-wasm-ts'; import { DIDResolver } from '../src/resolver'; import Bls12381G2KeyPairDock2022 from '../src/utils/vc/crypto/Bls12381G2KeyPairDock2022'; import { issueCredential, verifyCredential } from '../src/utils/vc'; +import stringify from 'json-stringify-deterministic'; const keypairOpts = { id: 'did:example:489398593#keys-1', @@ -34,9 +35,10 @@ class ExampleDIDResolver extends DIDResolver { const resolver = new ExampleDIDResolver(); +const id = 'https://ld.dock.io/examples/resident-card-schema.json'; const residentCardSchema = { $schema: 'http://json-schema.org/draft-07/schema#', - $id: 'https://ld.dock.io/examples/resident-card-schema.json', + $id: id, title: 'Resident Card Example', type: 'object', properties: { @@ -63,8 +65,9 @@ const residentCardSchema = { }; const embeddedSchema = { - id: `data:application/json;charset=utf-8,${encodeURIComponent(JSON.stringify(residentCardSchema))}`, + id, type: 'JsonSchemaValidator2018', + details: stringify({ jsonSchema: residentCardSchema }), }; // Defining schema allows to specify custom encoding diff --git a/package.json b/package.json index cf719d40a..6cc0ce74b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@docknetwork/sdk", - "version": "8.4.0", + "version": "8.5.0", "main": "index.js", "license": "MIT", "repository": { @@ -103,7 +103,7 @@ }, "dependencies": { "@digitalcredentials/vc-status-list": "^8.0.0", - "@docknetwork/crypto-wasm-ts": "0.60.0", + "@docknetwork/crypto-wasm-ts": "0.62.0", "@docknetwork/node-types": "^0.17.0", "@juanelas/base64": "^1.0.5", "@polkadot/api": "10.12.4", @@ -127,6 +127,7 @@ "multiformats": "^9.5.4", "n3": "1.16.2", "pako": "^2.1.0", - "rify": "^0.7.1" + "rify": "^0.7.1", + "semver": "^7.6.0" } } diff --git a/src/presentation.js b/src/presentation.js index 7cd37076a..9b1736ca4 100644 --- a/src/presentation.js +++ b/src/presentation.js @@ -8,6 +8,7 @@ import { } from '@docknetwork/crypto-wasm-ts'; import b58 from 'bs58'; import { stringToU8a } from '@polkadot/util'; +import semver from 'semver/preload'; import { ensureArray } from './utils/type-helpers'; import Bls12381BBSSignatureDock2022 from './utils/vc/crypto/Bls12381BBSSignatureDock2022'; @@ -197,7 +198,7 @@ export default class Presentation { 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), + credentialSchema: semver.gte(credential.version, '0.6.0') ? credential.schema : JSON.parse(credential.schema), issuer: credential.revealedAttributes.issuer || credential.revealedAttributes.proof.verificationMethod.split('#')[0], diff --git a/src/utils/vc/contexts/dock-bbs-v1.json b/src/utils/vc/contexts/dock-bbs-v1.json index ad85f99ca..bc58e2c5b 100644 --- a/src/utils/vc/contexts/dock-bbs-v1.json +++ b/src/utils/vc/contexts/dock-bbs-v1.json @@ -44,6 +44,11 @@ "@type": "@id", "@container": "@graph" }, + "details": { + "@id": "dockBBS:details", + "@type": "@id", + "@container": "@graph" + }, "DockVBAccumulator2022": { "@id": "https://ld.dock.io/security#DockVBAccumulator2022", "@context": { diff --git a/src/utils/vc/contexts/dock-bbs23-v1.json b/src/utils/vc/contexts/dock-bbs23-v1.json index 59a31de39..ce858ed2a 100644 --- a/src/utils/vc/contexts/dock-bbs23-v1.json +++ b/src/utils/vc/contexts/dock-bbs23-v1.json @@ -44,6 +44,11 @@ "@type": "@id", "@container": "@graph" }, + "details": { + "@id": "dockBBS23:details", + "@type": "@id", + "@container": "@graph" + }, "DockVBAccumulator2022": { "@id": "https://ld.dock.io/security#DockVBAccumulator2022", "@context": { diff --git a/src/utils/vc/contexts/dock-bddt16-v1.json b/src/utils/vc/contexts/dock-bddt16-v1.json index 6cb4a9259..1a2d85a09 100644 --- a/src/utils/vc/contexts/dock-bddt16-v1.json +++ b/src/utils/vc/contexts/dock-bddt16-v1.json @@ -44,6 +44,11 @@ "@type": "@id", "@container": "@graph" }, + "details": { + "@id": "dockBDDT16:details", + "@type": "@id", + "@container": "@graph" + }, "DockVBAccumulator2022": { "@id": "https://ld.dock.io/security#DockVBAccumulator2022", "@context": { diff --git a/src/utils/vc/contexts/dock-ps-v1.json b/src/utils/vc/contexts/dock-ps-v1.json index 39c091c31..15eb73999 100644 --- a/src/utils/vc/contexts/dock-ps-v1.json +++ b/src/utils/vc/contexts/dock-ps-v1.json @@ -44,6 +44,11 @@ "@type": "@id", "@container": "@graph" }, + "details": { + "@id": "dockPS:details", + "@type": "@id", + "@container": "@graph" + }, "DockVBAccumulator2022": { "@id": "https://ld.dock.io/security#DockVBAccumulator2022", "@context": { diff --git a/src/utils/vc/credentials.js b/src/utils/vc/credentials.js index 6ac3359cc..2c0ef0ed3 100644 --- a/src/utils/vc/credentials.js +++ b/src/utils/vc/credentials.js @@ -556,9 +556,8 @@ export function getJsonSchemaFromCredential(credential, full = false) { if (typeof credential.credentialSchema.id !== 'string') { throw new Error(`credentialSchema was expected to be string but was ${typeof credential.credentialSchema}`); } - // eslint-disable-next-line no-nested-ternary - const key = full ? (credential.credentialSchema.fullJsonSchema !== undefined ? 'fullJsonSchema' : 'id') : 'id'; - return CredentialSchema.convertFromDataUri(credential.credentialSchema[key]); + const schema = CredentialSchema.fromJSON(credential.credentialSchema); + return full ? schema.getEmbeddedJsonSchema() : schema.jsonSchema; } /** diff --git a/src/utils/vc/crypto/common/DockCryptoSignature.js b/src/utils/vc/crypto/common/DockCryptoSignature.js index 41abca19e..1ef380bbc 100644 --- a/src/utils/vc/crypto/common/DockCryptoSignature.js +++ b/src/utils/vc/crypto/common/DockCryptoSignature.js @@ -5,8 +5,10 @@ import { SECURITY_CONTEXT_URL } from 'jsonld-signatures'; import { u8aToU8a } from '@polkadot/util'; import stringify from 'json-stringify-deterministic'; +import semver from 'semver/preload'; import { withExtendedStaticProperties } from '../../../inheritance'; import CustomLinkedDataSignature from './CustomLinkedDataSignature'; +import { deepClone } from '../../../common'; const SUITE_CONTEXT_URL = 'https://www.w3.org/2018/credentials/v1'; @@ -91,7 +93,7 @@ export default withExtendedStaticProperties( } else { // Legacy. Cannot use `convertCredentialForVerification` because JSON.stringify is not deterministic // and credentialSchema string becomes different. See https://stackoverflow.com/a/43049877 - [serializedCredential, credSchema] = this.constructor.convertCredential(options); + [serializedCredential, credSchema] = this.constructor.convertLegacyCredential(options); } } else { // Serialize the data for signing @@ -113,7 +115,7 @@ export default withExtendedStaticProperties( * @param signingOptions * @returns {Array} - Returns [serialized cred object, cred schema] */ - static convertCredential({ + static convertLegacyCredential({ document, proof: explicitProof /* documentLoader */, signingOptions = { requireAllFieldsFromSchema: false }, @@ -157,7 +159,7 @@ export default withExtendedStaticProperties( credBuilder.setTopLevelField('type', JSON.stringify(document.type)); // Allow for relaxed schema generation, then embed the generated schema directly into the credential - const builtAnoncreds = credBuilder.updateSchemaIfNeeded(signingOptions); + const builtAnoncreds = credBuilder.updateSchemaIfNeededLegacy(signingOptions); // Re-assign the embedded schema to the document schema object // this is a bit hacky, but its the only way right now @@ -217,14 +219,14 @@ export default withExtendedStaticProperties( const s = this.extractSchema(document); let credSchema = s[0]; - const wasLegacySchema = s[1]; + const wasExactSchema = s[1]; const credJson = { ...document, proof: trimmedProof, }; this.formatMandatoryFields(credJson, document); - if (!wasLegacySchema) { + if (!wasExactSchema) { // Older credentials didn't include the version field in the final credential but they did while signing credJson.cryptoVersion = '0.2.0'; if (credJson.credentialSchema === undefined) { @@ -232,9 +234,13 @@ export default withExtendedStaticProperties( } credSchema = CredentialSchema.generateAppropriateSchema(credJson, credSchema); } - const schemaJson = credSchema.toJSON(); - // Older versions used JSON.stringify but newer use deterministic conversion - credJson.credentialSchema = wasLegacySchema ? stringify(schemaJson) : JSON.stringify(schemaJson); + const schemaJson = semver.gte(credSchema.version, '0.4.0') ? credSchema.toJSON() : credSchema.toJSONOlder(); + if (credJson.cryptoVersion && semver.gte(credJson.cryptoVersion, '0.6.0')) { + credJson.credentialSchema = schemaJson; + } else { + // Older versions used JSON.stringify but newer use deterministic conversion + credJson.credentialSchema = wasExactSchema ? stringify(schemaJson) : JSON.stringify(schemaJson); + } if (document.credentialSchema) { Object.assign(document.credentialSchema, schemaJson); @@ -283,10 +289,13 @@ export default withExtendedStaticProperties( // To work with JSON-LD credentials/presentations, we must always reveal the context and type // NOTE: that they are encoded as JSON strings here to reduce message count and so its *always known* + // TODO: `stringify` should be used which is deterministic since @context can be an object credBuilder.setTopLevelField( '@context', - JSON.stringify(document['@context']), + stringify(document['@context']), ); + // TODO: type is never an object? Or use `stringify` to be safe + // Not adding the TODOs here since verification code also uses JSON.stringify and will need to check versions and then use the appropriate call. credBuilder.setTopLevelField('type', JSON.stringify(document.type)); const serializedCred = credBuilder.serializeForSigning(); @@ -295,7 +304,7 @@ export default withExtendedStaticProperties( // Update `document` so that generated credential has `credentialSchema` and `cryptoVersion` set const updatedSchemaJson = credBuilder.schema.toJSON(); - serializedCred.credentialSchema = stringify(updatedSchemaJson); + serializedCred.credentialSchema = updatedSchemaJson; Object.assign(document.credentialSchema, updatedSchemaJson); // eslint-disable-next-line no-param-reassign document.cryptoVersion = serializedCred.cryptoVersion; @@ -370,12 +379,17 @@ export default withExtendedStaticProperties( return schema; } + const schemaJson = deepClone(document.credentialSchema); + // Passing all the default parsing options. Ideally `document.credentialSchema` should contain these + if (schemaJson.details === undefined) { + schemaJson.details = stringify({ parsingOptions: DefaultSchemaParsingOpts }); + } else { + const details = JSON.parse(schemaJson.details); + details.parsingOptions = { ...DefaultSchemaParsingOpts, ...details.parsingOptions }; + schemaJson.details = stringify(details); + } // If we already have a schema to use, add that first and then generate relaxed values later on - credSchema = await CredentialSchema.fromJSONWithPotentiallyExternalSchema({ - // Passing all the default parsing options. Ideally `document.credentialSchema` should contain these - parsingOptions: DefaultSchemaParsingOpts, - ...document.credentialSchema, - }, getSchema); + credSchema = await CredentialSchema.fromJSONWithPotentiallyExternalSchema(schemaJson, getSchema); } else { credSchema = this.extractSchemaWhenIdNotSet(document); wasExactSchema = false; @@ -406,7 +420,7 @@ export default withExtendedStaticProperties( let credSchema; if (document.credentialSchema) { // schema object exists but no ID means the SDK is signalling for the suite to generate a schema - credSchema = new CredentialSchema(CredentialSchema.essential(), document.credentialSchema.parsingOptions); + credSchema = new CredentialSchema(CredentialSchema.essential(), this.getParsingOptions(document)); } else { // Else, no schema was found so just use the essentials and v0.0.1 schema version // NOTE: version is important here and MUST be 0.0.1 otherwise it will invalidate BBS+ credentials @@ -428,6 +442,26 @@ export default withExtendedStaticProperties( return credSchema; } + static getParsingOptions(document) { + if (document.credentialSchema && document.credentialSchema.details !== undefined) { + const details = JSON.parse(document.credentialSchema.details); + return details.parsingOptions; + } + return DefaultSchemaParsingOpts; + } + + static withUpdatedParsingOptions(schemaJson, parsingOptions) { + const newSchemaJson = deepClone(schemaJson); + if (schemaJson.details === undefined) { + newSchemaJson.details = stringify({ parsingOptions }); + } else { + const details = JSON.parse(schemaJson.details); + details.parsingOptions = { ...details.parsingOptions, ...parsingOptions }; + newSchemaJson.details = stringify(details); + } + return newSchemaJson; + } + /** * @param document {object} to be signed. * @param proof {object} diff --git a/src/utils/vc/crypto/common/DockCryptoSignatureProof.js b/src/utils/vc/crypto/common/DockCryptoSignatureProof.js index d27bcd3a0..f14f5b454 100644 --- a/src/utils/vc/crypto/common/DockCryptoSignatureProof.js +++ b/src/utils/vc/crypto/common/DockCryptoSignatureProof.js @@ -1,5 +1,6 @@ import { Presentation } from '@docknetwork/crypto-wasm-ts'; import b58 from 'bs58'; +import semver from 'semver/preload'; import { withExtendedStaticProperties } from '../../../inheritance'; import CustomLinkedDataSignature from './CustomLinkedDataSignature'; @@ -121,12 +122,14 @@ export default withExtendedStaticProperties( delete revealedAttributes.id; } + const credVersion = proof.version; + // TODO: This is wrong. This won't work with presentation from 2 or more credentials const c = { sigType: proof.sigType, - version: proof.version, + version: credVersion, bounds: proof.bounds, - schema: JSON.stringify(credentialSchema), + schema: semver.gte(credVersion, '0.6.0') ? credentialSchema : JSON.stringify(credentialSchema), revealedAttributes: { proof: { type: this.sigName, diff --git a/src/utils/vc/presentations.js b/src/utils/vc/presentations.js index 6820f5ee2..de434c9c4 100644 --- a/src/utils/vc/presentations.js +++ b/src/utils/vc/presentations.js @@ -8,6 +8,7 @@ import { CredentialSchema, } from '@docknetwork/crypto-wasm-ts'; import b58 from 'bs58'; +import semver from 'semver/preload'; import { getPrivateStatus, verifyCredential } from './credentials'; import DIDResolver from "../../resolver/did/did-resolver"; // eslint-disable-line @@ -374,10 +375,8 @@ export function getKeyedProofsFromVerifiedPresentation(presentation) { */ export function getJsonSchemasFromPresentation(presentation, full = false) { return presentation.spec.credentials.map((cred) => { - const schema = CredentialSchema.fromJSON(JSON.parse(cred.schema)); - // eslint-disable-next-line no-nested-ternary - const key = full ? (schema.fullJsonSchema !== undefined ? 'fullJsonSchema' : 'jsonSchema') : 'jsonSchema'; - return schema[key]; + const schema = semver.gte(cred.version, '0.6.0') ? CredentialSchema.fromJSON(cred.schema) : CredentialSchema.fromJSON(JSON.parse(cred.schema)); + return full ? schema.getEmbeddedJsonSchema() : schema.jsonSchema; }); } diff --git a/tests/integration/anoncreds/derived-credentials.test.js b/tests/integration/anoncreds/derived-credentials.test.js index 3382f9639..e05e51346 100644 --- a/tests/integration/anoncreds/derived-credentials.test.js +++ b/tests/integration/anoncreds/derived-credentials.test.js @@ -12,6 +12,7 @@ import { RevocationStatusProtocol, } from '@docknetwork/crypto-wasm-ts'; import { InMemoryState, InMemoryKBUniversalState } from '@docknetwork/crypto-wasm-ts/lib/accumulator/in-memory-persistence'; +import stringify from 'json-stringify-deterministic'; import { DockAPI } from '../../../src'; import { FullNodeEndpoint, @@ -35,9 +36,10 @@ import { getKeyedProofsFromVerifiedPresentation } from '../../../src/utils/vc/pr import { deepClone } from '../../../src/utils/common'; // TODO: move to fixtures +const id = 'https://ld.dock.io/examples/resident-card-schema.json'; const residentCardSchema = { $schema: 'http://json-schema.org/draft-07/schema#', - $id: 'https://ld.dock.io/examples/resident-card-schema.json', + $id: id, title: 'Resident Card Example', type: 'object', properties: { @@ -73,10 +75,9 @@ const residentCardSchema = { }; const embeddedSchema = { - id: `data:application/json;charset=utf-8,${encodeURIComponent( - JSON.stringify(residentCardSchema), - )}`, + id, type: 'JsonSchemaValidator2018', + details: stringify({ jsonSchema: residentCardSchema }), }; describe.each(Schemes)('Derived Credentials', ({ @@ -467,6 +468,7 @@ describe.each(Schemes)('Derived Credentials', ({ }), ); expect(credentials[0].issuer).toEqual(credential.issuer); + expect(credentials[0].credentialSchema.id).toEqual(residentCardSchema.$id); // Ensure reconstructing presentation from credential matches // NOTE: ignoring proof here as itll differ when signed twice as above diff --git a/tests/integration/anoncreds/issuing.test.js b/tests/integration/anoncreds/issuing.test.js index 19c946228..fc2fdfee5 100644 --- a/tests/integration/anoncreds/issuing.test.js +++ b/tests/integration/anoncreds/issuing.test.js @@ -1,8 +1,9 @@ import { randomAsHex } from '@polkadot/util-crypto'; import { u8aToHex } from '@polkadot/util'; import { - DefaultSchemaParsingOpts, CredentialBuilder, CredentialSchema, initializeWasm, + DefaultSchemaParsingOpts, CredentialBuilder, CredentialSchema, initializeWasm, EMPTY_SCHEMA_ID, } from '@docknetwork/crypto-wasm-ts'; +import stringify from 'json-stringify-deterministic'; import { DockAPI } from '../../../src'; import { createNewDockDID, DidKeypair } from '../../../src/utils/did'; import { DockResolver } from '../../../src/resolver'; @@ -22,6 +23,7 @@ import { Schemes, } from '../../test-constants'; import defaultDocumentLoader from '../../../src/utils/vc/document-loader'; +import DockCryptoSignature from '../../../src/utils/vc/crypto/common/DockCryptoSignature'; describe.each(Schemes)('Issuance', ({ Name, @@ -54,15 +56,14 @@ describe.each(Schemes)('Issuance', ({ pair1 = new DidKeypair(dock.keyring.addFromUri(randomAsHex(32)), 1); did1 = createNewDockDID(); await registerNewDIDUsingPair(dock, did1, pair1); - }, 20000); - test(`Can create ${Name} public key for the DID`, async () => { keypair = CryptoKeyPair.generate({ controller: did1, msgCount: 100, }); if (Name !== 'BDDT16') { + // Setup public key on blockchain const pk1 = Module.prepareAddPublicKey(dock.api, u8aToHex(keypair.publicKeyBuffer)); await chainModule.addPublicKey( pk1, @@ -85,7 +86,7 @@ describe.each(Schemes)('Issuance', ({ // But the signer still adds a key identifier in the credential to determine which key will be used for verification keypair.id = 'my-key-id'; } - }, 30000); + }, 20000); test(`Can issue+verify a ${Name} credential with external schema reference`, async () => { const [externalSchemaEncoded, schemaId] = await setupExternalSchema(residentCardSchema, 'Resident Card Example', did1, pair1, dock); @@ -119,17 +120,17 @@ describe.each(Schemes)('Issuance', ({ ); // Ensure extra properties from crypto-wasm-ts are assigned to schema object - expect(credential.credentialSchema).toMatchObject({ - parsingOptions: { - useDefaults: false, - defaultMinimumInteger: -4294967295, - defaultMinimumDate: -17592186044415, - defaultDecimalPlaces: 0, - }, - version: CredentialSchema.VERSION, - }); expect(credential.cryptoVersion).toEqual(CredentialBuilder.VERSION); - expect(credential.credentialSchema.fullJsonSchema).toBeDefined(); + expect(credential.credentialSchema.version).toEqual(CredentialSchema.VERSION); + expect(credential.credentialSchema.id).toEqual(schemaId); + const details = JSON.parse(credential.credentialSchema.details); + expect(details.parsingOptions).toEqual({ + useDefaults: false, + defaultMinimumInteger: -4294967295, + defaultMinimumDate: -17592186044415, + defaultDecimalPlaces: 0, + }); + expect(details.fullJsonSchema).toBeDefined(); const result = await verifyCredential(credential, { resolver }); expect(result).toMatchObject( @@ -169,17 +170,17 @@ describe.each(Schemes)('Issuance', ({ ); // Ensure extra properties from crypto-wasm-ts are assigned to schema object - expect(credential.credentialSchema).toMatchObject({ - parsingOptions: { - useDefaults: false, - defaultMinimumInteger: -4294967295, - defaultMinimumDate: -17592186044415, - defaultDecimalPlaces: 0, - }, - version: CredentialSchema.VERSION, - }); expect(credential.cryptoVersion).toEqual(CredentialBuilder.VERSION); - expect(credential.credentialSchema.fullJsonSchema).not.toBeDefined(); + expect(credential.credentialSchema.version).toEqual(CredentialSchema.VERSION); + expect(credential.credentialSchema.id).toEqual(residentCardSchema.$id); + const details = JSON.parse(credential.credentialSchema.details); + expect(details.parsingOptions).toEqual({ + useDefaults: false, + defaultMinimumInteger: -4294967295, + defaultMinimumDate: -17592186044415, + defaultDecimalPlaces: 0, + }); + expect(details.fullJsonSchema).not.toBeDefined(); const result = await verifyCredential(credential, { resolver }); expect(result).toMatchObject( @@ -207,6 +208,7 @@ describe.each(Schemes)('Issuance', ({ // These won't be defined as the whole schema was autogenerated expect(externalSchema.$id).not.toBeDefined(); expect(fullSchema.$id).not.toBeDefined(); + expect(credential.credentialSchema.id).toEqual(EMPTY_SCHEMA_ID); for (const props of [fullSchema.properties.credentialSubject.properties, externalSchema.properties.credentialSubject.properties]) { // properties don't match exactly because some are generated while signing @@ -223,16 +225,17 @@ describe.each(Schemes)('Issuance', ({ } // Ensure schema was now defined, added by crypto-wasm-ts + expect(credential.cryptoVersion).toEqual(CredentialBuilder.VERSION); expect(credential.credentialSchema).toBeDefined(); - expect(credential.credentialSchema).toMatchObject({ - parsingOptions: { - useDefaults: false, - defaultMinimumInteger: -4294967295, - defaultMinimumDate: -17592186044415, - defaultDecimalPlaces: 0, - }, - version: CredentialSchema.VERSION, + expect(credential.credentialSchema.version).toEqual(CredentialSchema.VERSION); + const details = JSON.parse(credential.credentialSchema.details); + expect(details.parsingOptions).toEqual({ + useDefaults: false, + defaultMinimumInteger: -4294967295, + defaultMinimumDate: -17592186044415, + defaultDecimalPlaces: 0, }); + expect(details.fullJsonSchema).not.toBeDefined(); const result = await verifyCredential(credential, { resolver }); expect(result).toMatchObject( @@ -256,17 +259,18 @@ describe.each(Schemes)('Issuance', ({ unsignedCred.credentialSchema = { id: '', type: 'JsonSchemaValidator2018', - parsingOptions, + details: stringify({ + parsingOptions, + }), }; const credential = await issueCredential(issuerKey, unsignedCred); // Ensure schema was now defined, added by crypto-wasm-ts - expect(credential.credentialSchema).toBeDefined(); - expect(credential.credentialSchema).toMatchObject({ - parsingOptions, - version: CredentialSchema.VERSION, - }); + const details = JSON.parse(credential.credentialSchema.details); + expect(details.parsingOptions).toEqual(parsingOptions); + expect(details.fullJsonSchema).not.toBeDefined(); + expect(credential.credentialSchema.id).toEqual(EMPTY_SCHEMA_ID); const result = await verifyCredential(credential, { resolver }); expect(result).toMatchObject( @@ -282,13 +286,10 @@ describe.each(Schemes)('Issuance', ({ }; const issuerKey = getKeyDoc(did1, keypair, keypair.type, keypair.id); + const schemaWithGivenParsingOptions = DockCryptoSignature.withUpdatedParsingOptions(credentialJSON.credentialSchema, parsingOptions); const unsignedCred = { ...credentialJSON, - credentialSchema: { - id: credentialJSON.credentialSchema.id, - type: 'JsonSchemaValidator2018', - parsingOptions, - }, + credentialSchema: schemaWithGivenParsingOptions, issuer: did1, }; @@ -298,11 +299,10 @@ describe.each(Schemes)('Issuance', ({ const credential = await issueCredential(issuerKey, unsignedCred); // Ensure schema was now defined, added by crypto-wasm-ts - expect(credential.credentialSchema).toBeDefined(); - expect(credential.credentialSchema).toMatchObject({ - parsingOptions, - version: CredentialSchema.VERSION, - }); + const details = JSON.parse(credential.credentialSchema.details); + expect(details.parsingOptions).toEqual(parsingOptions); + expect(details.fullJsonSchema).not.toBeDefined(); + expect(credential.credentialSchema.id).toEqual(residentCardSchema.$id); const result = await verifyCredential(credential, { resolver }); expect(result).toMatchObject( diff --git a/tests/integration/anoncreds/utils.js b/tests/integration/anoncreds/utils.js index 11fc893d5..3cfd4e33a 100644 --- a/tests/integration/anoncreds/utils.js +++ b/tests/integration/anoncreds/utils.js @@ -3,6 +3,7 @@ import * as r1csf from 'r1csfile'; import * as fs from 'fs'; import { randomAsHex } from '@polkadot/util-crypto'; import { stringToHex } from '@polkadot/util'; +import stringify from 'json-stringify-deterministic'; import { blobHexIdToQualified, DockBlobIdByteSize } from '../../../src/modules/blob'; /** @@ -51,9 +52,10 @@ export async function parseR1CSFile(r1csName) { */ export async function setupExternalSchema(fullSchema, title, did, pair, dock) { const blobId = randomAsHex(DockBlobIdByteSize); + const qualifiedBlobId = blobHexIdToQualified(blobId); const schemaExternal = { $schema: 'http://json-schema.org/draft-07/schema#', - $id: blobHexIdToQualified(blobId), + $id: qualifiedBlobId, title, type: 'object', }; @@ -66,17 +68,19 @@ export async function setupExternalSchema(fullSchema, title, did, pair, dock) { await dock.blob.new(blob, did, pair, { didModule: dock.didModule }, false); return [{ - id: `data:application/json;charset=utf-8,${encodeURIComponent( - JSON.stringify(schemaExternal), - )}`, + id: qualifiedBlobId, type: 'JsonSchemaValidator2018', + details: stringify({ + jsonSchema: schemaExternal, + }), }, blobHexIdToQualified(blobId)]; } export function getResidentCardCredentialAndSchema(context) { + const id = 'https://ld.dock.io/examples/resident-card-schema.json'; const residentCardSchema = { $schema: 'http://json-schema.org/draft-07/schema#', - $id: 'https://ld.dock.io/examples/resident-card-schema.json', + $id: id, title: 'Resident Card Example', type: 'object', properties: { @@ -103,10 +107,9 @@ export function getResidentCardCredentialAndSchema(context) { }; const encodedSchema = { - id: `data:application/json;charset=utf-8,${encodeURIComponent( - JSON.stringify(residentCardSchema), - )}`, + id, type: 'JsonSchemaValidator2018', + details: stringify({ jsonSchema: residentCardSchema }), }; const credentialJSON = { diff --git a/yarn.lock b/yarn.lock index c7fa5ed1e..3245d8042 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2878,16 +2878,15 @@ fix-esm "^1.0.1" jsonld digitalcredentials/jsonld.js#v10.x -"@docknetwork/crypto-wasm-ts@0.60.0": - version "0.60.0" - resolved "https://registry.yarnpkg.com/@docknetwork/crypto-wasm-ts/-/crypto-wasm-ts-0.60.0.tgz#094d094003e71a03d030301ccdc7c4bfe18290b7" - integrity sha512-pY/SyfhEAJ42KXVq41JFW/WACThTwSuiOioXmltcgruga3kZ7SpCgGy7Dr06sldTDl58bsYVZwCZuUVGM8lQ0A== +"@docknetwork/crypto-wasm-ts@0.62.0": + version "0.62.0" + resolved "https://registry.yarnpkg.com/@docknetwork/crypto-wasm-ts/-/crypto-wasm-ts-0.62.0.tgz#c0b08039ff49379d5b1d8bcd10dbc4e899acd972" + integrity sha512-wiFOSLtJUHuB/FxBBeP9m9vitN5DZgE6Xkc49lUm65qSrUMsdrf4WHxuY2bnthTHv2ZmrLbD7MoIAwCAlT8Saw== dependencies: "@types/flat" "^5.0.2" "@types/lodash" "^4.14.195" bs58 "5.0.0" crypto-wasm-new "npm:@docknetwork/crypto-wasm@0.30.0" - crypto-wasm-old "npm:@docknetwork/crypto-wasm@0.23.0" flat "^5.0.2" json-pointer "^0.6.2" json-stringify-deterministic "^1.0.11" @@ -6713,13 +6712,6 @@ crypto-ld@^6.0.0: dependencies: buffer "^6.0.3" -"crypto-wasm-old@npm:@docknetwork/crypto-wasm@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@docknetwork/crypto-wasm/-/crypto-wasm-0.23.0.tgz#5ae04db0f7990fb6fc9c7ad3f0a1cb7255518169" - integrity sha512-/bDSy05HkIZIZL9HDHowjCKxTDf9Cf04e1ElIY0o/q9ewbxHQ4/r8Ppv5V5bOnVkxcFG9lWQQstKXQDV86UWRw== - dependencies: - buffer "^6.0.3" - d@1, d@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"