Skip to content

Commit

Permalink
init gs1 chaining verification
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 Jul 22, 2024
1 parent 99ab1e5 commit df97ff2
Show file tree
Hide file tree
Showing 7 changed files with 8,272 additions and 194 deletions.
20 changes: 10 additions & 10 deletions api/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@digitalbazaar/ecdsa-sd-2023-cryptosuite": "^1.0.2",
"@digitalbazaar/ed25519-signature-2018": "^4.0.0",
"@digitalbazaar/ed25519-signature-2020": "^5.2.0",
"@digitalbazaar/vc": "^6.2.0",
"@digitalbazaar/vc": "^6.3.0",
"@digitalbazaar/vc-revocation-list": "^5.0.1",
"@digitalbazaar/vc-status-list": "^7.1.0",
"cors": "^2.8.5",
Expand Down Expand Up @@ -64,4 +64,4 @@
"overrides": {
"jsonld": "$jsonld"
}
}
}
118 changes: 62 additions & 56 deletions api/src/services/documentLoader/index.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,82 @@
// @ts-ignore
import jsonldSignatures from 'jsonld-signatures';
import { getResolver } from './didresolver.js';
import { fetch_jsonld, fetchIPFS } from '../fetch/index.js';
import { contexts } from './context/index.js';
import jsonldSignatures from "jsonld-signatures";
import { getResolver } from "./didresolver.js";
import { fetch_jsonld, fetchIPFS } from "../fetch/index.js";
import { contexts } from "./context/index.js";

const cache = contexts;

const uncachedStatusListCredentialTypes = ['RevocationList2020Credential', 'StatusList2021Credential']

const documentLoader: Promise<any> = jsonldSignatures.extendContextLoader(async (url: string) => {
const uncachedStatusListCredentialTypes = [
"RevocationList2020Credential",
"StatusList2021Credential",
];

const documentLoader: (url: string) => Promise<any> =
jsonldSignatures.extendContextLoader(async (url: string) => {
// Fetch did documents
if (url.startsWith('did:')) {

const [did, verificationMethod] = url.split('#')

// fetch document
const didDocument: any = (await getResolver().resolve(url)).didDocument

// if a verifcation method of the DID document is queried (not yet implemented in the official resolver)
if (verificationMethod && didDocument) {

const verificationMethodDoc: any | undefined = didDocument.verificationMethod.filter(function (method: any) {
return method.id === url || method.id === verificationMethod;
})[0];

if (!verificationMethodDoc)
throw new jsonldSignatures.VerificationError(
new Error(`${verificationMethod} is an unknown verification method for ${did}`)
);

return {
contextUrl: null,
documentUrl: url,
// deliver verification method with the DID doc context
document: Object.assign(verificationMethodDoc, { '@context': verificationMethodDoc['@context'] || didDocument['@context'] }),
};

}
if (url.startsWith("did:")) {
const [did, verificationMethod] = url.split("#");

// fetch document
const didDocument: any = (await getResolver().resolve(url)).didDocument;

// if a verifcation method of the DID document is queried (not yet implemented in the official resolver)
if (verificationMethod && didDocument) {
const verificationMethodDoc: any | undefined =
didDocument.verificationMethod.filter(function (method: any) {
return method.id === url || method.id === verificationMethod;
})[0];

if (!verificationMethodDoc)
throw new jsonldSignatures.VerificationError(
new Error(
`${verificationMethod} is an unknown verification method for ${did}`
)
);

return {
contextUrl: null,
documentUrl: url,
document: didDocument,
contextUrl: null,
documentUrl: url,
// deliver verification method with the DID doc context
document: Object.assign(verificationMethodDoc, {
"@context":
verificationMethodDoc["@context"] || didDocument["@context"],
}),
};
}

return {
contextUrl: null,
documentUrl: url,
document: didDocument,
};
}

let document = cache.get(url);

// fetch if not in cache
if (!document) {

if (url.startsWith('ipfs://')) {

document = await fetchIPFS(url);

} else {

document = await fetch_jsonld(url);

}

if (!document.type || !Array.isArray(document.type) || !uncachedStatusListCredentialTypes.some((t: string) => document.type.includes(t))) cache.set(url, document);

if (url.startsWith("ipfs://")) {
document = await fetchIPFS(url);
} else {
document = await fetch_jsonld(url);
}

if (
!document.type ||
!Array.isArray(document.type) ||
!uncachedStatusListCredentialTypes.some((t: string) =>
document.type.includes(t)
)
)
cache.set(url, document);
}

return {
contextUrl: null,
documentUrl: url,
document: document,
contextUrl: null,
documentUrl: url,
document: document,
};
});

});

export { documentLoader }
export { documentLoader };
60 changes: 60 additions & 0 deletions api/src/services/verifier/gs1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
checkGS1CredentialPresentation,
checkGS1CredentialWithoutPresentation,
externalCredential,
verifyExternalCredential,
gs1RulesResult,
gs1RulesResultContainer,
verificationErrorCode,
VerifiableCredential,
VerifiablePresentation,
// @ts-ignore
} from "@gs1us/vc-verifier-rules";

import { documentLoader } from "../documentLoader/index.js";

export const gs1CredentialTypes = [
"OrganizationDataCredential",
"KeyCredential",
"ProductDataCredential",
];

export const gs1CredentialContext =
"https://ref.gs1.org/gs1/vc/license-context";

export function isGs1Credential(credential: VerifiableCredential): boolean {
return (
credential["@context"].includes(gs1CredentialContext) &&
credential.type.some((type: string) => gs1CredentialTypes.includes(type))
);
}

const getExternalCredential: externalCredential = async (
url: string
): Promise<VerifiableCredential> => {
const extendedVC = await documentLoader(url);
return extendedVC.document;
};

export async function checkGS1Credential(
verifiableCredential: VerifiableCredential,
checkExternalCredential: verifyExternalCredential
): Promise<gs1RulesResult> {
return await checkGS1CredentialWithoutPresentation(
getExternalCredential,
checkExternalCredential,
verifiableCredential
);
}

// Check if the Verifiable Presentation for any GS1 Credential and if so check the GS1 Credential Rules
export async function verifyGS1Credentials(
verifiablePresentation: VerifiablePresentation,
checkExternalCredential: verifyExternalCredential
): Promise<gs1RulesResultContainer> {
return await checkGS1CredentialPresentation(
getExternalCredential,
checkExternalCredential,
verifiablePresentation
);
}
Loading

0 comments on commit df97ff2

Please sign in to comment.