From b182b0aa6dd23506ffcc519383a56c3dbeaeea9c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 4 Nov 2024 17:14:12 +0000 Subject: [PATCH 01/21] Add initial statements and links for conformance. --- tests/suites/conformance.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/suites/conformance.js diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js new file mode 100644 index 00000000..01cf225d --- /dev/null +++ b/tests/suites/conformance.js @@ -0,0 +1,18 @@ +/*! + * Copyright 2024 Digital Bazaar, Inc. + * SPDX-License-Identifier: BSD-3-Clause + */ + +describe('Conformance', function() { + beforeEach(function() { + + }); + it('Specifically, all relevant normative statements in Sections 2. Data ' + + 'Model and 3. Algorithms of this document MUST be enforced.', function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Specifically%2C%20all%20relevant%20normative%20statements%20in%20Sections%202.%20Data%20Model%20and%203.%20Algorithms%20of%20this%20document%20MUST%20be%20enforced.'; + }); + it('Conforming processors MUST produce errors when non-conforming ' + + 'documents are consumed.', function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Conforming%20processors%20MUST%20produce%20errors%20when%20non%2Dconforming%20documents%20are%20consumed.'; + }); +}); From c64dc7fbbc329afe5e337205d60c0ee5f80b24f0 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 5 Nov 2024 09:07:52 -0500 Subject: [PATCH 02/21] Further abstract conformance. --- tests/suites/conformance.js | 46 +++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js index 01cf225d..363dd2bc 100644 --- a/tests/suites/conformance.js +++ b/tests/suites/conformance.js @@ -3,16 +3,38 @@ * SPDX-License-Identifier: BSD-3-Clause */ -describe('Conformance', function() { - beforeEach(function() { - - }); - it('Specifically, all relevant normative statements in Sections 2. Data ' + - 'Model and 3. Algorithms of this document MUST be enforced.', function() { - this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Specifically%2C%20all%20relevant%20normative%20statements%20in%20Sections%202.%20Data%20Model%20and%203.%20Algorithms%20of%20this%20document%20MUST%20be%20enforced.'; +export function assertConformance({ + issuers, + verifiers, + suiteName, + keyType, + vcVersion, + credentials +}) { + describe(`${suiteName} - Conformance - VC ${vcVersion}`, function() { + this.matrix = true; + this.report = true; + this.implemented = [...issuers]; + this.rowLabel = 'Test Name'; + this.columnLabel = 'Implementation'; + for(const [name, {endpoints}] of issuers) { + describe(`${name} ${keyType}`, function() { + beforeEach(function() { + this.currentTest.cell = { + rowId: this.currentTest.title, + columnId: `${name} ${keyType}` + }; + }); + it('Specifically, all relevant normative statements in Sections 2. Data ' + + 'Model and 3. Algorithms of this document MUST be enforced.', function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Specifically%2C%20all%20relevant%20normative%20statements%20in%20Sections%202.%20Data%20Model%20and%203.%20Algorithms%20of%20this%20document%20MUST%20be%20enforced.'; + }); + it('Conforming processors MUST produce errors when non-conforming ' + + 'documents are consumed.', function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Conforming%20processors%20MUST%20produce%20errors%20when%20non%2Dconforming%20documents%20are%20consumed.'; + }); + }); + } }); - it('Conforming processors MUST produce errors when non-conforming ' + - 'documents are consumed.', function() { - this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Conforming%20processors%20MUST%20produce%20errors%20when%20non%2Dconforming%20documents%20are%20consumed.'; - }); -}); +} + From 9455f73fcf2ce9e3c5622250677f5df466814eba Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 5 Nov 2024 18:21:11 +0000 Subject: [PATCH 03/21] Start work on conformance setup function. --- tests/suites/conformance.js | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js index 363dd2bc..1f2b5f93 100644 --- a/tests/suites/conformance.js +++ b/tests/suites/conformance.js @@ -2,39 +2,56 @@ * Copyright 2024 Digital Bazaar, Inc. * SPDX-License-Identifier: BSD-3-Clause */ +import {assertions} from 'data-integrity-test-suite-assertion'; export function assertConformance({ - issuers, verifiers, suiteName, keyType, vcVersion, - credentials + credential, + setup = _setup }) { describe(`${suiteName} - Conformance - VC ${vcVersion}`, function() { this.matrix = true; this.report = true; - this.implemented = [...issuers]; + this.implemented = [...verifiers]; this.rowLabel = 'Test Name'; this.columnLabel = 'Implementation'; - for(const [name, {endpoints}] of issuers) { - describe(`${name} ${keyType}`, function() { + let credentials = new Map(); + before(async function() { + credentials = await setup({credential, suiteName, keyType}); + }); + for(const [name, {endpoints}] of verifiers) { + const [verifier] = endpoints; + describe(`${name}: ${keyType}`, function() { beforeEach(function() { this.currentTest.cell = { rowId: this.currentTest.title, - columnId: `${name} ${keyType}` + columnId: this.currentTest.parent.title }; }); - it('Specifically, all relevant normative statements in Sections 2. Data ' + - 'Model and 3. Algorithms of this document MUST be enforced.', function() { + it('Specifically, all relevant normative statements in Sections 2. ' + + 'Data Model and 3. Algorithms of this document MUST be enforced.', + async function() { this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Specifically%2C%20all%20relevant%20normative%20statements%20in%20Sections%202.%20Data%20Model%20and%203.%20Algorithms%20of%20this%20document%20MUST%20be%20enforced.'; }); it('Conforming processors MUST produce errors when non-conforming ' + - 'documents are consumed.', function() { + 'documents are consumed.', async function() { this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Conforming%20processors%20MUST%20produce%20errors%20when%20non%2Dconforming%20documents%20are%20consumed.'; + await assertions.verificationFail({ + verifier, + credential: {}, + reason: 'Should ' + }); }); }); } }); } +async function _setup({}) { + // not bs58 encoded verificationMethod + // type is not DataIntegrityProof + // invalid cryptosuite name +} From 76c823d4f563fd227b75507326889c8dcd3c896c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 5 Nov 2024 18:49:58 +0000 Subject: [PATCH 04/21] Reuse DI generators for conformance setup. --- tests/suites/conformance.js | 51 +++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js index 1f2b5f93..cc420a2f 100644 --- a/tests/suites/conformance.js +++ b/tests/suites/conformance.js @@ -2,7 +2,12 @@ * Copyright 2024 Digital Bazaar, Inc. * SPDX-License-Identifier: BSD-3-Clause */ -import {assertions} from 'data-integrity-test-suite-assertion'; +import { + assertions, + generators, + issueCloned +} from 'data-integrity-test-suite-assertion'; +import {getMultiKey} from '../vc-generator/key-gen.js'; export function assertConformance({ verifiers, @@ -39,19 +44,45 @@ export function assertConformance({ it('Conforming processors MUST produce errors when non-conforming ' + 'documents are consumed.', async function() { this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Conforming%20processors%20MUST%20produce%20errors%20when%20non%2Dconforming%20documents%20are%20consumed.'; - await assertions.verificationFail({ - verifier, - credential: {}, - reason: 'Should ' - }); + for(const [key, credential] of credentials) { + await assertions.verificationFail({ + verifier, + credential, + reason: `Should not verify VC with ${key}` + }); + } }); }); } }); } -async function _setup({}) { - // not bs58 encoded verificationMethod - // type is not DataIntegrityProof - // invalid cryptosuite name +async function _setup({ + credential, + suiteName, + keyType, + cryptosuite, + mandatoryPointers, + selectivePointers +}) { + const { + invalidProofType, + invalidVm, + invalidCryptosuite + } = generators?.mandatory; + const credentials = new Map(); + const keyPair = await getMultiKey({keyType}); + const signer = keyPair.signer(); + // not bs58 encoded verificationMethod via invalidVm + // type is not DataIntegrityProof invalidType + // invalid cryptosuite name invalidCryptosuite + credentials.set('invalidCryptosuite', await issueCloned(invalidCryptosuite({ + + }))); + credentials.set('invalidVerificationMethod', await issueCloned(invalidVm({ + + }))); + credentials.set('invalidProofType', await issueCloned(invalidProofType({ + }))); + return credentials; } From 95236121676c26a9ce001d338ab68df76dc9a906 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 5 Nov 2024 16:34:32 -0500 Subject: [PATCH 05/21] Add _getSuites & initial generator params. --- tests/suites/conformance.js | 67 +++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js index cc420a2f..84f4655c 100644 --- a/tests/suites/conformance.js +++ b/tests/suites/conformance.js @@ -7,7 +7,9 @@ import { generators, issueCloned } from 'data-integrity-test-suite-assertion'; +import {DataIntegrityProof} from '@digitalbazaar/data-integrity'; import {getMultiKey} from '../vc-generator/key-gen.js'; +import {getSuite} from '../vc-generator/cryptosuites.js'; export function assertConformance({ verifiers, @@ -40,6 +42,13 @@ export function assertConformance({ 'Data Model and 3. Algorithms of this document MUST be enforced.', async function() { this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Specifically%2C%20all%20relevant%20normative%20statements%20in%20Sections%202.%20Data%20Model%20and%203.%20Algorithms%20of%20this%20document%20MUST%20be%20enforced.'; + for(const [key, credential] of credentials) { + await assertions.verificationFail({ + verifier, + credential, + reason: `Should not verify VC with ${key}` + }); + } }); it('Conforming processors MUST produce errors when non-conforming ' + 'documents are consumed.', async function() { @@ -60,7 +69,6 @@ async function _setup({ credential, suiteName, keyType, - cryptosuite, mandatoryPointers, selectivePointers }) { @@ -75,14 +83,59 @@ async function _setup({ // not bs58 encoded verificationMethod via invalidVm // type is not DataIntegrityProof invalidType // invalid cryptosuite name invalidCryptosuite - credentials.set('invalidCryptosuite', await issueCloned(invalidCryptosuite({ - + credentials.set('invalid cryptosuite', await issueCloned(invalidCryptosuite({ + credential: structuredClone(credential), + ..._getSuites({ + signer, + suiteName, + selectivePointers, + mandatoryPointers + }) }))); - credentials.set('invalidVerificationMethod', await issueCloned(invalidVm({ - + credentials.set('invalid VerificationMethod', await issueCloned(invalidVm({ + credential: structuredClone(credential), + ..._getSuites({ + signer, + suiteName, + selectivePointers, + mandatoryPointers + }) }))); - credentials.set('invalidProofType', await issueCloned(invalidProofType({ - + credentials.set('invalid Proof Type', await issueCloned(invalidProofType({ + credential: structuredClone(credential), + ..._getSuites({ + signer, + suiteName, + selectivePointers, + mandatoryPointers + }) }))); return credentials; } + +function _getSuites({ + signer, + suiteName, + mandatoryPointers, + selectivePointers +}) { + const suites = { + suite: new DataIntegrityProof({ + signer, + cryptosuite: getSuite({ + suite: suiteName, + mandatoryPointers + }) + }) + }; + if(selectivePointers) { + suites.selectiveSuite = new DataIntegrityProof({ + signer, + cryptosuite: getSuite({ + suite: suiteName, + selectivePointers + }) + }); + } + return suites; +} From f2f75d105d2cb5ec45ab1b5e38548c58d9202794 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 5 Nov 2024 22:09:52 +0000 Subject: [PATCH 06/21] Add conformance spec file. --- tests/70-conformance.js | 38 +++++++++++++++++++++++++++++++++++++ tests/suites/conformance.js | 12 ++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/70-conformance.js diff --git a/tests/70-conformance.js b/tests/70-conformance.js new file mode 100644 index 00000000..5243eb9c --- /dev/null +++ b/tests/70-conformance.js @@ -0,0 +1,38 @@ +/*! + * Copyright 2024 Digital Bazaar, Inc. + * SPDX-License-Identifier: BSD-3-Clause + */ +import {conformanceSuite} from './suites/conformance.js'; +import {endpoints} from 'vc-test-suite-implementations'; +import {getSuiteConfig} from './test-config.js'; + +const cryptosuites = [ + 'ecdsa-rdfc-2019', + 'ecdsa-sd-2023' +]; + +for(const suiteName of cryptosuites) { + const {tags, credentials, vectors} = getSuiteConfig(suiteName); + const {match: verifiers} = endpoints.filterByTag({ + tags: [...tags], + property: 'verifiers' + }); + for(const vcVersion of vectors.vcTypes) { + const { + document, + mandatoryPointers, + selectivePointers + } = credentials.create[vcVersion]; + for(const keyType of vectors.keyTypes) { + conformanceSuite({ + verifiers, + suiteName, + keyType, + vcVersion, + credential: document, + mandatoryPointers, + selectivePointers + }); + } + } +} diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js index 84f4655c..06781fd7 100644 --- a/tests/suites/conformance.js +++ b/tests/suites/conformance.js @@ -11,12 +11,14 @@ import {DataIntegrityProof} from '@digitalbazaar/data-integrity'; import {getMultiKey} from '../vc-generator/key-gen.js'; import {getSuite} from '../vc-generator/cryptosuites.js'; -export function assertConformance({ +export function conformanceSuite({ verifiers, suiteName, keyType, vcVersion, credential, + mandatoryPointers, + selectivePointers, setup = _setup }) { describe(`${suiteName} - Conformance - VC ${vcVersion}`, function() { @@ -27,7 +29,13 @@ export function assertConformance({ this.columnLabel = 'Implementation'; let credentials = new Map(); before(async function() { - credentials = await setup({credential, suiteName, keyType}); + credentials = await setup({ + credential, + mandatoryPointers, + selectivePointers, + suiteName, + keyType + }); }); for(const [name, {endpoints}] of verifiers) { const [verifier] = endpoints; From 6c5e4e3f4fb6b5c013b4d7942ca39a1cc5f6947c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 6 Nov 2024 14:23:33 +0000 Subject: [PATCH 07/21] Set issuer on VC. --- tests/suites/conformance.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js index 06781fd7..0e996366 100644 --- a/tests/suites/conformance.js +++ b/tests/suites/conformance.js @@ -88,11 +88,13 @@ async function _setup({ const credentials = new Map(); const keyPair = await getMultiKey({keyType}); const signer = keyPair.signer(); + const _credential = structuredClone(credential); + _credential.issuer = keyPair.controller; // not bs58 encoded verificationMethod via invalidVm // type is not DataIntegrityProof invalidType // invalid cryptosuite name invalidCryptosuite credentials.set('invalid cryptosuite', await issueCloned(invalidCryptosuite({ - credential: structuredClone(credential), + credential: structuredClone(_credential), ..._getSuites({ signer, suiteName, @@ -101,7 +103,7 @@ async function _setup({ }) }))); credentials.set('invalid VerificationMethod', await issueCloned(invalidVm({ - credential: structuredClone(credential), + credential: structuredClone(_credential), ..._getSuites({ signer, suiteName, @@ -110,7 +112,7 @@ async function _setup({ }) }))); credentials.set('invalid Proof Type', await issueCloned(invalidProofType({ - credential: structuredClone(credential), + credential: structuredClone(_credential), ..._getSuites({ signer, suiteName, From f7252f1f3df96ac5765babb3ee310277854e935d Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 7 Nov 2024 10:24:07 -0500 Subject: [PATCH 08/21] Conformance suite returns mocha Suite. --- tests/suites/conformance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js index 0e996366..0b4e6585 100644 --- a/tests/suites/conformance.js +++ b/tests/suites/conformance.js @@ -21,7 +21,7 @@ export function conformanceSuite({ selectivePointers, setup = _setup }) { - describe(`${suiteName} - Conformance - VC ${vcVersion}`, function() { + return describe(`${suiteName} - Conformance - VC ${vcVersion}`, function() { this.matrix = true; this.report = true; this.implemented = [...verifiers]; From 0ebad02904278a21b86e8ffea00e87198471209d Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 6 Nov 2024 15:24:30 -0500 Subject: [PATCH 09/21] Add initial data model suite intended for issuers. --- tests/suites/data-model.js | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tests/suites/data-model.js diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js new file mode 100644 index 00000000..9f6f3ad7 --- /dev/null +++ b/tests/suites/data-model.js @@ -0,0 +1,67 @@ +/*! + * Copyright 2024 Digital Bazaar, Inc. + * SPDX-License-Identifier: BSD-3-Clause + */ +import { + assertions, +} from 'data-integrity-test-suite-assertion'; + +export function dataModelSuite({ + issuers, + suiteName, + keyType, + vcVersion, + credential, + mandatoryPointers, + selectivePointers, +}) { + describe(`${suiteName} - Data Model - VC ${vcVersion}`, function() { + this.matrix = true; + this.report = true; + this.implemented = [...issuers]; + this.rowLabel = 'Test Name'; + this.columnLabel = 'Implementation'; + for(const [name, {endpoints}] of issuers) { + const [issuer] = endpoints; + describe(`${name}: ${keyType}`, function() { + let securedCredential = null; + let issuerError = null; + before(async function(){ + + }); + beforeEach(function() { + this.currentTest.cell = { + rowId: this.currentTest.title, + columnId: this.currentTest.parent.title + }; + }); + it('The publicKeyMultibase value of the verification method MUST ' + + 'start with the base-58-btc prefix (z), as defined in the ' + + 'Multibase section of Controller Documents 1.0. A ' + + 'Multibase-encoded Ed25519 256-bit public key value follows, as ' + + 'defined in the Multikey section of Controller Documents 1.0.', + async function() { + this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=in%20this%20specification.-,The%20publicKeyMultibase%20value%20of%20the%20verification%20method%20MUST%20start%20with%20the%20base%2D58%2Dbtc%20prefix,-(z)%2C%20as'; + }); + it('Any other encoding MUST NOT be allowed. (verificationMethod)', + async function() { + this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=of%20Controller%20Documents%201.0.-,Any%20other%20encoding%20MUST%20NOT%20be%20allowed.,-Developers%20are%20advised%20to%20not'; + }); + it('The type property MUST be DataIntegrityProof.', async function() { + this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20type%20property%20MUST%20be%20DataIntegrityProof.'; + }); + it('The cryptosuite property of the proof MUST be eddsa-rdfc-2022 or ' + + 'eddsa-jcs-2022.', async function() { + this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20cryptosuite%20property%20of%20the%20proof%20MUST%20be%20eddsa%2Drdfc%2D2022%20or%20eddsa%2Djcs%2D2022.'; + }); + it('The proofValue property of the proof MUST be a detached EdDSA ' + + 'signature produced according to [RFC8032], encoded using the ' + + 'base-58-btc header and alphabet as described in the Multibase ' + + 'section of Controller Documents 1.0.', async function() { + this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20proofValue%20property%20of%20the%20proof%20MUST%20be%20a%20detached%20EdDSA%20signature%20produced%20according%20to%20%5BRFC8032%5D%2C%20encoded%20using%20the%20base%2D58%2Dbtc%20header%20and%20alphabet%20as%20described%20in%20the%20Multibase%20section%20of%20Controller%20Documents%201.0.'; + + }); + }); + } + }); +} From 40b5bd5772cfb7496ed182c544b37fb19e3584a3 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 6 Nov 2024 16:07:03 -0500 Subject: [PATCH 10/21] Add assertBefore & endpoint check. --- tests/suites/data-model.js | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 9f6f3ad7..3c278997 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -2,9 +2,11 @@ * Copyright 2024 Digital Bazaar, Inc. * SPDX-License-Identifier: BSD-3-Clause */ +import {createInitialVc, endpointCheck} from '../helpers.js'; import { assertions, } from 'data-integrity-test-suite-assertion'; +import {expect} from 'chai'; export function dataModelSuite({ issuers, @@ -12,8 +14,7 @@ export function dataModelSuite({ keyType, vcVersion, credential, - mandatoryPointers, - selectivePointers, + mandatoryPointers }) { describe(`${suiteName} - Data Model - VC ${vcVersion}`, function() { this.matrix = true; @@ -23,11 +24,19 @@ export function dataModelSuite({ this.columnLabel = 'Implementation'; for(const [name, {endpoints}] of issuers) { const [issuer] = endpoints; + // does the endpoint support this test? + if(!endpointCheck({endpoint: issuer, keyType, vcVersion})) { + continue; + } describe(`${name}: ${keyType}`, function() { let securedCredential = null; - let issuerError = null; - before(async function(){ - + before(async function() { + securedCredential = await createInitialVc({ + issuer, + vcVersion, + vc: credential, + mandatoryPointers + }); }); beforeEach(function() { this.currentTest.cell = { @@ -35,6 +44,12 @@ export function dataModelSuite({ columnId: this.currentTest.parent.title }; }); + function assertBefore() { + expect( + securedCredential, + `Expected issuer ${name}: ${keyType} to issue a VC` + ).to.exist; + } it('The publicKeyMultibase value of the verification method MUST ' + 'start with the base-58-btc prefix (z), as defined in the ' + 'Multibase section of Controller Documents 1.0. A ' + @@ -42,23 +57,28 @@ export function dataModelSuite({ 'defined in the Multikey section of Controller Documents 1.0.', async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=in%20this%20specification.-,The%20publicKeyMultibase%20value%20of%20the%20verification%20method%20MUST%20start%20with%20the%20base%2D58%2Dbtc%20prefix,-(z)%2C%20as'; + assertBefore(); }); it('Any other encoding MUST NOT be allowed. (verificationMethod)', async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=of%20Controller%20Documents%201.0.-,Any%20other%20encoding%20MUST%20NOT%20be%20allowed.,-Developers%20are%20advised%20to%20not'; + assertBefore(); }); it('The type property MUST be DataIntegrityProof.', async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20type%20property%20MUST%20be%20DataIntegrityProof.'; + assertBefore(); }); it('The cryptosuite property of the proof MUST be eddsa-rdfc-2022 or ' + 'eddsa-jcs-2022.', async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20cryptosuite%20property%20of%20the%20proof%20MUST%20be%20eddsa%2Drdfc%2D2022%20or%20eddsa%2Djcs%2D2022.'; + assertBefore(); }); it('The proofValue property of the proof MUST be a detached EdDSA ' + 'signature produced according to [RFC8032], encoded using the ' + 'base-58-btc header and alphabet as described in the Multibase ' + 'section of Controller Documents 1.0.', async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20proofValue%20property%20of%20the%20proof%20MUST%20be%20a%20detached%20EdDSA%20signature%20produced%20according%20to%20%5BRFC8032%5D%2C%20encoded%20using%20the%20base%2D58%2Dbtc%20header%20and%20alphabet%20as%20described%20in%20the%20Multibase%20section%20of%20Controller%20Documents%201.0.'; + assertBefore(); }); }); From a277997271d5eab39e96b23d9d0980b7dfc75c55 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 6 Nov 2024 16:59:56 -0500 Subject: [PATCH 11/21] Fill in first VM test & get proofs. --- tests/suites/data-model.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 3c278997..2b3065ce 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -16,7 +16,7 @@ export function dataModelSuite({ credential, mandatoryPointers }) { - describe(`${suiteName} - Data Model - VC ${vcVersion}`, function() { + return describe(`${suiteName} - Data Model - VC ${vcVersion}`, function() { this.matrix = true; this.report = true; this.implemented = [...issuers]; @@ -30,6 +30,7 @@ export function dataModelSuite({ } describe(`${name}: ${keyType}`, function() { let securedCredential = null; + let proofs = []; before(async function() { securedCredential = await createInitialVc({ issuer, @@ -37,6 +38,12 @@ export function dataModelSuite({ vc: credential, mandatoryPointers }); + if(securedCredential) { + proofs = Array.isArray(securedCredential.proofs) ? + securedCredential?.proofs : [securedCredential?.proofs]; + // only test proofs that match the relevant cryptosuite + proofs.filter(p => p.cryptosuite === suiteName); + } }); beforeEach(function() { this.currentTest.cell = { @@ -49,6 +56,10 @@ export function dataModelSuite({ securedCredential, `Expected issuer ${name}: ${keyType} to issue a VC` ).to.exist; + expect( + securedCredential, + 'Expected VC to be an object' + ).to.be.an('object'); } it('The publicKeyMultibase value of the verification method MUST ' + 'start with the base-58-btc prefix (z), as defined in the ' + @@ -58,6 +69,14 @@ export function dataModelSuite({ async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=in%20this%20specification.-,The%20publicKeyMultibase%20value%20of%20the%20verification%20method%20MUST%20start%20with%20the%20base%2D58%2Dbtc%20prefix,-(z)%2C%20as'; assertBefore(); + for(const proof of proofs) { + expect(proof.verificationMethod).to.exist; + expect(proof.verificationMethod).to.be.a('string'); + expect( + assertions.shouldBeBs58(proof.verificationMethod), + 'Expected "proof.verificationMethod" to be Base58 encoded' + ).to.be.true; + } }); it('Any other encoding MUST NOT be allowed. (verificationMethod)', async function() { From d99022592395b0a393322012fe346eb8cd020783 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 6 Nov 2024 17:05:03 -0500 Subject: [PATCH 12/21] Add further assertions on proofs to data model suite. --- tests/suites/data-model.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 2b3065ce..4c8be234 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -82,15 +82,34 @@ export function dataModelSuite({ async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=of%20Controller%20Documents%201.0.-,Any%20other%20encoding%20MUST%20NOT%20be%20allowed.,-Developers%20are%20advised%20to%20not'; assertBefore(); + for(const proof of proofs) { + expect(proof.verificationMethod).to.exist; + expect(proof.verificationMethod).to.be.a('string'); + expect( + assertions.shouldBeBs58(proof.verificationMethod), + 'Expected "proof.verificationMethod" to be Base58 encoded' + ).to.be.true; + } }); it('The type property MUST be DataIntegrityProof.', async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20type%20property%20MUST%20be%20DataIntegrityProof.'; assertBefore(); + for(const proof of proofs) { + expect(proof.type).to.exist; + expect(proof.type).to.be.a('string'); + expect(proof.type).to.equal('DataIntegrityProof'); + } }); it('The cryptosuite property of the proof MUST be eddsa-rdfc-2022 or ' + 'eddsa-jcs-2022.', async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20cryptosuite%20property%20of%20the%20proof%20MUST%20be%20eddsa%2Drdfc%2D2022%20or%20eddsa%2Djcs%2D2022.'; assertBefore(); + for(const proof of proofs) { + expect(proof.cryptosuite).to.exist; + expect(proof.cryptosuite).to.be.a('string'); + expect(proof.cryptosuite).to.oneOf( + ['eddsa-rdfc-2022', 'eddsa-jcs-2022']); + } }); it('The proofValue property of the proof MUST be a detached EdDSA ' + 'signature produced according to [RFC8032], encoded using the ' + @@ -98,7 +117,14 @@ export function dataModelSuite({ 'section of Controller Documents 1.0.', async function() { this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20proofValue%20property%20of%20the%20proof%20MUST%20be%20a%20detached%20EdDSA%20signature%20produced%20according%20to%20%5BRFC8032%5D%2C%20encoded%20using%20the%20base%2D58%2Dbtc%20header%20and%20alphabet%20as%20described%20in%20the%20Multibase%20section%20of%20Controller%20Documents%201.0.'; assertBefore(); - + for(const proof of proofs) { + expect(proof.proofValue).to.exist; + expect(proof.proofValue).to.be.a('string'); + expect( + assertions.shouldBeBs58(proof.proofValue), + 'Expected "proof.proofValue" to be Base58 encoded' + ).to.be.true; + } }); }); } From a308742fed1e0c5d7769ce830e6e786a879fc868 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 7 Nov 2024 10:22:51 -0500 Subject: [PATCH 13/21] Add initial data-model test. --- tests/80-data-model.js | 38 ++++++++++++++++++++++++++++++++++++++ tests/suites/data-model.js | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/80-data-model.js diff --git a/tests/80-data-model.js b/tests/80-data-model.js new file mode 100644 index 00000000..d2ed151f --- /dev/null +++ b/tests/80-data-model.js @@ -0,0 +1,38 @@ +/*! + * Copyright 2024 Digital Bazaar, Inc. + * SPDX-License-Identifier: BSD-3-Clause + */ +import {dataModelSuite} from './suites/data-model.js'; +import {endpoints} from 'vc-test-suite-implementations'; +import {getSuiteConfig} from './test-config.js'; + +const cryptosuites = [ + 'ecdsa-rdfc-2019', + 'ecdsa-jcs-2019' +]; + +for(const suiteName of cryptosuites) { + const {tags, credentials, vectors} = getSuiteConfig(suiteName); + const {match: issuers} = endpoints.filterByTag({ + tags: [...tags], + property: 'issuers' + }); + for(const vcVersion of vectors.vcTypes) { + const { + document, + mandatoryPointers, + selectivePointers + } = credentials.create[vcVersion]; + for(const keyType of vectors.keyTypes) { + dataModelSuite({ + issuers, + suiteName, + keyType, + vcVersion, + credential: document, + mandatoryPointers, + selectivePointers + }); + } + } +} diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 4c8be234..97f1d962 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -107,7 +107,7 @@ export function dataModelSuite({ for(const proof of proofs) { expect(proof.cryptosuite).to.exist; expect(proof.cryptosuite).to.be.a('string'); - expect(proof.cryptosuite).to.oneOf( + expect(proof.cryptosuite).to.be.oneOf( ['eddsa-rdfc-2022', 'eddsa-jcs-2022']); } }); From c89ef2a993cd29e8a47fd2aed3c6269ff7356e7a Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 7 Nov 2024 10:33:25 -0500 Subject: [PATCH 14/21] Remove proofValue test from data model & update links. --- tests/suites/data-model.js | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 97f1d962..c7823836 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -63,11 +63,9 @@ export function dataModelSuite({ } it('The publicKeyMultibase value of the verification method MUST ' + 'start with the base-58-btc prefix (z), as defined in the ' + - 'Multibase section of Controller Documents 1.0. A ' + - 'Multibase-encoded Ed25519 256-bit public key value follows, as ' + - 'defined in the Multikey section of Controller Documents 1.0.', + 'Multibase section of Controller Documents 1.0. A ', async function() { - this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=in%20this%20specification.-,The%20publicKeyMultibase%20value%20of%20the%20verification%20method%20MUST%20start%20with%20the%20base%2D58%2Dbtc%20prefix,-(z)%2C%20as'; + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#data-model:~:text=The%20publicKeyMultibase%20value%20of%20the%20verification%20method%20MUST%20start%20with%20the%20base%2D58%2Dbtc%20prefix%20(z)%2C%20as%20defined%20in%20the%20Multibase%20section%20of%20Controller%20Documents%201.0.'; assertBefore(); for(const proof of proofs) { expect(proof.verificationMethod).to.exist; @@ -80,7 +78,7 @@ export function dataModelSuite({ }); it('Any other encoding MUST NOT be allowed. (verificationMethod)', async function() { - this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=of%20Controller%20Documents%201.0.-,Any%20other%20encoding%20MUST%20NOT%20be%20allowed.,-Developers%20are%20advised%20to%20not'; + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey'; assertBefore(); for(const proof of proofs) { expect(proof.verificationMethod).to.exist; @@ -92,7 +90,7 @@ export function dataModelSuite({ } }); it('The type property MUST be DataIntegrityProof.', async function() { - this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20type%20property%20MUST%20be%20DataIntegrityProof.'; + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey:~:text=The%20type%20property%20MUST%20be%20DataIntegrityProof.'; assertBefore(); for(const proof of proofs) { expect(proof.type).to.exist; @@ -100,30 +98,15 @@ export function dataModelSuite({ expect(proof.type).to.equal('DataIntegrityProof'); } }); - it('The cryptosuite property of the proof MUST be eddsa-rdfc-2022 or ' + - 'eddsa-jcs-2022.', async function() { - this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20cryptosuite%20property%20of%20the%20proof%20MUST%20be%20eddsa%2Drdfc%2D2022%20or%20eddsa%2Djcs%2D2022.'; + it('The cryptosuite property MUST be ecdsa-rdfc-2019, ' + + 'ecdsa-jcs-2019, or ecdsa-sd-2023.', async function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey:~:text=The%20cryptosuite%20property%20MUST%20be%20ecdsa%2Drdfc%2D2019%2C%20ecdsa%2Djcs%2D2019%2C%20or%20ecdsa%2Dsd%2D2023.'; assertBefore(); for(const proof of proofs) { expect(proof.cryptosuite).to.exist; expect(proof.cryptosuite).to.be.a('string'); expect(proof.cryptosuite).to.be.oneOf( - ['eddsa-rdfc-2022', 'eddsa-jcs-2022']); - } - }); - it('The proofValue property of the proof MUST be a detached EdDSA ' + - 'signature produced according to [RFC8032], encoded using the ' + - 'base-58-btc header and alphabet as described in the Multibase ' + - 'section of Controller Documents 1.0.', async function() { - this.test.link = 'https://w3c.github.io/vc-di-eddsa/#data-model:~:text=The%20proofValue%20property%20of%20the%20proof%20MUST%20be%20a%20detached%20EdDSA%20signature%20produced%20according%20to%20%5BRFC8032%5D%2C%20encoded%20using%20the%20base%2D58%2Dbtc%20header%20and%20alphabet%20as%20described%20in%20the%20Multibase%20section%20of%20Controller%20Documents%201.0.'; - assertBefore(); - for(const proof of proofs) { - expect(proof.proofValue).to.exist; - expect(proof.proofValue).to.be.a('string'); - expect( - assertions.shouldBeBs58(proof.proofValue), - 'Expected "proof.proofValue" to be Base58 encoded' - ).to.be.true; + ['ecdsa-rdfc-2019', 'edcsa-jcs-2019', 'ecdsa-sd-2023']); } }); }); From f4f6507d4331acb680d4b5612b630f013e604bcf Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 7 Nov 2024 10:38:03 -0500 Subject: [PATCH 15/21] Comment out jcs & correct naming in before statement. --- tests/80-data-model.js | 3 ++- tests/suites/data-model.js | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/80-data-model.js b/tests/80-data-model.js index d2ed151f..15419520 100644 --- a/tests/80-data-model.js +++ b/tests/80-data-model.js @@ -8,7 +8,8 @@ import {getSuiteConfig} from './test-config.js'; const cryptosuites = [ 'ecdsa-rdfc-2019', - 'ecdsa-jcs-2019' + 'ecdsa-sd-2023' + //FIXME implement jcs 'ecdsa-jcs-2019' ]; for(const suiteName of cryptosuites) { diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index c7823836..90e5d0c2 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -39,10 +39,10 @@ export function dataModelSuite({ mandatoryPointers }); if(securedCredential) { - proofs = Array.isArray(securedCredential.proofs) ? - securedCredential?.proofs : [securedCredential?.proofs]; + proofs = Array.isArray(securedCredential.proof) ? + securedCredential?.proof : [securedCredential?.proof]; // only test proofs that match the relevant cryptosuite - proofs.filter(p => p.cryptosuite === suiteName); + proofs = proofs.filter(p => p?.cryptosuite === suiteName); } }); beforeEach(function() { From 93173effc6ecbc13a2346318aef4ede3a43458ff Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 7 Nov 2024 10:45:41 -0500 Subject: [PATCH 16/21] Use didResolver to assert on publicKeyMultibase. --- tests/suites/data-model.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 90e5d0c2..5a8bf7f4 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -6,6 +6,7 @@ import {createInitialVc, endpointCheck} from '../helpers.js'; import { assertions, } from 'data-integrity-test-suite-assertion'; +import {didResolver} from '../didResolver.js'; import {expect} from 'chai'; export function dataModelSuite({ @@ -70,9 +71,12 @@ export function dataModelSuite({ for(const proof of proofs) { expect(proof.verificationMethod).to.exist; expect(proof.verificationMethod).to.be.a('string'); + const didDoc = await didResolver({url: proof.verificationMethod}); + expect(didDoc).to.be.an('object'); + expect(didDoc.publicKeyMultibase).to.be.a('string'); expect( - assertions.shouldBeBs58(proof.verificationMethod), - 'Expected "proof.verificationMethod" to be Base58 encoded' + assertions.shouldBeBs58(didDoc.publicKeyMultibase), + 'Expected "publicKeyMultibase" to be Base58 encoded' ).to.be.true; } }); @@ -83,9 +87,12 @@ export function dataModelSuite({ for(const proof of proofs) { expect(proof.verificationMethod).to.exist; expect(proof.verificationMethod).to.be.a('string'); + const didDoc = await didResolver({url: proof.verificationMethod}); + expect(didDoc).to.be.an('object'); + expect(didDoc.publicKeyMultibase).to.be.a('string'); expect( - assertions.shouldBeBs58(proof.verificationMethod), - 'Expected "proof.verificationMethod" to be Base58 encoded' + assertions.shouldBeBs58(didDoc.publicKeyMultibase), + 'Expected "publicKeyMultibase" to be Base58 encoded' ).to.be.true; } }); From 4100168561fa5d0db1f9331fabece4629ded9e00 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 11 Nov 2024 16:20:05 +0000 Subject: [PATCH 17/21] Update tests/suites/data-model.js add period to end of sentence. Co-authored-by: Ted Thibodeau Jr --- tests/suites/data-model.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 5a8bf7f4..4d338bba 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -55,11 +55,11 @@ export function dataModelSuite({ function assertBefore() { expect( securedCredential, - `Expected issuer ${name}: ${keyType} to issue a VC` + `Expected issuer ${name}: ${keyType} to issue a VC.` ).to.exist; expect( securedCredential, - 'Expected VC to be an object' + 'Expected VC to be an object.' ).to.be.an('object'); } it('The publicKeyMultibase value of the verification method MUST ' + From 5cef3a40fa72e1aa45f430fbc18edc1387b33c51 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 11 Nov 2024 16:21:55 +0000 Subject: [PATCH 18/21] Update tests/suites/data-model.js add period to bs58 reason. Co-authored-by: Ted Thibodeau Jr --- tests/suites/data-model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 4d338bba..ba17f16e 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -76,7 +76,7 @@ export function dataModelSuite({ expect(didDoc.publicKeyMultibase).to.be.a('string'); expect( assertions.shouldBeBs58(didDoc.publicKeyMultibase), - 'Expected "publicKeyMultibase" to be Base58 encoded' + 'Expected "publicKeyMultibase" to be Base58 encoded.' ).to.be.true; } }); From 8eb774811acb1a0a3a215ed46b083fbfe025a51e Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 11 Nov 2024 16:22:17 +0000 Subject: [PATCH 19/21] Update tests/suites/data-model.js add missing period to end of bs58 reason. Co-authored-by: Ted Thibodeau Jr --- tests/suites/data-model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index ba17f16e..18a79dc8 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -92,7 +92,7 @@ export function dataModelSuite({ expect(didDoc.publicKeyMultibase).to.be.a('string'); expect( assertions.shouldBeBs58(didDoc.publicKeyMultibase), - 'Expected "publicKeyMultibase" to be Base58 encoded' + 'Expected "publicKeyMultibase" to be Base58 encoded.' ).to.be.true; } }); From dc39f440404b5c4bd82288e1f932d20402511f6e Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 11 Nov 2024 16:25:34 +0000 Subject: [PATCH 20/21] Update tests/suites/data-model.js Remove trailing A from end of sentence. --- tests/suites/data-model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index 18a79dc8..f1403020 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -64,7 +64,7 @@ export function dataModelSuite({ } it('The publicKeyMultibase value of the verification method MUST ' + 'start with the base-58-btc prefix (z), as defined in the ' + - 'Multibase section of Controller Documents 1.0. A ', + 'Multibase section of Controller Documents 1.0. ', async function() { this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#data-model:~:text=The%20publicKeyMultibase%20value%20of%20the%20verification%20method%20MUST%20start%20with%20the%20base%2D58%2Dbtc%20prefix%20(z)%2C%20as%20defined%20in%20the%20Multibase%20section%20of%20Controller%20Documents%201.0.'; assertBefore(); From 0da76254df51fd805112ccdc77e2cafb452a3c32 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 11 Nov 2024 17:40:08 +0000 Subject: [PATCH 21/21] Handle implemented & multi-key-types. --- tests/70-conformance.js | 20 ++-- tests/80-data-model.js | 20 ++-- tests/suites/conformance.js | 86 ++++++++-------- tests/suites/data-model.js | 190 +++++++++++++++++++----------------- 4 files changed, 163 insertions(+), 153 deletions(-) diff --git a/tests/70-conformance.js b/tests/70-conformance.js index 5243eb9c..90b33243 100644 --- a/tests/70-conformance.js +++ b/tests/70-conformance.js @@ -23,16 +23,14 @@ for(const suiteName of cryptosuites) { mandatoryPointers, selectivePointers } = credentials.create[vcVersion]; - for(const keyType of vectors.keyTypes) { - conformanceSuite({ - verifiers, - suiteName, - keyType, - vcVersion, - credential: document, - mandatoryPointers, - selectivePointers - }); - } + conformanceSuite({ + verifiers, + suiteName, + keyTypes: vectors.keyTypes, + vcVersion, + credential: document, + mandatoryPointers, + selectivePointers + }); } } diff --git a/tests/80-data-model.js b/tests/80-data-model.js index 15419520..e67f2e05 100644 --- a/tests/80-data-model.js +++ b/tests/80-data-model.js @@ -24,16 +24,14 @@ for(const suiteName of cryptosuites) { mandatoryPointers, selectivePointers } = credentials.create[vcVersion]; - for(const keyType of vectors.keyTypes) { - dataModelSuite({ - issuers, - suiteName, - keyType, - vcVersion, - credential: document, - mandatoryPointers, - selectivePointers - }); - } + dataModelSuite({ + issuers, + suiteName, + keyTypes: vectors.keyTypes, + vcVersion, + credential: document, + mandatoryPointers, + selectivePointers + }); } } diff --git a/tests/suites/conformance.js b/tests/suites/conformance.js index 0b4e6585..8df7bce0 100644 --- a/tests/suites/conformance.js +++ b/tests/suites/conformance.js @@ -14,7 +14,7 @@ import {getSuite} from '../vc-generator/cryptosuites.js'; export function conformanceSuite({ verifiers, suiteName, - keyType, + keyTypes, vcVersion, credential, mandatoryPointers, @@ -24,52 +24,58 @@ export function conformanceSuite({ return describe(`${suiteName} - Conformance - VC ${vcVersion}`, function() { this.matrix = true; this.report = true; - this.implemented = [...verifiers]; + this.implemented = []; this.rowLabel = 'Test Name'; this.columnLabel = 'Implementation'; - let credentials = new Map(); + const credentials = new Map(keyTypes.map(kt => [kt, null])); before(async function() { - credentials = await setup({ - credential, - mandatoryPointers, - selectivePointers, - suiteName, - keyType - }); + for(const keyType of keyTypes) { + credentials.set(keyType, await setup({ + credential, + mandatoryPointers, + selectivePointers, + suiteName, + keyType + })); + } }); for(const [name, {endpoints}] of verifiers) { const [verifier] = endpoints; - describe(`${name}: ${keyType}`, function() { - beforeEach(function() { - this.currentTest.cell = { - rowId: this.currentTest.title, - columnId: this.currentTest.parent.title - }; - }); - it('Specifically, all relevant normative statements in Sections 2. ' + - 'Data Model and 3. Algorithms of this document MUST be enforced.', - async function() { - this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Specifically%2C%20all%20relevant%20normative%20statements%20in%20Sections%202.%20Data%20Model%20and%203.%20Algorithms%20of%20this%20document%20MUST%20be%20enforced.'; - for(const [key, credential] of credentials) { - await assertions.verificationFail({ - verifier, - credential, - reason: `Should not verify VC with ${key}` - }); - } - }); - it('Conforming processors MUST produce errors when non-conforming ' + - 'documents are consumed.', async function() { - this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Conforming%20processors%20MUST%20produce%20errors%20when%20non%2Dconforming%20documents%20are%20consumed.'; - for(const [key, credential] of credentials) { - await assertions.verificationFail({ - verifier, - credential, - reason: `Should not verify VC with ${key}` - }); - } + for(const keyType of keyTypes) { + // add implementer name and keyType to test report + this.implemented.push(`${name}: ${keyType}`); + describe(`${name}: ${keyType}`, function() { + beforeEach(function() { + this.currentTest.cell = { + rowId: this.currentTest.title, + columnId: this.currentTest.parent.title + }; + }); + it('Specifically, all relevant normative statements in Sections 2. ' + + 'Data Model and 3. Algorithms of this document MUST be enforced.', + async function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Specifically%2C%20all%20relevant%20normative%20statements%20in%20Sections%202.%20Data%20Model%20and%203.%20Algorithms%20of%20this%20document%20MUST%20be%20enforced.'; + for(const [key, credential] of credentials.get(keyType)) { + await assertions.verificationFail({ + verifier, + credential, + reason: `Should not verify VC with ${key}` + }); + } + }); + it('Conforming processors MUST produce errors when non-conforming ' + + 'documents are consumed.', async function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#:~:text=Conforming%20processors%20MUST%20produce%20errors%20when%20non%2Dconforming%20documents%20are%20consumed.'; + for(const [key, credential] of credentials.get(keyType)) { + await assertions.verificationFail({ + verifier, + credential, + reason: `Should not verify VC with ${key}` + }); + } + }); }); - }); + } } }); } diff --git a/tests/suites/data-model.js b/tests/suites/data-model.js index f1403020..a8f486c1 100644 --- a/tests/suites/data-model.js +++ b/tests/suites/data-model.js @@ -12,7 +12,7 @@ import {expect} from 'chai'; export function dataModelSuite({ issuers, suiteName, - keyType, + keyTypes, vcVersion, credential, mandatoryPointers @@ -20,103 +20,111 @@ export function dataModelSuite({ return describe(`${suiteName} - Data Model - VC ${vcVersion}`, function() { this.matrix = true; this.report = true; - this.implemented = [...issuers]; + this.implemented = []; this.rowLabel = 'Test Name'; this.columnLabel = 'Implementation'; for(const [name, {endpoints}] of issuers) { - const [issuer] = endpoints; - // does the endpoint support this test? - if(!endpointCheck({endpoint: issuer, keyType, vcVersion})) { - continue; - } - describe(`${name}: ${keyType}`, function() { - let securedCredential = null; - let proofs = []; - before(async function() { - securedCredential = await createInitialVc({ - issuer, - vcVersion, - vc: credential, - mandatoryPointers - }); - if(securedCredential) { - proofs = Array.isArray(securedCredential.proof) ? - securedCredential?.proof : [securedCredential?.proof]; - // only test proofs that match the relevant cryptosuite - proofs = proofs.filter(p => p?.cryptosuite === suiteName); + for(const keyType of keyTypes) { + for(const issuer of endpoints) { + // does the endpoint support this test? + if(!endpointCheck({endpoint: issuer, keyType, vcVersion})) { + continue; } - }); - beforeEach(function() { - this.currentTest.cell = { - rowId: this.currentTest.title, - columnId: this.currentTest.parent.title - }; - }); - function assertBefore() { - expect( - securedCredential, - `Expected issuer ${name}: ${keyType} to issue a VC.` - ).to.exist; - expect( - securedCredential, - 'Expected VC to be an object.' - ).to.be.an('object'); - } - it('The publicKeyMultibase value of the verification method MUST ' + - 'start with the base-58-btc prefix (z), as defined in the ' + - 'Multibase section of Controller Documents 1.0. ', - async function() { - this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#data-model:~:text=The%20publicKeyMultibase%20value%20of%20the%20verification%20method%20MUST%20start%20with%20the%20base%2D58%2Dbtc%20prefix%20(z)%2C%20as%20defined%20in%20the%20Multibase%20section%20of%20Controller%20Documents%201.0.'; - assertBefore(); - for(const proof of proofs) { - expect(proof.verificationMethod).to.exist; - expect(proof.verificationMethod).to.be.a('string'); - const didDoc = await didResolver({url: proof.verificationMethod}); - expect(didDoc).to.be.an('object'); - expect(didDoc.publicKeyMultibase).to.be.a('string'); - expect( - assertions.shouldBeBs58(didDoc.publicKeyMultibase), - 'Expected "publicKeyMultibase" to be Base58 encoded.' - ).to.be.true; - } - }); - it('Any other encoding MUST NOT be allowed. (verificationMethod)', - async function() { - this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey'; - assertBefore(); - for(const proof of proofs) { - expect(proof.verificationMethod).to.exist; - expect(proof.verificationMethod).to.be.a('string'); - const didDoc = await didResolver({url: proof.verificationMethod}); - expect(didDoc).to.be.an('object'); - expect(didDoc.publicKeyMultibase).to.be.a('string'); + // add implementer name and keyType to test report + this.implemented.push(`${name}: ${keyType}`); + describe(`${name}: ${keyType}`, function() { + let securedCredential = null; + let proofs = []; + before(async function() { + securedCredential = await createInitialVc({ + issuer, + vcVersion, + vc: credential, + mandatoryPointers + }); + if(securedCredential) { + proofs = Array.isArray(securedCredential.proof) ? + securedCredential?.proof : [securedCredential?.proof]; + // only test proofs that match the relevant cryptosuite + proofs = proofs.filter(p => p?.cryptosuite === suiteName); + } + }); + beforeEach(function() { + this.currentTest.cell = { + rowId: this.currentTest.title, + columnId: this.currentTest.parent.title + }; + }); + function assertBefore() { + expect( + securedCredential, + `Expected issuer ${name}: ${keyType} to issue a VC.` + ).to.exist; expect( - assertions.shouldBeBs58(didDoc.publicKeyMultibase), - 'Expected "publicKeyMultibase" to be Base58 encoded.' - ).to.be.true; + securedCredential, + 'Expected VC to be an object.' + ).to.be.an('object'); } + it('The publicKeyMultibase value of the verification method MUST ' + + 'start with the base-58-btc prefix (z), as defined in the ' + + 'Multibase section of Controller Documents 1.0. ', + async function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#data-model:~:text=The%20publicKeyMultibase%20value%20of%20the%20verification%20method%20MUST%20start%20with%20the%20base%2D58%2Dbtc%20prefix%20(z)%2C%20as%20defined%20in%20the%20Multibase%20section%20of%20Controller%20Documents%201.0.'; + assertBefore(); + for(const proof of proofs) { + expect(proof.verificationMethod).to.exist; + expect(proof.verificationMethod).to.be.a('string'); + const didDoc = await didResolver({ + url: proof.verificationMethod}); + expect(didDoc).to.be.an('object'); + expect(didDoc.publicKeyMultibase).to.be.a('string'); + expect( + assertions.shouldBeBs58(didDoc.publicKeyMultibase), + 'Expected "publicKeyMultibase" to be Base58 encoded.' + ).to.be.true; + } + }); + it('Any other encoding MUST NOT be allowed. (verificationMethod)', + async function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey'; + assertBefore(); + for(const proof of proofs) { + expect(proof.verificationMethod).to.exist; + expect(proof.verificationMethod).to.be.a('string'); + const didDoc = await didResolver({ + url: proof.verificationMethod}); + expect(didDoc).to.be.an('object'); + expect(didDoc.publicKeyMultibase).to.be.a('string'); + expect( + assertions.shouldBeBs58(didDoc.publicKeyMultibase), + 'Expected "publicKeyMultibase" to be Base58 encoded.' + ).to.be.true; + } + }); + it('The type property MUST be DataIntegrityProof.', + async function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey:~:text=The%20type%20property%20MUST%20be%20DataIntegrityProof.'; + assertBefore(); + for(const proof of proofs) { + expect(proof.type).to.exist; + expect(proof.type).to.be.a('string'); + expect(proof.type).to.equal('DataIntegrityProof'); + } + }); + it('The cryptosuite property MUST be ecdsa-rdfc-2019, ' + + 'ecdsa-jcs-2019, or ecdsa-sd-2023.', async function() { + this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey:~:text=The%20cryptosuite%20property%20MUST%20be%20ecdsa%2Drdfc%2D2019%2C%20ecdsa%2Djcs%2D2019%2C%20or%20ecdsa%2Dsd%2D2023.'; + assertBefore(); + for(const proof of proofs) { + expect(proof.cryptosuite).to.exist; + expect(proof.cryptosuite).to.be.a('string'); + expect(proof.cryptosuite).to.be.oneOf( + ['ecdsa-rdfc-2019', 'edcsa-jcs-2019', 'ecdsa-sd-2023']); + } + }); }); - it('The type property MUST be DataIntegrityProof.', async function() { - this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey:~:text=The%20type%20property%20MUST%20be%20DataIntegrityProof.'; - assertBefore(); - for(const proof of proofs) { - expect(proof.type).to.exist; - expect(proof.type).to.be.a('string'); - expect(proof.type).to.equal('DataIntegrityProof'); - } - }); - it('The cryptosuite property MUST be ecdsa-rdfc-2019, ' + - 'ecdsa-jcs-2019, or ecdsa-sd-2023.', async function() { - this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#multikey:~:text=The%20cryptosuite%20property%20MUST%20be%20ecdsa%2Drdfc%2D2019%2C%20ecdsa%2Djcs%2D2019%2C%20or%20ecdsa%2Dsd%2D2023.'; - assertBefore(); - for(const proof of proofs) { - expect(proof.cryptosuite).to.exist; - expect(proof.cryptosuite).to.be.a('string'); - expect(proof.cryptosuite).to.be.oneOf( - ['ecdsa-rdfc-2019', 'edcsa-jcs-2019', 'ecdsa-sd-2023']); - } - }); - }); + } + } } }); }