Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use exported vc gens #30

Merged
merged 9 commits into from
Jun 18, 2024
64 changes: 45 additions & 19 deletions tests/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
*/
import {
deriveCredentials,
getMultikeys,
issueCredentials
} from './vc-generator/index.js';
import {generators} from 'data-integrity-test-suite-assertion';

export async function verifySetup({credentials, keyTypes, suite}) {
const testVectors = {
Expand All @@ -25,22 +27,31 @@ export async function verifySetup({credentials, keyTypes, suite}) {
lessThanFull: new Map(),
//disclosedCredentialsWithoutFirstArrayElement
missingElements: new Map()
},
invalid: {
// invalid "proof.type" and "proof.cryptosuite"
proofTypeAndCryptosuite: new Map(),
// invalid "proof.cryptosuite"
cryptosuite: new Map()
}
}
};
const {subjectNestedObjects, subjectHasArrays} = credentials.verify;
const keys = await getMultikeys({keyTypes});
// takes an object with keys versions values vector and
// transforms the vectors
const transformVectors = (obj, func = id => id) => Object.entries(obj).map(
input => {
const [vcVersion, vector] = input;
return [vcVersion, func(structuredClone(vector))];
});

// create initial signed VCs
testVectors.signed = await issueCredentials({
credentials: Object.entries(subjectNestedObjects),
suite,
keyTypes
});
// takes an object with keys versions values vector and
// transforms the vectors
const transformVectors = (obj, func) => Object.entries(obj).map(input => {
const [vcVersion, vector] = input;
return [vcVersion, func(structuredClone(vector))];
});
const disclosedBaseVectors = transformVectors(
subjectNestedObjects,
vector => {
Expand All @@ -50,8 +61,8 @@ export async function verifySetup({credentials, keyTypes, suite}) {
// use initial VCs for a basic selective disclosure test
testVectors.disclosed.base = await deriveCredentials({
vectors: disclosedBaseVectors,
suite,
keyTypes
suiteName: suite,
keys
});
const disclosedNestedVectors = transformVectors(
subjectNestedObjects,
Expand All @@ -63,8 +74,8 @@ export async function verifySetup({credentials, keyTypes, suite}) {
// create initial nestedDisclosedCredential from signedVc
testVectors.disclosed.nested = await deriveCredentials({
vectors: disclosedNestedVectors,
suite,
keyTypes
suiteName: suite,
keys
});
const disclosedNoIdVectors = transformVectors(
subjectNestedObjects,
Expand All @@ -78,14 +89,14 @@ export async function verifySetup({credentials, keyTypes, suite}) {
);
testVectors.disclosed.noIds = await deriveCredentials({
vectors: disclosedNoIdVectors,
keyTypes,
suite
keys,
suiteName: suite
});
// select full arrays
testVectors.disclosed.array.full = await deriveCredentials({
vectors: Object.entries(structuredClone(subjectHasArrays)),
suite,
keyTypes
vectors: transformVectors(subjectHasArrays),
suiteName: suite,
keys
});
const lessThanFullVectors = transformVectors(
subjectHasArrays,
Expand All @@ -97,8 +108,8 @@ export async function verifySetup({credentials, keyTypes, suite}) {
);
testVectors.disclosed.array.lessThanFull = await deriveCredentials({
vectors: lessThanFullVectors,
suite,
keyTypes
suiteName: suite,
keys
});
const removeFirst7Vectors = transformVectors(
subjectHasArrays,
Expand All @@ -110,8 +121,23 @@ export async function verifySetup({credentials, keyTypes, suite}) {
);
testVectors.disclosed.array.missingElements = await deriveCredentials({
vectors: removeFirst7Vectors,
suite,
keyTypes
suiteName: suite,
keys
});
const {mandatory} = generators;
const {invalidCryptosuite, invalidProofType} = mandatory;
testVectors.disclosed.invalid.proofTypeAndCryptosuite =
await deriveCredentials({
keys,
vectors: transformVectors(subjectNestedObjects),
suiteName: suite,
generators: [invalidProofType, invalidCryptosuite]
});
testVectors.disclosed.invalid.cryptosuite = await deriveCredentials({
keys,
vectors: transformVectors(subjectNestedObjects),
suiteName: suite,
generators: [invalidCryptosuite]
});
return testVectors;
}
57 changes: 27 additions & 30 deletions tests/suites/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,72 +48,69 @@ export function verifySuite({
};
});
const {disclosed, signed} = credentials;
const getTestVector = map => map?.get(keyType)?.get(vcVersion);
const cloneTestVector = map => structuredClone(
map?.get(keyType)?.get(vcVersion));
it('MUST verify a valid VC with a bbs-2023 proof.',
async function() {
const credential = getTestVector(disclosed?.base);
const credential = cloneTestVector(disclosed?.base);
await verificationSuccess({credential, verifier});
});
it('MUST verify a valid VC with nested disclosed properties.',
async function() {
const credential = getTestVector(disclosed?.nested);
const credential = cloneTestVector(disclosed?.nested);
await verificationSuccess({credential, verifier});
});
it('MUST verify a valid VC with disclosed properties and bnodes.',
async function() {
const credential = getTestVector(disclosed?.noIds);
const credential = cloneTestVector(disclosed?.noIds);
await verificationSuccess({credential, verifier});
});
it('MUST verify with full array revealed properties',
async function() {
const credential = getTestVector(disclosed?.array?.full);
const credential = cloneTestVector(disclosed?.array?.full);
await verificationSuccess({credential, verifier});
});
it('MUST verify with fewer array revealed properties',
async function() {
const credential = getTestVector(disclosed?.array?.lessThanFull);
const credential = cloneTestVector(disclosed?.array?.lessThanFull);
await verificationSuccess({credential, verifier});
});
it('MUST verify w/o first element revealed properties',
async function() {
const credential = getTestVector(disclosed?.array?.missingElements);
const credential = cloneTestVector(
disclosed?.array?.missingElements);
await verificationSuccess({credential, verifier});
});
it('If the "proofValue" string does not start with "u", an ' +
'error MUST be raised.', async function() {
const credential = getTestVector(disclosed?.base);
const signedCredentialCopy = structuredClone(credential);
const credential = cloneTestVector(disclosed?.base);
// intentionally modify proofValue to not start with 'u'
signedCredentialCopy.proof.proofValue = 'a';
await verificationFail({
credential: signedCredentialCopy, verifier
});
credential.proof.proofValue = 'a';
await verificationFail({credential, verifier});
});
it('If the "cryptosuite" field is not the string "bbs-2023", ' +
'an error MUST be raised.', async function() {
const credential = getTestVector(disclosed?.base);
const signedCredentialCopy = structuredClone(credential);
signedCredentialCopy.proof.cryptosuite = 'invalid-cryptosuite';
await verificationFail({
credential: signedCredentialCopy, verifier
});
const credential = cloneTestVector(disclosed?.invalid?.cryptosuite);
await verificationFail({credential, verifier});
});
it('If proofConfig.type is not set to DataIntegrityProof and/or ' +
'proofConfig.cryptosuite is not set to bbs-2023, an ' +
'INVALID_PROOF_CONFIGURATION error MUST be raised.', async function() {
this.test.link = 'https://w3c.github.io/vc-di-bbs/#base-proof-transformation-bbs-2023:~:text=If%20proofConfig.type%20is%20not%20set%20to%20DataIntegrityProof%20and/or%20proofConfig.cryptosuite%20is%20not%20set%20to%20bbs%2D2023%2C%20an%20INVALID_PROOF_CONFIGURATION%20error%20MUST%20be%20raised.';
const credential = cloneTestVector(
disclosed?.invalid?.proofTypeAndCryptosuite);
await verificationFail({credential, verifier});
});
it('MUST fail to verify a base proof.', async function() {
const credential = getTestVector(signed);
const signedCredentialCopy = structuredClone(credential);
await verificationFail({
credential: signedCredentialCopy, verifier
});
const credential = cloneTestVector(signed);
await verificationFail({credential, verifier});
});
it('MUST fail to verify a modified disclosed credential.',
async function() {
const credential = getTestVector(disclosed?.base);
const signedCredentialCopy = structuredClone(credential);
const credential = cloneTestVector(disclosed?.base);
// intentionally modify `credentialSubject` ID
signedCredentialCopy.credentialSubject.id = 'urn:invalid';
await verificationFail({
credential: signedCredentialCopy, verifier
});
credential.credentialSubject.id = 'urn:invalid';
await verificationFail({credential, verifier});
});
});
}
Expand Down
79 changes: 33 additions & 46 deletions tests/vc-generator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as vc from '@digitalbazaar/vc';
import {documentLoader as defaultLoader} from './documentLoader.js';
import {getMultikeys} from './key-gen.js';
import {getSuite} from './cryptosuites.js';
import {issueCloned} from 'data-integrity-test-suite-assertion';

/**
* Issues test data locally and then returns a Map
Expand Down Expand Up @@ -64,52 +65,6 @@ export async function issueCredential({
});
}

/**
* Derives test data locally and then returns a Map
* with the test data.
*
* @param {object} options - Options to use.
* @param {Map<string, object>} options.vectors - Version & VC creation options.
* @param {Function} [options.documentLoader = defaultLoader] - A
* documentLoader(url).
* @param {string} options.suite - A cryptosuite id.
* @param {Array<string>} options.keyTypes - A list of key types.
*
* @returns {Promise<Map<string, object>>} Returns a Map <keyType, vc>.
*/
export async function deriveCredentials({
vectors,
documentLoader = defaultLoader,
suite,
keyTypes = ['P-381']
}) {
const results = new Map();
const keys = await getMultikeys({keyTypes});
for(const [keyType, {signer, issuer}] of keys) {
const versionedVcs = new Map();
for(const [vcVersion, vector] of vectors) {
const {credential, mandatoryPointers, selectivePointers} = vector;
const verifiableCredential = await issueCredential({
credential,
issuer,
signer,
suite,
mandatoryPointers
});
const derivedVc = await deriveCredential({
verifiableCredential,
documentLoader,
suite,
signer,
selectivePointers
});
versionedVcs.set(vcVersion, derivedVc);
}
results.set(keyType, versionedVcs);
}
return results;
}

export async function deriveCredential({
documentLoader = defaultLoader,
verifiableCredential,
Expand All @@ -135,3 +90,35 @@ export async function verifyCredential({
suite: getSuite({suite, verify: true})
});
}

export async function deriveCredentials({
keys,
vectors,
map = new Map(),
suiteName,
generators = []
}) {
for(const [keyType, {signer, issuer}] of keys) {
map.set(keyType, new Map());
for(const [vcVersion, vector] of vectors) {
const {credential, mandatoryPointers, selectivePointers} = vector;
const _credential = structuredClone(credential);
_credential.issuer = issuer;
// the first params passed to the first generator
const initParams = {
suite: getSuite({suite: suiteName, signer, mandatoryPointers}),
selectiveSuite: getSuite({suite: suiteName, signer, selectivePointers}),
credential: _credential
};
// call each generator on itself to produce accumulated invalid suites
// and vectors
const testData = generators.reduce((accumulator, current) =>
current(accumulator), initParams);
const vc = await issueCloned(testData);
map.get(keyType).set(vcVersion, vc);
}
}
return map;
}

export {getSuite, getMultikeys};