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

Add algorithm suites (2 -> 1) #96

Open
wants to merge 35 commits into
base: add-conformance-suite
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0b7bc09
Add non-suite specific algorithm statements & start ecdsa-rdfc-2019.
aljones15 Nov 7, 2024
96690e1
Add basic matrix and row info to rdfc2019 algorithms.
aljones15 Nov 8, 2024
2279c67
Add the ecdsa-rdfc-2019 algorithm statements.
aljones15 Nov 8, 2024
ed9cfaf
Add setup code and first test for well formed utf strings.
aljones15 Nov 8, 2024
7b9c7a0
Create common algorithms assertions.
aljones15 Nov 8, 2024
ea3e4c9
Use verificationSucess to test common algorithm tests.
aljones15 Nov 8, 2024
eb32e93
Fill in dummy data for rdfc-2019 algorithms.
aljones15 Nov 8, 2024
27f53d8
Start work on generators for rdfc 2019 setup.
aljones15 Nov 9, 2024
299a12f
Move getSuites to common helpers file.
aljones15 Nov 10, 2024
c7a5bb7
Further work on algorithms setup.
aljones15 Nov 10, 2024
0b3d470
Stub unsafe for canonize.
aljones15 Nov 10, 2024
7f49ed1
Add basic algorithms test.
aljones15 Nov 10, 2024
66d96b8
Proxy canonize on cryptosuite itself.
aljones15 Nov 10, 2024
6b54465
Use unsafeProxy for no proof type or cryptosuite.
aljones15 Nov 11, 2024
9a0f1d9
Add beforeEach & fix unsafeProxy.
aljones15 Nov 11, 2024
a668cfa
Change to implemented array.
aljones15 Nov 11, 2024
87bc3d2
Move keyTypes into algorithms.
aljones15 Nov 11, 2024
acd5776
Change common tests to verifier tests.
aljones15 Nov 12, 2024
a8f9f63
Only run keyType statements if suite supports keyTypes.
aljones15 Nov 12, 2024
494e350
Start work on common setup and proxy.
aljones15 Nov 13, 2024
b0b8e2f
Add proxy for createVerifyData that uses sha512.
aljones15 Nov 13, 2024
4f6d275
Switch the sha hashes for keyTypes.
aljones15 Nov 13, 2024
d13dd26
Add matrix code to common & push name to implemented.
aljones15 Nov 13, 2024
f79c096
ecdsa-jcs algorithms and helpers
PatStLouis Nov 11, 2024
7244c28
Apply text suggestion
PatStLouis Nov 12, 2024
17d6e68
Use test helpers not suite helpers.
aljones15 Nov 13, 2024
db117a6
Switch default interop vc version to 2.0 for rdfc-2019.
aljones15 Nov 13, 2024
c4db008
Merge isValid utils into common helpers import.
aljones15 Nov 13, 2024
befb9e9
Add initial jcs 2019 config and update cryptosuite name.
aljones15 Nov 13, 2024
0a889e5
Change default supported vc type to 2.0.
aljones15 Nov 13, 2024
5832b1b
Minor corrections to jcs suite.
aljones15 Nov 13, 2024
405cce2
Add implemented to suites.
aljones15 Nov 13, 2024
da85c81
Replace ecdsa2022 w/ jcs2019Proofs.
aljones15 Nov 13, 2024
bf0e8ca
Move lone transformation test to main area.
aljones15 Nov 13, 2024
e644d74
Update tests/helpers.js comment about test version support.
aljones15 Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion config/runner.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,17 @@
"P-384": 96
},
"interop": {
"vcVersion": "1.1"
"vcVersion": "2.0"
}
},
"ecdsa-jcs-2019": {
"tags": ["ecdsa-jcs-2019"],
"proofLengths": {
"P-256": 64,
"P-384": 96
},
"interop": {
"vcVersion": "2.0"
}
},
"ecdsa-sd-2023": {
Expand Down
7 changes: 7 additions & 0 deletions tests/90-algorithms-jcs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*!
* Copyright 2024 Digital Bazaar, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
import {ecdsaJcs2019Algorithms} from './suites/algorithms-jcs.js';

ecdsaJcs2019Algorithms();
47 changes: 47 additions & 0 deletions tests/90-algorithms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*!
* Copyright 2024 Digital Bazaar, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
import {
commonAlgorithms,
ecdsaRdfc2019Algorithms
} from './suites/algorithms.js';
import {endpoints} from 'vc-test-suite-implementations';
import {getSuiteConfig} from './test-config.js';

const cryptosuites = [
'ecdsa-rdfc-2019',
];

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];
ecdsaRdfc2019Algorithms({
verifiers,
suiteName,
keyTypes: vectors.keyTypes,
vcVersion,
credential: document,
mandatoryPointers,
selectivePointers
});
commonAlgorithms({
verifiers,
suiteName,
keyTypes: vectors.keyTypes,
vcVersion,
credential: document,
mandatoryPointers,
selectivePointers
});
}
}
75 changes: 71 additions & 4 deletions tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import * as bs58 from 'base58-universal';
import * as bs64 from 'base64url-universal';
import {createRequire} from 'node:module';
import {isUtf8} from 'node:buffer';
import {klona} from 'klona';
import {readFileSync} from 'fs';
import {v4 as uuidv4} from 'uuid';

export const require = createRequire(import.meta.url);
Expand Down Expand Up @@ -89,8 +91,8 @@ export const createDisclosedVc = async ({
export const endpointCheck = ({endpoint, vcVersion, keyType}) => {
const {
supportedEcdsaKeyTypes,
// assume support for vc 1.1
supports = {vc: ['1.1']}
// assume support for vc 2.0
supports = {vc: ['2.0']}
} = endpoint.settings;
// if an issuer does not support the current keyType skip it
const keyTypes = supportedEcdsaKeyTypes || supports?.keyTypes;
Expand Down Expand Up @@ -208,11 +210,76 @@ export function getColumnNameForTestCategory(testCategory) {
}
}

export function setupReportableTestSuite(runnerContext, name) {
export function setupReportableTestSuite(
runnerContext,
name = 'Implementation'
) {
runnerContext.matrix = true;
runnerContext.report = true;
runnerContext.rowLabel = 'Test Name';
runnerContext.columnLabel = name;

runnerContext.implemented = [];
}

export function isValidUtf8(string) {
const textEncoder = new TextEncoder();
const uint8Array = textEncoder.encode(string);
if(!isUtf8(uint8Array)) {
return false;
} else {
return true;
}
}

export function isValidDatetime(dateString) {
return !isNaN(Date.parse(dateString));
}

export const config = JSON.parse(readFileSync('./config/runner.json'));

export function createValidCredential(version = 2) {
let credential = {
type: ['VerifiableCredential'],
id: `urn:uuid:${uuidv4()}`,
credentialSubject: {id: 'did:example:alice'}
};
if(version === 1) {
// add v1.1 context and issuanceDate
credential = Object.assign({}, {
'@context': [
'https://www.w3.org/2018/credentials/v1',
'https://w3id.org/security/data-integrity/v2'
],
issuanceDate: ISOTimeStamp()
}, credential);
} else if(version === 2) {
// add v2 context
credential = Object.assign({}, {
'@context': [
'https://www.w3.org/ns/credentials/v2'
]
}, credential);
} else {
return null;
}
return credential;
}

export function setupRow() {
// append test meta data to the it/test this.
this.currentTest.cell = {
columnId: this.currentTest.parent.title,
rowId: this.currentTest.title
};
}

export function getProofs(issuedVc) {
// if the implementation failed to issue a VC or to sign the VC,
// return an empty array
if(!issuedVc?.proof) {
return [];
}
const proofs = Array.isArray(issuedVc?.proof) ?
issuedVc.proof : [issuedVc?.proof];
return proofs;
}
196 changes: 196 additions & 0 deletions tests/suites/algorithms-jcs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
/*!
* Copyright 2024 Digital Bazaar, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
import {
config,
createInitialVc,
createValidCredential,
getProofs,
isValidDatetime,
isValidUtf8,
setupReportableTestSuite,
setupRow
} from '../helpers.js';
import chai from 'chai';
import {endpoints} from 'vc-test-suite-implementations';

const should = chai.should();

export function ecdsaJcs2019Algorithms() {
const cryptosuite = 'ecdsa-jcs-2019';
const {tags} = config.suites[
cryptosuite
];
const {match: issuers} = endpoints.filterByTag({
tags: [...tags],
property: 'issuers'
});

describe('ecdsa-jcs-2019 - Algorithms - Transformation', function() {
setupReportableTestSuite(this);
this.implemented = [...issuers.keys()];
let validCredential;
before(async function() {
validCredential = await createValidCredential();
});
for(const [columnId, {endpoints}] of issuers) {
describe(columnId, function() {
const [issuer] = endpoints;
let issuedVc;
let proofs;
let jcs2019Proofs = [];
before(async function() {
issuedVc = await createInitialVc({issuer, vc: validCredential});
proofs = getProofs(issuedVc);
if(proofs?.length) {
jcs2019Proofs = proofs.filter(
proof => proof?.cryptosuite === cryptosuite);
}
});
beforeEach(setupRow);
const assertBefore = () => {
should.exist(issuedVc, 'Expected issuer to have issued a ' +
'credential.');
should.exist(proofs, 'Expected credential to have a proof.');
jcs2019Proofs.length.should.be.gte(1, 'Expected at least one ' +
'ecdsa-jcs-2019 cryptosuite.');
};
it('The proof options MUST contain a type identifier for the ' +
'cryptographic suite (type) and MAY contain a cryptosuite ' +
'identifier (cryptosuite).',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#proof-serialization-ecdsa-jcs-2019';
assertBefore();
for(const proof of jcs2019Proofs) {
should.exist(proof.type,
'Expected a type identifier on the proof.');
}
});
it('The transformation options MUST contain a type identifier ' +
'for the cryptographic suite (type) and a cryptosuite identifier ' +
'(cryptosuite).',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#transformation-ecdsa-jcs-2019';
assertBefore();
for(const proof of jcs2019Proofs) {
should.exist(proof.type, 'Expected a type identifier on ' +
'the proof.');
should.exist(proof.cryptosuite,
'Expected a cryptosuite identifier on the proof.');
}
});
it('Whenever this algorithm encodes strings, ' +
'it MUST use UTF-8 encoding.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#transformation-ecdsa-jcs-2019';
assertBefore();
for(const proof of jcs2019Proofs) {
should.exist(proof?.proofValue,
'Expected proofValue to exist.');
isValidUtf8(proof.proofValue).should.equal(
true,
'Expected proofValue value to be a valid UTF-8 encoded string.'
);
}
});
it('If options.type is not set to the string DataIntegrityProof or ' +
'options.cryptosuite is not set to the string ecdsa-jcs-2019, ' +
'an error MUST be raised and SHOULD convey an error type ' +
'of PROOF_TRANSFORMATION_ERROR.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#transformation-ecdsa-jcs-2019';
assertBefore();
for(const proof of jcs2019Proofs) {
should.exist(proof.type,
'Expected a type identifier on the proof.');
should.exist(proof.cryptosuite,
'Expected a cryptosuite identifier on the proof.');
proof.type.should.equal('DataIntegrityProof',
'Expected DataIntegrityProof type.');
proof.cryptosuite.should.equal('ecdsa-jcs-2019',
'Expected ecdsa-jcs-2019 cryptosuite.');
}
});
});
}
});

describe('ecdsa-jcs-2019 - Algorithms - Proof Configuration', function() {
setupReportableTestSuite(this);
this.implemented = [...issuers.keys()];
let validCredential;
before(async function() {
validCredential = await createValidCredential();
});
for(const [columnId, {endpoints}] of issuers) {
describe(columnId, function() {
const [issuer] = endpoints;
let issuedVc;
let proofs;
let jcs2019Proofs = [];
before(async function() {
issuedVc = await createInitialVc({issuer, vc: validCredential});
proofs = getProofs(issuedVc);
if(proofs?.length) {
jcs2019Proofs = proofs.filter(
proof => proof?.cryptosuite === cryptosuite);
}
});
beforeEach(setupRow);
const assertBefore = () => {
should.exist(issuedVc, 'Expected issuer to have issued a ' +
'credential.');
should.exist(proofs, 'Expected credential to have a proof.');
jcs2019Proofs.length.should.be.gte(1, 'Expected at least one ' +
'ecdsa-jcs-2019 cryptosuite.');
};
it('The proof options MUST contain a type identifier for the ' +
'cryptographic suite (type) and MUST contain a cryptosuite ' +
'identifier (cryptosuite).',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#proof-configuration-ecdsa-jcs-2019';
assertBefore();
for(const proof of jcs2019Proofs) {
should.exist(proof.type,
'Expected a type identifier on the proof.');
should.exist(proof.cryptosuite,
'Expected a cryptosuite identifier on the proof.');
}
});
it('If proofConfig.type is not set to DataIntegrityProof ' +
'and/or proofConfig.cryptosuite is not set to ecdsa-jcs-2019, ' +
'an error MUST be raised and SHOULD convey an error type ' +
'of PROOF_GENERATION_ERROR.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#proof-configuration-ecdsa-jcs-2019';
assertBefore();
for(const proof of jcs2019Proofs) {
should.exist(proof.type,
'Expected a type identifier on the proof.');
should.exist(proof.cryptosuite,
'Expected a cryptosuite identifier on the proof.');
proof.type.should.equal('DataIntegrityProof',
'Expected DataIntegrityProof type.');
proof.cryptosuite.should.equal('ecdsa-jcs-2019',
'Expected ecdsa-jcs-2019 cryptosuite.');
}
});
it('If proofConfig.created is set and if the value is not a ' +
'valid [XMLSCHEMA11-2] datetime, an error MUST be raised and ' +
'SHOULD convey an error type of PROOF_GENERATION_ERROR.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#proof-configuration-ecdsa-jcs-2019';
for(const proof of jcs2019Proofs) {
if(proof?.created) {
isValidDatetime(proof.created).should.equal(
true,
'Expected created value to be a valid datetime string.'
);
}
}
});
});
}
});
}
Loading
Loading