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

fix context and missing vcHolder implementations #109

Merged
merged 7 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion config/runner.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"vcVersion": "2.0"
},
"vcHolder": {
"holderName": "Grotto Networking",
"holderName": "Digital Bazaar",
"tags": ["vcHolder"]
}
}
Expand Down
193 changes: 111 additions & 82 deletions tests/95-functions-sd.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,16 @@ describe('Functions - ecdsa-sd-2023', function() {
for(const [columnId, {endpoints}] of issuers) {
describe(columnId, function() {
const [issuer] = endpoints;
const [holder] = holders.get(columnId).endpoints;
const [verifier] = verifiers.get(columnId).endpoints;
let holder = null;
if(holders.get(columnId)) {
[holder] = holders.get(columnId)?.endpoints;
} else {
}
let verifier = null;
if(verifiers.get(columnId)) {
[verifier] = verifiers.get(columnId)?.endpoints;
} else {
}
let securedCredential;
let disclosedCredential;
let validDerivedProof;
Expand Down Expand Up @@ -102,23 +110,26 @@ describe('Functions - ecdsa-sd-2023', function() {
'PROOF_VERIFICATION_ERROR.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#selective-disclosure-functions';
const proof = proofExists(securedCredential);
should.exist(proof.proofValue,
'Expected proof to have proofValue.');

// Create negative fixture
const invalidBaseCredential = structuredClone(securedCredential);
invalidBaseCredential.proof.proofValue =
invalidBaseCredential.proof.proofValue.slice(1);
({disclosedCredential} = await createDisclosedVc(
{
selectivePointers: ['/credentialSubject/id'],
signedCredential: invalidBaseCredential,
vcHolder: holder
}));
should.not.exist(disclosedCredential?.proof,
'Derive endpoint should reject proof without multibase indicator.'
);
if(holder) {
const proof = proofExists(securedCredential);
should.exist(proof.proofValue,
'Expected proof to have proofValue.');
// Create negative fixture
const invalidBaseCredential = structuredClone(securedCredential);
invalidBaseCredential.proof.proofValue =
invalidBaseCredential.proof.proofValue.slice(1);
({disclosedCredential} = await createDisclosedVc(
{
selectivePointers: ['/credentialSubject/id'],
signedCredential: invalidBaseCredential,
vcHolder: holder
}));
should.not.exist(disclosedCredential?.proof,
'"Derive" endpoint should reject proof without multibase indicator.'
);
} else {
this.skip();
}
});
// 3.5.3 parseBaseProofValue
it('If the decodedProofValue does not start with the ' +
Expand All @@ -127,41 +138,48 @@ describe('Functions - ecdsa-sd-2023', function() {
'convey an error type of PROOF_VERIFICATION_ERROR.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#selective-disclosure-functions';
const proof = proofExists(securedCredential);
should.exist(proof.proofValue,
'Expected proof to have proofValue.');

// Create negative fixture
const invalidBaseCredential = structuredClone(securedCredential);
invalidBaseCredential.proof.proofValue =
invalidBaseCredential.proof.proofValue.slice(0, 1) +
invalidBaseCredential.proof.proofValue.slice(4);
({disclosedCredential} = await createDisclosedVc(
{
selectivePointers: ['/credentialSubject/id'],
signedCredential: invalidBaseCredential,
vcHolder: holder
}));
should.not.exist(disclosedCredential?.proof,
'Derive endpoint should reject proof without header.'
);
if(holder) {
const proof = proofExists(securedCredential);
should.exist(proof.proofValue,
'Expected proof to have proofValue.');
// Create negative fixture
const invalidBaseCredential = structuredClone(securedCredential);
invalidBaseCredential.proof.proofValue =
invalidBaseCredential.proof.proofValue.slice(0, 1) +
invalidBaseCredential.proof.proofValue.slice(4);
({disclosedCredential} = await createDisclosedVc(
{
selectivePointers: ['/credentialSubject/id'],
signedCredential: invalidBaseCredential,
vcHolder: holder
}));
should.not.exist(disclosedCredential?.proof,
'"Derive" endpoint should reject proof without header.'
);
} else {
this.skip();
}
});
// 3.5.7 serializeDerivedProofValue
it('CBOR-encode components per [RFC8949] where CBOR ' +
'tagging MUST NOT be used on any of the components.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#selective-disclosure-functions';
({disclosedCredential} = await createDisclosedVc(
{
selectivePointers: ['/credentialSubject/id'],
signedCredential: securedCredential,
vcHolder: holder
}));
const decodedDerivedProofValue =
await inspectSdDerivedProofValue(disclosedCredential.proof);
should.exist(decodedDerivedProofValue,
'Implementation must not use CBOR tagging.'
);
if(holder) {
({disclosedCredential} = await createDisclosedVc(
{
selectivePointers: ['/credentialSubject/id'],
signedCredential: securedCredential,
vcHolder: holder
}));
const decodedDerivedProofValue =
await inspectSdDerivedProofValue(disclosedCredential.proof);
should.exist(decodedDerivedProofValue,
'Implementation must not use CBOR tagging.'
);
} else {
this.skip();
}
});
// 3.5.8 parseDerivedProofValue
it('If the proofValue string does not start with u, ' +
Expand All @@ -170,14 +188,17 @@ describe('Functions - ecdsa-sd-2023', function() {
'error type of PROOF_VERIFICATION_ERROR.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#selective-disclosure-functions';
await verifySuccess(verifier, validDerivedProof);

// Clone a valid proof and slice the multibase header
const invalidDerivedProof =
structuredClone(validDerivedProof);
invalidDerivedProof.proof.proofValue =
invalidDerivedProof.proof.proofValue.slice(1);
await verifyError(verifier, invalidDerivedProof);
if(verifier) {
await verifySuccess(verifier, validDerivedProof);
// Clone a valid proof and slice the multibase header
const invalidDerivedProof =
structuredClone(validDerivedProof);
invalidDerivedProof.proof.proofValue =
invalidDerivedProof.proof.proofValue.slice(1);
await verifyError(verifier, invalidDerivedProof);
} else {
this.skip();
PatStLouis marked this conversation as resolved.
Show resolved Hide resolved
}
});
// 3.5.8 parseDerivedProofValue
it('If the decodedProofValue does not start with the ECDSA-SD ' +
Expand All @@ -186,14 +207,18 @@ describe('Functions - ecdsa-sd-2023', function() {
'type of PROOF_VERIFICATION_ERROR.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#selective-disclosure-functions';
await verifySuccess(verifier, validDerivedProof);
// Clone a valid proof and slice the ECDSA-SD disclosure proof header
const invalidDerivedProof =
structuredClone(validDerivedProof);
invalidDerivedProof.proof.proofValue =
invalidDerivedProof.proof.proofValue.slice(0, 1) +
invalidDerivedProof.proof.proofValue.slice(4);
await verifyError(verifier, invalidDerivedProof);
if(verifier) {
await verifySuccess(verifier, validDerivedProof);
// Clone a valid proof and slice the ECDSA-SD disclosure proof header
const invalidDerivedProof =
structuredClone(validDerivedProof);
invalidDerivedProof.proof.proofValue =
invalidDerivedProof.proof.proofValue.slice(0, 1) +
invalidDerivedProof.proof.proofValue.slice(4);
await verifyError(verifier, invalidDerivedProof);
} else {
this.skip();
}
});
// 3.5.8 parseDerivedProofValue
it('Initialize components to an array that is the result of ' +
Expand All @@ -207,27 +232,31 @@ describe('Functions - ecdsa-sd-2023', function() {
'PROOF_VERIFICATION_ERROR.',
async function() {
this.test.link = 'https://www.w3.org/TR/vc-di-ecdsa/#selective-disclosure-functions';
const validDerivedProofValue =
await inspectSdDerivedProofValue(validDerivedProof.proof);
if(verifier) {
const validDerivedProofValue =
await inspectSdDerivedProofValue(validDerivedProof.proof);

// Create invalid bodies for negative tests
let invalidDerivedProof = structuredClone(validDerivedProof);
const invalidDerivedProofValue =
structuredClone(validDerivedProofValue);
// Create invalid bodies for negative tests
let invalidDerivedProof = structuredClone(validDerivedProof);
const invalidDerivedProofValue =
structuredClone(validDerivedProofValue);

// add a non bytearray element in the labelMap array
invalidDerivedProof = structuredClone(validDerivedProof);
invalidDerivedProofValue.labelMap.push = 'not a bytearray';
invalidDerivedProof.proof =
encodeSdDerivedProofValue(invalidDerivedProof);
await verifyError(verifier, invalidDerivedProof);
// add a non bytearray element in the labelMap array
invalidDerivedProof = structuredClone(validDerivedProof);
invalidDerivedProofValue.labelMap.push = 'not a bytearray';
invalidDerivedProof.proof =
encodeSdDerivedProofValue(invalidDerivedProof);
await verifyError(verifier, invalidDerivedProof);

// replace an integer with a string in the mandatoryIndexes array
invalidDerivedProof = structuredClone(validDerivedProof);
invalidDerivedProofValue.mandatoryIndexes[0] = '0';
invalidDerivedProof.proof =
encodeSdDerivedProofValue(invalidDerivedProof);
await verifyError(verifier, invalidDerivedProof);
// replace an integer with a string in the mandatoryIndexes array
invalidDerivedProof = structuredClone(validDerivedProof);
invalidDerivedProofValue.mandatoryIndexes[0] = '0';
invalidDerivedProof.proof =
encodeSdDerivedProofValue(invalidDerivedProof);
await verifyError(verifier, invalidDerivedProof);
} else {
this.skip();
}
});
});
}
Expand Down
31 changes: 5 additions & 26 deletions tests/mocks/valid/vc1.1/document.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,15 @@
"@context": [
"https://www.w3.org/2018/credentials/v1",
{
"@protected": true,
"DriverLicenseCredential": "urn:example:DriverLicenseCredential",
"DriverLicense": {
"@id": "urn:example:DriverLicense",
"@context": {
"@protected": true,
"id": "@id",
"type": "@type",
"documentIdentifier": "urn:example:documentIdentifier",
"dateOfBirth": "urn:example:dateOfBirth",
"expirationDate": "urn:example:expiration",
"issuingAuthority": "urn:example:issuingAuthority"
}
},
"driverLicense": {
"@id": "urn:example:driverLicense",
"@type": "@id"
}
"name": "https://schema.org/name",
"description": "https://schema.org/description"
}
],
"id": "urn:uuid:36245ee9-9074-4b05-a777-febff2e69757",
"type": ["VerifiableCredential", "DriverLicenseCredential"],
"type": ["VerifiableCredential"],
"credentialSubject": {
"id": "urn:uuid:1a0e4ef5-091f-4060-842e-18e519ab9440",
"driverLicense": {
"type": "DriverLicense",
"documentIdentifier": "T21387yc328c7y32h23f23",
"dateOfBirth": "01-01-1990",
"expirationDate": "01-01-2030",
"issuingAuthority": "VA"
}
"name": "Alice",
"description": "A credential about Alice."
}
}
1 change: 0 additions & 1 deletion tests/mocks/valid/vc1.1/mandatoryPointers.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
[
"/issuanceDate",
"/issuer"
]
5 changes: 1 addition & 4 deletions tests/mocks/valid/vc1.1/selectivePointers.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[
"/credentialSubject/driverLicense/documentIdentifier",
"/credentialSubject/driverLicense/dateOfBirth",
"/credentialSubject/driverLicense/expirationDate",
"/credentialSubject/driverLicense/issuingAuthority"
"/credentialSubject/name"
]
33 changes: 4 additions & 29 deletions tests/mocks/valid/vc2.0/document.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,12 @@
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@protected": true,
"DriverLicenseCredential": "urn:example:DriverLicenseCredential",
"DriverLicense": {
"@id": "urn:example:DriverLicense",
"@context": {
"@protected": true,
"id": "@id",
"type": "@type",
"documentIdentifier": "urn:example:documentIdentifier",
"dateOfBirth": "urn:example:dateOfBirth",
"expirationDate": "urn:example:expiration",
"issuingAuthority": "urn:example:issuingAuthority"
}
},
"driverLicense": {
"@id": "urn:example:driverLicense",
"@type": "@id"
}
}
"https://www.w3.org/ns/credentials/v2"
],
"id": "urn:uuid:36245ee9-9074-4b05-a777-febff2e69757",
"type": ["VerifiableCredential", "DriverLicenseCredential"],
"type": ["VerifiableCredential"],
"credentialSubject": {
"id": "urn:uuid:1a0e4ef5-091f-4060-842e-18e519ab9440",
"driverLicense": {
"type": "DriverLicense",
"documentIdentifier": "T21387yc328c7y32h23f23",
"dateOfBirth": "01-01-1990",
"expirationDate": "01-01-2030",
"issuingAuthority": "VA"
}
"name": "Alice",
"description": "A credential about Alice."
}
}
5 changes: 1 addition & 4 deletions tests/mocks/valid/vc2.0/selectivePointers.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[
"/credentialSubject/driverLicense/documentIdentifier",
"/credentialSubject/driverLicense/dateOfBirth",
"/credentialSubject/driverLicense/expirationDate",
"/credentialSubject/driverLicense/issuingAuthority"
"/credentialSubject/name"
]
Loading