From ca57fd4f0bee9ad2404796b7b428816a01b8af66 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 17 Oct 2024 14:13:43 -0400 Subject: [PATCH] Create invalid disclosed VC w/ 2 components. --- tests/setup.js | 17 ++++++++++ tests/suites/verify.js | 3 +- tests/vc-generator/stubMethods.js | 55 +++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/tests/setup.js b/tests/setup.js index ff0d6aa..b1d149b 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -14,6 +14,10 @@ import { getMultikeys, issueCredentials } from './vc-generator/index.js'; +import { + encodeProofValue, + parseDisclosureProofValue +} from './vc-generator/stubMethods.js'; import {generators} from 'data-integrity-test-suite-assertion'; import {writeFile} from 'node:fs/promises'; @@ -144,6 +148,19 @@ export async function verifySetup({credentials, keyTypes, suite}) { } } disclosed.invalid.valuePrefix = valuePrefix; + // invalid element count means less than 4 components + const componentCount = disclosed.invalid.componentCount = new Map(); + for(const [keyType, versions] of disclosed?.basic) { + componentCount.set(keyType, new Map()); + for(const [vcVersion, vc] of versions) { + const modifiedVc = structuredClone(vc); + const params = parseDisclosureProofValue({proof: modifiedVc.proof}); + const payload = [params.bbsProof, params.presentationHeader]; + modifiedVc.proof.proofValue = encodeProofValue({payload}); + // perform test data mutation here + componentCount.get(keyType).set(vcVersion, modifiedVc); + } + } return { base, disclosed diff --git a/tests/suites/verify.js b/tests/suites/verify.js index 23b89be..b59262f 100644 --- a/tests/suites/verify.js +++ b/tests/suites/verify.js @@ -151,7 +151,8 @@ export function verifySuite({ async function() { this.test.link = 'https://w3c.github.io/vc-di-bbs/#:~:text=If%20the%20result%20is%20not%20an%20array%20of%20five%2C%20six%2C%20or%20seven%20elements%20%E2%80%94%20a%20byte%20array%2C%20a%20map%20of%20integers%20to%20integers%2C%20two%20arrays%20of%20integers%2C%20and%20one%20or%20two%20byte%20arrays%3B%20an%20error%20MUST%20be%20raised%20and%20SHOULD%20convey%20an%20error%20type%20of%20PROOF_VERIFICATION_ERROR'; await verificationFail({ - credential: cloneTestVector(disclosed?.invalid?.elementCount), + credential: cloneTestVector(disclosed?.invalid?.componentCount), + verifier, reason: 'Should not verify a disclosed VC w/ less than 4 components' }); }); diff --git a/tests/vc-generator/stubMethods.js b/tests/vc-generator/stubMethods.js index 80665d9..6b2c359 100644 --- a/tests/vc-generator/stubMethods.js +++ b/tests/vc-generator/stubMethods.js @@ -439,3 +439,58 @@ async function _findProof({proofId, proofSet, dataIntegrityProof}) { export function stringToUtf8Bytes({str, utfOffset = 0}) { return TEXT_ENCODER.encode(str).map(b => b + utfOffset); } + +export function parseDisclosureProofValue({proof} = {}) { + try { + if(typeof proof?.proofValue !== 'string') { + throw new TypeError('"proof.proofValue" must be a string.'); + } + if(proof.proofValue[0] !== 'u') { + throw new Error('Only base64url multibase encoding is supported.'); + } + + // decode from base64url + const proofValue = base64url.decode(proof.proofValue.slice(1)); + if(!_startsWithBytes(proofValue, CBOR_PREFIX_DERIVED)) { + throw new TypeError('"proof.proofValue" must be a derived proof.'); + } + + const payload = proofValue.subarray(CBOR_PREFIX_DERIVED.length); + const [ + bbsProof, + compressedLabelMap, + mandatoryIndexes, + selectiveIndexes, + presentationHeader + ] = cborg.decode(payload, {useMaps: true, tags: TAGS}); + + const labelMap = _decompressLabelMap(compressedLabelMap); + const params = { + bbsProof, labelMap, mandatoryIndexes, selectiveIndexes, + presentationHeader + }; + return params; + } catch(e) { + const err = new TypeError( + 'The proof does not include a valid "proofValue" property.'); + err.cause = e; + throw err; + } +} + +function _decompressLabelMap(compressedLabelMap) { + const map = new Map(); + for(const [k, v] of compressedLabelMap.entries()) { + map.set(`c14n${k}`, `b${v}`); + } + return map; +} + +function _startsWithBytes(buffer, prefix) { + for(let i = 0; i < prefix.length; ++i) { + if(buffer[i] !== prefix[i]) { + return false; + } + } + return true; +}