From f4cacbf7b1e5b35e86196d12b7ef941a288739d4 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Sun, 17 Nov 2024 17:06:46 -0500 Subject: [PATCH 1/5] Add parseDisclosureProofValue & Use DeriveStub. --- tests/suites/proxies.js | 15 +++++++- tests/suites/stubs.js | 85 +++++++++++++++++++++++++++++++++++------ 2 files changed, 86 insertions(+), 14 deletions(-) diff --git a/tests/suites/proxies.js b/tests/suites/proxies.js index 81b97723..fad69bc4 100644 --- a/tests/suites/proxies.js +++ b/tests/suites/proxies.js @@ -2,8 +2,9 @@ * Copyright 2024 Digital Bazaar, Inc. * SPDX-License-Identifier: BSD-3-Clause */ +import {Token, Type} from 'cborg'; import crypto from 'node:crypto'; -import {stubDerive} from './stubs.js'; +import {DeriveStub} from './stubs.js'; /** * Creates a proxy of an object with stubs. * @@ -154,7 +155,17 @@ async function _canonizeProof(proof, { } export function invalidCborTagProxy(suite) { - const stubs = {derive: stubDerive}; + const typeEncoders = { + Uint8Array(uint8Array) { + return [ + new Token(Type.tag, 2), + new Token(Type.bytes, uint8Array.map(b => b + 1)) + ]; + } + }; + const stubs = {derive({...args}) { + return new DeriveStub({typeEncoders}).derive({...args}); + }}; if(suite._cryptosuite) { suite._cryptosuite = createProxy({ original: suite._cryptosuite, diff --git a/tests/suites/stubs.js b/tests/suites/stubs.js index 63b95458..c1b8ea68 100644 --- a/tests/suites/stubs.js +++ b/tests/suites/stubs.js @@ -12,7 +12,6 @@ import { selectJsonLd, stripBlankNodePrefixes } from '@digitalbazaar/di-sd-primitives'; -import {Token, Type} from 'cborg'; const CBOR_PREFIX_BASE = new Uint8Array([0xd9, 0x5d, 0x00]); const CBOR_PREFIX_DERIVED = new Uint8Array([0xd9, 0x5d, 0x01]); @@ -21,6 +20,38 @@ const CBOR_PREFIX_DERIVED = new Uint8Array([0xd9, 0x5d, 0x01]); const TAGS = []; TAGS[64] = bytes => bytes; +export class DeriveStub { + constructor({typeEncoders}) { + this.typeEncoders = typeEncoders; + } + async derive({ + cryptosuite, document, proofSet, + documentLoader, dataIntegrityProof + }) { + // get test specific options + const {typeEncoders} = this; + // find matching base `proof` in `proofSet` + const {options: {proofId}} = cryptosuite; + const baseProof = await _findProof({proofId, proofSet, dataIntegrityProof}); + // generate data for disclosure + const { + baseSignature, publicKey, signatures, + labelMap, mandatoryIndexes, revealDoc + } = await _createDisclosureData( + {cryptosuite, document, proof: baseProof, documentLoader}); + + // create new disclosure proof + const newProof = {...baseProof}; + newProof.proofValue = await serializeDisclosureProofValue({ + baseSignature, publicKey, signatures, + labelMap, mandatoryIndexes, typeEncoders + }); + // attach proof to reveal doc w/o context + delete newProof['@context']; + revealDoc.proof = newProof; + return revealDoc; + } +} // Stubs the ecdsa-sd-2023 derive function export async function stubDerive({ cryptosuite, document, proofSet, @@ -37,7 +68,7 @@ export async function stubDerive({ // create new disclosure proof const newProof = {...baseProof}; - newProof.proofValue = await invalidSerializeDisclosureProofValue( + newProof.proofValue = await serializeDisclosureProofValue( {baseSignature, publicKey, signatures, labelMap, mandatoryIndexes}); // attach proof to reveal doc w/o context @@ -47,17 +78,10 @@ export async function stubDerive({ } // ecdsa-sd-2023 method that uses invalid cbor tags -function invalidSerializeDisclosureProofValue({ - baseSignature, publicKey, signatures, labelMap, mandatoryIndexes +function serializeDisclosureProofValue({ + baseSignature, publicKey, signatures, + labelMap, mandatoryIndexes, typeEncoders } = {}) { - const typeEncoders = { - Uint8Array(uint8Array) { - return [ - new Token(Type.tag, 2), - new Token(Type.bytes, uint8Array.map(b => b + 1)) - ]; - } - }; // encode as multibase (base64url no pad) CBOR const payload = [ // Uint8Array @@ -241,3 +265,40 @@ async function _findProof({proofId, proofSet, dataIntegrityProof}) { } return proof; } + +// ecdsa-sd-2023 proofValue +export function parseDisclosureProofValue({proof} = {}) { + try { + // decode from base64url + const proofValue = base64url.decode(proof.proofValue.slice(1)); + + const payload = proofValue.subarray(CBOR_PREFIX_DERIVED.length); + const [ + baseSignature, + publicKey, + signatures, + compressedLabelMap, + mandatoryIndexes + ] = cborg.decode(payload, {useMaps: true, tags: TAGS}); + + const labelMap = _decompressLabelMap(compressedLabelMap); + const params = { + baseSignature, publicKey, signatures, labelMap, mandatoryIndexes + }; + return params; + } catch(e) { + const err = new TypeError( + 'The proof does not include a valid "proofValue" property.'); + err.cause = e; + throw err; + } +} +// ecdsa-sd-2023 proofValue +function _decompressLabelMap(compressedLabelMap) { + const map = new Map(); + for(const [k, v] of compressedLabelMap.entries()) { + map.set(`c14n${k}`, `u${base64url.encode(v)}`); + } + return map; +} + From f32e4f5f79bef2a28ce3c0af17c3f9ea73362881 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Sun, 17 Nov 2024 17:07:07 -0500 Subject: [PATCH 2/5] Start work on invalidProofArray. --- tests/suites/algorithms-sd.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/suites/algorithms-sd.js b/tests/suites/algorithms-sd.js index 4343431c..1503fcb2 100644 --- a/tests/suites/algorithms-sd.js +++ b/tests/suites/algorithms-sd.js @@ -179,8 +179,11 @@ export function sd2023Algorithms({ 'MUST be raised and SHOULD convey an error type of ' + 'PROOF_VERIFICATION_ERROR.', async function() { this.test.link = 'https://w3c.github.io/vc-di-ecdsa/#selective-disclosure-functions:~:text=array%20of%20integers%20%E2%80%94-,an%20error%20MUST%20be%20raised%20and%20SHOULD%20convey%20an%20error%20type%20of%20PROOF_VERIFICATION_ERROR.,-Replace%20the%20fourth'; - this.test.cell.skipMessage = 'Not Implemented'; - this.skip(); + await assertions.verificationFail({ + verifier, + credential: fixtures.get(keyType).get('invalidProofArray'), + reason: 'Should not verify proofValue array missing elements' + }); }); it('The transformation options MUST contain a type identifier for ' + 'the cryptographic suite (type), a cryptosuite identifier ' + @@ -351,5 +354,6 @@ async function _setup({ // invalid 3 byte header invalidProofValueHeader.proof.proofValue = `u${encodeBs64Url(invalidBuffer)}`; credentials.set('invalidDisclosureProofHeader', invalidProofValueHeader); + const invalidProofArray = structuredClone(securedCredential); return credentials; } From 4ee9352fd95916e129aa4e140221c6971ce76b6d Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 18 Nov 2024 14:54:33 +0000 Subject: [PATCH 3/5] Add working tests for invalid proofValue elements --- tests/suites/algorithms-sd.js | 9 +++++++++ tests/suites/stubs.js | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/tests/suites/algorithms-sd.js b/tests/suites/algorithms-sd.js index 1503fcb2..039fe3f3 100644 --- a/tests/suites/algorithms-sd.js +++ b/tests/suites/algorithms-sd.js @@ -12,6 +12,10 @@ import { encodeBs64Url, getBs64UrlBytes } from '../helpers.js'; +import { + parseDisclosureProofValue, + serializeProofValue +} from './stubs.js'; import {expect} from 'chai'; import {getMultiKey} from '../vc-generator/key-gen.js'; import {getSuites} from './helpers.js'; @@ -355,5 +359,10 @@ async function _setup({ invalidProofValueHeader.proof.proofValue = `u${encodeBs64Url(invalidBuffer)}`; credentials.set('invalidDisclosureProofHeader', invalidProofValueHeader); const invalidProofArray = structuredClone(securedCredential); + const params = parseDisclosureProofValue({proof: invalidProofArray.proof}); + invalidProofArray.proof.proofValue = serializeProofValue({ + payload: [params.baseSignature, params.publicKey] + }); + credentials.set('invalidProofArray', invalidProofArray); return credentials; } diff --git a/tests/suites/stubs.js b/tests/suites/stubs.js index c1b8ea68..78eca59f 100644 --- a/tests/suites/stubs.js +++ b/tests/suites/stubs.js @@ -101,6 +101,18 @@ function serializeDisclosureProofValue({ return `u${base64url.encode(cbor)}`; } +// ecdsa-sd-2023 test data creation function +export function serializeProofValue({ + prefix = CBOR_PREFIX_DERIVED, + payload, + typeEncoders +}) { + const cbor = _concatBuffers([ + prefix, cborg.encode(payload, {useMaps: true, typeEncoders}) + ]); + return `u${base64url.encode(cbor)}`; +} + // ecdsa-sd-2023 derive helper async function _createDisclosureData({ cryptosuite, document, proof, documentLoader From f28651e4cb65e88372440765b8cd901b137836bf Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 18 Nov 2024 15:00:53 +0000 Subject: [PATCH 4/5] Remove stubDerived & DRY up proofValue serialization. --- tests/suites/stubs.js | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/tests/suites/stubs.js b/tests/suites/stubs.js index 78eca59f..f87b658a 100644 --- a/tests/suites/stubs.js +++ b/tests/suites/stubs.js @@ -52,30 +52,6 @@ export class DeriveStub { return revealDoc; } } -// Stubs the ecdsa-sd-2023 derive function -export async function stubDerive({ - cryptosuite, document, proofSet, - documentLoader, dataIntegrityProof -}) { - // find matching base `proof` in `proofSet` - const {options: {proofId}} = cryptosuite; - const baseProof = await _findProof({proofId, proofSet, dataIntegrityProof}); - // generate data for disclosure - const { - baseSignature, publicKey, signatures, labelMap, mandatoryIndexes, revealDoc - } = await _createDisclosureData( - {cryptosuite, document, proof: baseProof, documentLoader}); - - // create new disclosure proof - const newProof = {...baseProof}; - newProof.proofValue = await serializeDisclosureProofValue( - {baseSignature, publicKey, signatures, labelMap, mandatoryIndexes}); - - // attach proof to reveal doc w/o context - delete newProof['@context']; - revealDoc.proof = newProof; - return revealDoc; -} // ecdsa-sd-2023 method that uses invalid cbor tags function serializeDisclosureProofValue({ @@ -95,10 +71,11 @@ function serializeDisclosureProofValue({ // array of numbers mandatoryIndexes ]; - const cbor = _concatBuffers([ - CBOR_PREFIX_DERIVED, cborg.encode(payload, {useMaps: true, typeEncoders}) - ]); - return `u${base64url.encode(cbor)}`; + return serializeProofValue({ + prefix: CBOR_PREFIX_DERIVED, + payload, + typeEncoders + }); } // ecdsa-sd-2023 test data creation function From fe8507ecb8948a8a214bb2421a003c94024b5e3c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 18 Nov 2024 15:09:58 +0000 Subject: [PATCH 5/5] Comment payload missing elements steps. --- tests/suites/algorithms-sd.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/suites/algorithms-sd.js b/tests/suites/algorithms-sd.js index 039fe3f3..a6173a61 100644 --- a/tests/suites/algorithms-sd.js +++ b/tests/suites/algorithms-sd.js @@ -359,7 +359,9 @@ async function _setup({ invalidProofValueHeader.proof.proofValue = `u${encodeBs64Url(invalidBuffer)}`; credentials.set('invalidDisclosureProofHeader', invalidProofValueHeader); const invalidProofArray = structuredClone(securedCredential); + // parse the existing disclosure proofValue const params = parseDisclosureProofValue({proof: invalidProofArray.proof}); + // create a new proofValue missing 3 elements invalidProofArray.proof.proofValue = serializeProofValue({ payload: [params.baseSignature, params.publicKey] });