Skip to content

Commit

Permalink
fix status list in presentation
Browse files Browse the repository at this point in the history
Signed-off-by: F-Node-Karlsruhe <christian.fries@eecc.de>
  • Loading branch information
F-Node-Karlsruhe committed Sep 11, 2023
1 parent 516f895 commit 3763867
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ VC Verifier Changelog
WIP
---

- fix statusList in presentation


1.7.1 (2023-09-08)
---

Expand Down
69 changes: 69 additions & 0 deletions api/__tests__/presentation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,77 @@ const domainPresentation: any = {
}
}

const statusPresentation: any = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/ed25519-2020/v1"
],
"type": [
"VerifiablePresentation"
],
"verifiableCredential": [
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"ipfs://QmY9CDY2PoXLgHr2vG4u8mj27cfAyuzVxE2swt8wwFn7Rt",
"https://w3id.org/vc-revocation-list-2020/v1",
"https://w3id.org/security/suites/ed25519-2020/v1"
],
"id": "https://ssi.eecc.de/api/registry/vc/b7440bf7-2317-43e4-9857-4c85032ac4a1",
"type": [
"VerifiableCredential",
"EECCAccessCredential"
],
"issuer": {
"id": "did:web:ssi.eecc.de",
"image": "https://id.eecc.de/assets/img/logo_big.png",
"name": "EECC"
},
"issuanceDate": "2023-06-19T09:58:08Z",
"credentialStatus": {
"id": "https://ssi.eecc.de/api/registry/vc/status/did:web:ssi.eecc.de/1#1",
"type": "RevocationList2020Status",
"revocationListIndex": 1,
"revocationListCredential": "https://ssi.eecc.de/api/registry/vc/status/did:web:ssi.eecc.de/1"
},
"credentialSubject": {
"id": "https://ssi.eecc.de/verifier",
"customer_name": "VC Verifier"
},
"proof": {
"type": "Ed25519Signature2020",
"created": "2023-06-19T09:58:08Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:web:ssi.eecc.de#z6MkoHWsmSZnHisAxnVdokYHnXaVqWFZ4H33FnNg13zyymxd",
"proofValue": "z247VYAm5GbG1sAAcqW7QwEL1mfXxaSa3N93EuLc4HeTUm219UjrPMC5gyq5xTAaDQCVMUEVTouyboY4UMTxzjekN"
}
}
],
"holder": "did:web:ssi.eecc.de",
"proof": {
"type": "Ed25519Signature2020",
"created": "2023-06-19T10:19:04Z",
"verificationMethod": "did:web:ssi.eecc.de#z6MkoHWsmSZnHisAxnVdokYHnXaVqWFZ4H33FnNg13zyymxd",
"proofPurpose": "authentication",
"challenge": "demochallenge",
"proofValue": "z3BCT7df4bRXXTa9i79apmiou76M8LVZXGFYHA18xT6wX3PfcpjfWaMc9xhFwmGi9XTj8tth1ai1ASeQoHiGWMn1V"
}
}

describe("Verifier API Test for Presentations", () => {

test("Verify presentation with status", async () => {
const res = await request(app).post("/api/verifier").send([statusPresentation]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(true);
expect(res.body[0]).toHaveProperty('credentialResults');
res.body[0].credentialResults.forEach((el: any) => {
expect(el).toHaveProperty('verified');
expect(el.verified).toBe(true);
});
});

test("Verify single presentation with challenge", async () => {
const res = await request(app).post("/api/verifier").query({ challenge: '12345' }).send([multiPresentation]);
expect(res.statusCode).toEqual(200);
Expand Down
49 changes: 42 additions & 7 deletions api/src/services/verifier/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,32 @@ function getSuites(proof: Proof | Proof[]): unknown[] {

}

function getPresentationStatus(presentation: VerifiablePresentation): CredentialStatus[] | CredentialStatus | undefined {

const credentials = (
Array.isArray(presentation.verifiableCredential)
? presentation.verifiableCredential
: [presentation.verifiableCredential]
)
.filter((credential: VerifiableCredential) => credential.credentialStatus);

if (credentials.length == 0) return undefined;

if (credentials.length == 1) return credentials[0].credentialStatus;

const statusTypes = credentials.map((credential: VerifiableCredential) => {
return Array.isArray(credential.credentialStatus)
? credential.credentialStatus.map((credentialStatus: CredentialStatus) => credentialStatus.type)
: credential.credentialStatus.type
});

// disallow multiple status types
if (new Set(statusTypes.flat(1)).size > 1) throw new Error('Currently only on status type is allowed within one presentation!');

return credentials[0].credentialStatus;

}

function getCheckStatus(credentialStatus?: CredentialStatus[] | CredentialStatus): any | undefined {
// no status provided
if (!credentialStatus) return undefined;
Expand Down Expand Up @@ -79,13 +105,15 @@ export class Verifier {

let result;

const checkStatus = getCheckStatus(verifiable.credentialStatus);

if (verifiable.type.includes('VerifiableCredential')) {

if ((Array.isArray(verifiable.proof) ? verifiable.proof[0].type : verifiable.proof.type) == 'DataIntegrityProof') {
const credential = verifiable as VerifiableCredential;

const checkStatus = getCheckStatus(credential.credentialStatus);

if ((Array.isArray(credential.proof) ? credential.proof[0].type : credential.proof.type) == 'DataIntegrityProof') {

result = await jsigs.verify(verifiable, {
result = await jsigs.verify(credential, {
suite,
purpose: new AssertionProofPurpose(),
documentLoader,
Expand All @@ -95,17 +123,24 @@ export class Verifier {

} else {

result = await verifyCredential({ credential: verifiable, suite, documentLoader, checkStatus });
result = await verifyCredential({ credential, suite, documentLoader, checkStatus });

}
}

if (verifiable.type.includes('VerifiablePresentation')) {

const presentation = verifiable as VerifiablePresentation;

// try to use challenge in proof if not provided in case no exchange protocol is used
if (!challenge) challenge = (Array.isArray(verifiable.proof) ? verifiable.proof[0].challenge : verifiable.proof.challenge);
if (!challenge) challenge = (Array.isArray(presentation.proof) ? presentation.proof[0].challenge : presentation.proof.challenge);


const checkStatus = getCheckStatus(
getPresentationStatus(presentation)
);

result = await verify({ presentation: verifiable, suite, documentLoader, challenge, domain, checkStatus });
result = await verify({ presentation, suite, documentLoader, challenge, domain, checkStatus });

}

Expand Down

0 comments on commit 3763867

Please sign in to comment.