From a818ea8cf1db8e6519bbe7f8f2d1499616bcb130 Mon Sep 17 00:00:00 2001 From: Sebastian Schmittner Date: Fri, 3 Feb 2023 11:49:23 +0100 Subject: [PATCH 1/5] added gs1 demo product example Signed-off-by: Sebastian Schmittner --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68ef988..b07afbe 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # VC Verifier -The [EECC Verifier](https://ssi.eecc.de/verifier/) for verifiable credentials provides a verification API as well as the corresponding UI. It's primary purpose is to aggregate data from various VCs and display them in a comprehensible manner as a product passport. +The [EECC Verifier](https://ssi.eecc.de/verifier/) for verifiable credentials provides a verification API as well as the corresponding UI. It's primary purpose is to aggregate data from various VCs and display them in a comprehensible manner as a product passport. [See here for an example.](https://ssi.eecc.de/verifier/#/verify?subjectId=https%3A%2F%2Fid.eecc.de/01/04012345999990/10/20210401-A/21/XYZ-1234) This tool uses the libraries by [Digital Bazaar, Inc.](https://github.com/digitalbazaar), in particular From 5583e6f65066946c1f228b9b9be4551f5000bd58 Mon Sep 17 00:00:00 2001 From: F-Node-Karlsruhe Date: Fri, 3 Feb 2023 16:08:00 +0100 Subject: [PATCH 2/5] allow api to process presentations --- api/src/routers/verify/index.ts | 8 ++++---- api/src/routes/verify/index.ts | 26 +++++++++++++------------- api/src/services/verifier/index.ts | 26 ++++++++++++++++++-------- api/src/types.d.ts | 28 ++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 api/src/types.d.ts diff --git a/api/src/routers/verify/index.ts b/api/src/routers/verify/index.ts index 4851dd7..0aa2a22 100644 --- a/api/src/routers/verify/index.ts +++ b/api/src/routers/verify/index.ts @@ -3,7 +3,7 @@ import { VerifyRoutes } from '../../routes/index.js'; const verifyRoutes = new VerifyRoutes(); -const { verifyCredential, verifyCredentials, verifySubjectsVCs } = verifyRoutes +const { fetchAndVerify, verify, verifySubjectsVCs } = verifyRoutes export const verifyRouter = Router(); @@ -81,7 +81,7 @@ export const verifyRouter = Router(); ] } */ - verifyRouter.get('/vc/:vcid', verifyCredential); +verifyRouter.get('/vc/:vcid', fetchAndVerify); /** * POST /api/verifier/vc @@ -151,7 +151,7 @@ export const verifyRouter = Router(); } ] */ - verifyRouter.post('/vc', verifyCredentials); +verifyRouter.post('/', verify); /** * GET /api/verifier/id/{subjectId} @@ -199,5 +199,5 @@ export const verifyRouter = Router(); } ] */ - verifyRouter.get('/id/:subjectId', verifySubjectsVCs); +verifyRouter.get('/id/:subjectId', verifySubjectsVCs); diff --git a/api/src/routes/verify/index.ts b/api/src/routes/verify/index.ts index 6b1cbda..fcdf100 100644 --- a/api/src/routes/verify/index.ts +++ b/api/src/routes/verify/index.ts @@ -1,14 +1,14 @@ import { NextFunction, Request, response, Response } from 'express'; import { StatusCodes } from 'http-status-codes'; -import { VCVerifier, fetch_json } from '../../services/index.js'; +import { Verifier, fetch_json } from '../../services/index.js'; const VC_REGISTRY = process.env.VC_REGISTRY ? process.env.VC_REGISTRY : 'https://ssi.eecc.de/api/registry/vcs/'; export class VerifyRoutes { - verifyCredential = async (req: Request, res: Response, next: NextFunction): Promise => { + fetchAndVerify = async (req: Request, res: Response, next: NextFunction): Promise => { try { @@ -17,13 +17,13 @@ export class VerifyRoutes { try { - credential = await fetch_json(req.params.vcid); + credential = await fetch_json(req.params.vcid) as Verifiable; - } catch(error) { + } catch (error) { return res.status(StatusCodes.NOT_FOUND); } - const result = await VCVerifier.verifyCredential(credential); + const result = await Verifier.verify(credential); return res.status(StatusCodes.OK).json(result); @@ -33,13 +33,13 @@ export class VerifyRoutes { } - verifyCredentials = async (req: Request, res: Response, next: NextFunction): Promise => { + verify = async (req: Request, res: Response, next: NextFunction): Promise => { try { - let tasks = Promise.all(req.body.map(function(vc: any){ + let tasks = Promise.all(req.body.map(function (verifialbe: Verifiable) { - return VCVerifier.verifyCredential(vc); + return Verifier.verify(verifialbe); })); @@ -59,19 +59,19 @@ export class VerifyRoutes { try { // fetch credentials - let credentials: object; + let credentials: Verifiable[]; try { - credentials = await fetch_json(VC_REGISTRY + encodeURIComponent(req.params.subjectId)); + credentials = await fetch_json(VC_REGISTRY + encodeURIComponent(req.params.subjectId)) as [Verifiable]; - } catch(error) { + } catch (error) { return res.status(StatusCodes.NOT_FOUND); } - let tasks = Promise.all((credentials as [object]).map(function(vc: any){ + let tasks = Promise.all(credentials.map(function (vc) { - return VCVerifier.verifyCredential(vc); + return Verifier.verify(vc); })); diff --git a/api/src/services/verifier/index.ts b/api/src/services/verifier/index.ts index f73465b..45c33dd 100644 --- a/api/src/services/verifier/index.ts +++ b/api/src/services/verifier/index.ts @@ -1,5 +1,5 @@ // @ts-ignore -import { verifyCredential } from '@digitalbazaar/vc'; +import { verifyCredential, verify } from '@digitalbazaar/vc'; // @ts-ignore import { Ed25519Signature2020 } from '@digitalbazaar/ed25519-signature-2020'; // @ts-ignore @@ -7,16 +7,26 @@ import { checkStatus } from '@digitalbazaar/vc-revocation-list'; import { documentLoader } from '../documentLoader/index.js'; -export class VCVerifier { +function getSuite(proof: Proof): unknown { - static async verifyCredential(credential: any): Promise { - - // TODO choose suite based on proofType - const suite = new Ed25519Signature2020(); + // Ed25519Signature2020 is backwards compatible to Ed25519Signature2018 + if (['Ed25519Signature2020', 'Ed25519Signature2018'].includes(proof.type)) return new Ed25519Signature2020(); - const result = await verifyCredential({credential, suite, documentLoader, checkStatus}); + throw new Error(`${proof.type} not implemented`); - return result +} + +export class Verifier { + + static async verify(verifiable: Verifiable): Promise { + + const suite = getSuite(verifiable.proof); + + if (verifiable.type.includes('VerifiableCredential')) return await verifyCredential({ credential: verifiable, suite, documentLoader, checkStatus }); + + if (verifiable.type.includes('VerifiablePresentation')) return await verify({ presentation: verifiable, suite, documentLoader, challenge: verifiable.proof.challenge, checkStatus }); + + throw Error('Provided verifiable object is of unknown type!'); } } \ No newline at end of file diff --git a/api/src/types.d.ts b/api/src/types.d.ts new file mode 100644 index 0000000..6f0502d --- /dev/null +++ b/api/src/types.d.ts @@ -0,0 +1,28 @@ + +type Proof = { + type: string; + challenge: string | undefined; +} + +type Verifiable = { + '@context': (string | any)[]; + type: string[]; + proof: Proof; +} + +type CredentialSubject = { + id: string | URL; +} + +type VerifiableCredential = Verifiable & { + id: URL; + issuer: string | any; + issuanceDate: string; + credentialSubject: CredentialSubject; +} + +type VerifiablePresentation = Verifiable & { + id: URL; + holder: string | any; + verifiableCredential: VerifiableCredential | VerifiableCredential[]; +} \ No newline at end of file From 75bdf41cfd47d14591721687f12fa3774b729fcf Mon Sep 17 00:00:00 2001 From: F-Node-Karlsruhe Date: Tue, 7 Feb 2023 12:08:50 +0100 Subject: [PATCH 3/5] enable presentations in frontend --- frontend/src/store/index.js | 36 ++-- frontend/src/utils.js | 12 +- frontend/src/views/Entry.vue | 116 +++++++------ frontend/src/views/Verify.vue | 298 +++++++++++++++++++++++++--------- 4 files changed, 306 insertions(+), 156 deletions(-) diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 53b2a83..b7d9272 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -3,8 +3,8 @@ import { createStore } from 'vuex' export default createStore({ state: { - version: '0.5.0', - credentials: [], + version: '0.6.0', + verifiables: [], VC_REGISTRY: process.env.VC_REGISTRY || 'https://ssi.eecc.de/api/registry/vcs/', showQRModal: false }, @@ -12,32 +12,20 @@ export default createStore({ showQRModal(state, payload) { state.showQRModal = payload.value }, - addCredential(state, credential) { - state.credentials.push(credential) + addVerifiables(state, verifiables) { + state.verifiables = state.verifiables.concat(verifiables) }, - addCredentials(state, credentials) { - state.credentials = state.credentials.concat(credentials) - }, - setCredentials(state, credentials) { - state.credentials = credentials - }, - resetCredentials(state) { - state.credentials = [] + resetVerifiables(state) { + state.verifiables = []; }, }, - actions: { - addCredential(context, credential) { - this.commit('addCredential', credential) + actions: { + addVerifiables(context, verifiables) { + this.commit('addVerifiables', verifiables) }, - addCredentials(context, credentials) { - this.commit('addCredentials', credentials) - }, - setCredentials(context, credentials) { - this.commit('setCredentials', credentials) + resetVerifiables() { + this.commit('resetVerifiables') }, - resetCredentials() { - this.commit('resetCredentials') - }, - }, + }, modules: {}, }) \ No newline at end of file diff --git a/frontend/src/utils.js b/frontend/src/utils.js index 182fe1b..ba7afbe 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -1,3 +1,7 @@ +export const VerifiableType = { + CREDENTIAL: 'VerifiableCredential', + PRESENTATION: 'VerifiablePresentation' +}; export function isURL(url) { if (typeof url != 'string') return false; @@ -9,9 +13,15 @@ export function getCredentialValue(value) { } export function getPlainCredential(credential) { - var clean_credential = {...credential}; + var clean_credential = { ...credential }; delete clean_credential.verified; delete clean_credential.revoked; delete clean_credential.status; + delete clean_credential.presentation; return clean_credential; } + +export function getVerifiableType(verifiable) { + if (verifiable.type.includes(VerifiableType.PRESENTATION)) return VerifiableType.PRESENTATION; + return VerifiableType.CREDENTIAL; +} diff --git a/frontend/src/views/Entry.vue b/frontend/src/views/Entry.vue index 9a83e7f..fe5287d 100644 --- a/frontend/src/views/Entry.vue +++ b/frontend/src/views/Entry.vue @@ -2,9 +2,11 @@

Credential Selector

- - - + + +

Select the credential/s using one of the options below.

@@ -13,8 +15,11 @@
Credential File
- - + +
Upload a credential in json format
@@ -25,8 +30,12 @@
Credential Id
- - + +
Provide the credential's id
@@ -37,66 +46,67 @@
Subject Id
- - + +
Provide the subject id for which the credentials shall be queried
- +
\ No newline at end of file diff --git a/frontend/src/views/Verify.vue b/frontend/src/views/Verify.vue index 2650610..ecd3d54 100644 --- a/frontend/src/views/Verify.vue +++ b/frontend/src/views/Verify.vue @@ -1,11 +1,14 @@