Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jchartrand committed Jan 7, 2025
1 parent c562d29 commit 1545645
Show file tree
Hide file tree
Showing 15 changed files with 494 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
timeout-minutes: 10
strategy:
matrix:
node-version: [16.x]
node-version: [18.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
Expand Down
19 changes: 19 additions & 0 deletions .knownDidRegistries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const knownDidRegistries = [
{
name: 'DCC Pilot Registry',
url: 'https://digitalcredentials.github.io/issuer-registry/registry.json'
},
{
name: 'DCC Sandbox Registry',
url: 'https://digitalcredentials.github.io/sandbox-registry/registry.json'
},
{
name: 'DCC Community Registry',
url: 'https://digitalcredentials.github.io/community-registry/registry.json'
},
{
name: 'DCC Registry',
url: 'https://digitalcredentials.github.io/dcc-registry/registry.json'
}
]

2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# isomorphic-lib-template Changelog

## 1.0.0 - TBD
## 0.0.1 - TBD

### Added

Expand Down
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022 Digital Credentials Consortium
Copyright (c) 2025 Digital Credentials Consortium

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Example Isomorphic TS/JS Lib Template _(@digitalcredentials/isomorphic-lib-template)_
# verifier-core _(@digitalcredentials/verifier-core)_

[![Build status](https://img.shields.io/github/actions/workflow/status/digitalcredentials/isomorphic-lib-template/main.yml?branch=main)](https://github.com/digitalcredentials/isomorphic-lib-template/actions?query=workflow%3A%22Node.js+CI%22)
[![NPM Version](https://img.shields.io/npm/v/@digitalcredentials/isomorphic-lib-template.svg)](https://npm.im/@digitalcredentials/isomorphic-lib-template)
[![Build status](https://img.shields.io/github/actions/workflow/status/digitalcredentials/verifier-core/main.yml?branch=main)](https://github.com/digitalcredentials/verifier-core/actions?query=workflow%3A%22Node.js+CI%22)
[![NPM Version](https://img.shields.io/npm/v/@digitalcredentials/verifier-core.svg)](https://npm.im/@digitalcredentials/verifier-core)

> A Typescript/Javascript isomorphic library template, for use in the browser, Node.js, and React Native.
> For verifying Verifiable Credentials in the browser, Node.js, and React Native.
## Table of Contents

Expand All @@ -16,31 +16,31 @@

## Background

TBD
The Digital Credentials Consortium has a few applications that verify credentials in essentially the same way, with consequent code duplication. This package extracts that common functionality to a single shared package to make ongoing maintenance easier.

## Security

TBD

## Install

- Node.js 16+ is recommended.
- Node.js 18+ is recommended.

### NPM

To install via NPM:

```
npm install @digitalcredentials/isomorphic-lib-template
npm install @digitalcredentials/verifier-core
```

### Development

To install locally (for development):

```
git clone https://github.com/digitalcredentials/isomorphic-lib-template.git
cd isomorphic-lib-template
git clone https://github.com/digitalcredentials/verifier-core.git
cd verifier-core
npm install
```

Expand All @@ -57,4 +57,4 @@ If editing the Readme, please conform to the

## License

[MIT License](LICENSE.md) © 2022 Digital Credentials Consortium.
[MIT License](LICENSE.md) © 2025 Digital Credentials Consortium.
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@digitalcredentials/isomorphic-lib-template",
"description": "A Typescript/Javascript isomorphic library template, for use in the browser, Node.js, and React Native.",
"name": "@digitalcredentials/verifier-core",
"description": "For verifying Verifiable Credentials in the browser, Node.js, and React Native.",
"version": "0.0.1",
"scripts": {
"build": "npm run clear && tsc -d && tsc -p tsconfig.esm.json",
Expand All @@ -23,6 +23,15 @@
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"dependencies": {
"@digitalbazaar/data-integrity": "^2.5.0",
"@digitalbazaar/eddsa-rdfc-2022-cryptosuite": "^1.2.0",
"@digitalcredentials/ed25519-signature-2020": "^6.0.0",
"@digitalcredentials/issuer-registry-client": "^3.0.0",
"@digitalcredentials/jsonld-signatures": "^12.0.1",
"@digitalcredentials/security-document-loader": "^6.0.1",
"@digitalcredentials/vc": "^9.0.1",
"@digitalcredentials/vc-bitstring-status-list": "^1.0.0",
"@digitalcredentials/vc-status-list": "^9.0.0"
},
"devDependencies": {
"@types/chai": "^4.3.4",
Expand Down
8 changes: 0 additions & 8 deletions src/Example.ts

This file was deleted.

84 changes: 84 additions & 0 deletions src/Verify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// import '@digitalcredentials/data-integrity-rn';

Check failure on line 1 in src/Verify.ts

View workflow job for this annotation

GitHub Actions / test-karma (16.x)

Cannot find module './types/credential' or its corresponding type declarations.

Check failure on line 1 in src/Verify.ts

View workflow job for this annotation

GitHub Actions / test-node (18.x)

Cannot find module './types/credential' or its corresponding type declarations.

Check failure on line 1 in src/Verify.ts

View workflow job for this annotation

GitHub Actions / lint (16.x)

Cannot find module './types/credential' or its corresponding type declarations.
import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020';
import * as vc from '@digitalcredentials/vc';
import { securityLoader } from '@digitalcredentials/security-document-loader';
import { getCredentialStatusChecker } from './credentialStatus';
import { addTrustedIssuersToVerificationResponse } from './issuerRegistries';

import { Credential } from './types/credential';

/*
// the new eddsa-rdfc-2022-cryptosuite
import {DataIntegrityProof} from '@digitalbazaar/data-integrity';
import {cryptosuite as eddsaRdfc2022CryptoSuite} from '@digitalbazaar/eddsa-rdfc-2022-cryptosuite';
const suite = new DataIntegrityProof({
cryptosuite: eddsaRdfc2022CryptoSuite
});
*/

const documentLoader = securityLoader({ fetchRemoteContexts: true }).build();
const suite = new Ed25519Signature2020();

export interface VerificationError {
"message": string,
"isFatal": boolean
}

export interface Step {
"id": string,
"valid": boolean,
"foundInRegistries"?: string[],
}

export interface VerificationResponse {
"verified": boolean,
"isFatal": boolean,
"credential": object,
"errors"?: VerificationError[],
"log"?: Step[]
}

export async function verifyCredential({credential, reloadIssuerRegistry = true}:{credential: Credential, reloadIssuerRegistry: boolean}): Promise<VerificationResponse> {

const fatalErrorMessage = checkForFatalErrors(credential)

if (fatalErrorMessage) return {credential, isFatal: true, verified: false, errors: [{message: fatalErrorMessage, isFatal: true}]}

const verificationResponse = await vc.verifyCredential({
credential,
suite,
documentLoader,
checkStatus: getCredentialStatusChecker(credential)
});

delete verificationResponse.results
delete verificationResponse.statusResult

const { issuer } = credential
await addTrustedIssuersToVerificationResponse({verificationResponse, reloadIssuerRegistry, issuer})
verificationResponse.isFatal = false

return verificationResponse;
}

function checkForFatalErrors(credential: Credential) : string | null {

try {
// eslint-disable-next-line no-new
new URL(credential.id as string);
} catch (e) {
return "The credential's id uses an invalid format. It may have been issued as part of an early pilot. Please contact the issuer to get a replacement."
}

if (!credential.proof) {
return 'This is not a Verifiable Credential - it does not have a digital signature.'
}

return null
}


// import { purposes } from '@digitalcredentials/jsonld-signatures';
// import { VerifiablePresentation, PresentationError } from './types/presentation';
// const presentationPurpose = new purposes.AssertionProofPurpose();
// import { extractCredentialsFrom } from './verifiableObject';
39 changes: 39 additions & 0 deletions src/credentialStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { checkStatus } from '@digitalcredentials/vc-bitstring-status-list';

Check failure on line 1 in src/credentialStatus.ts

View workflow job for this annotation

GitHub Actions / test-karma (16.x)

Cannot find module './types/credential' or its corresponding type declarations.

Check failure on line 1 in src/credentialStatus.ts

View workflow job for this annotation

GitHub Actions / test-karma (16.x)

Parameter 's' implicitly has an 'any' type.

Check failure on line 1 in src/credentialStatus.ts

View workflow job for this annotation

GitHub Actions / test-node (18.x)

Cannot find module './types/credential' or its corresponding type declarations.

Check failure on line 1 in src/credentialStatus.ts

View workflow job for this annotation

GitHub Actions / test-node (18.x)

Parameter 's' implicitly has an 'any' type.

Check failure on line 1 in src/credentialStatus.ts

View workflow job for this annotation

GitHub Actions / lint (16.x)

Cannot find module './types/credential' or its corresponding type declarations.

Check failure on line 1 in src/credentialStatus.ts

View workflow job for this annotation

GitHub Actions / lint (16.x)

Parameter 's' implicitly has an 'any' type.
import { checkStatus as checkStatusLegacy } from '@digitalcredentials/vc-status-list';
import { Credential } from './types/credential';

export enum StatusPurpose {
Revocation = 'revocation',
Suspension = 'suspension'
}

export function getCredentialStatusChecker(credential: Credential) : (() => boolean) | null {
if (!credential.credentialStatus) {
return null;
}
const credentialStatuses = Array.isArray(credential.credentialStatus) ?
credential.credentialStatus :
[credential.credentialStatus];
const [credentialStatus] = credentialStatuses;
switch (credentialStatus.type) {
case 'BitstringStatusListEntry':
return checkStatus;
case 'StatusList2021Entry':
return checkStatusLegacy;
default:
return null;
}
}

export function hasStatusPurpose(
credential: Credential,
statusPurpose: StatusPurpose
) : boolean {
if (!credential.credentialStatus) {
return false;
}
const credentialStatuses = Array.isArray(credential.credentialStatus) ?
credential.credentialStatus :
[credential.credentialStatus];
return credentialStatuses.some(s => s.statusPurpose === statusPurpose);
}
12 changes: 11 additions & 1 deletion src/declarations.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
// declare module 'jsonld'
declare module '@digitalcredentials/did-io';
declare module '@digitalcredentials/did-method-key';
declare module '@digitalcredentials/vc';
declare module '@digitalcredentials/vc-bitstring-status-list';
declare module '@digitalcredentials/vc-status-list';
declare module '@digitalcredentials/vpqr';
declare module '@digitalcredentials/jsonld-signatures';
declare module '@digitalbazaar/data-integrity';
declare module '@digitalbazaar/eddsa-rdfc-2022-cryptosuite';
declare module '@digitalcredentials/ed25519-signature-2020';
declare module '@digitalcredentials/ed25519-verification-key-2020';
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*!
* Copyright (c) 2022 Digital Credentials Consortium. All rights reserved.
*/
export { Example } from './Example'
export { verifyCredential, // verifyPresentation
} from './Verify'
46 changes: 46 additions & 0 deletions src/issuerRegistries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {RegistryClient} from '@digitalcredentials/issuer-registry-client';
import {knownDidRegistries} from '../.knownDidRegistries'
import { VerificationResponse } from './Verify';
const registries = new RegistryClient()
const registryNotYetLoaded = true;
/**
* Checks to see if a VC's issuer appears in any of the known DID registries.
*
* @returns A list of the names of the DID registries in which the issuer appears.
*/

export async function getTrustedRegistryListForIssuer({ issuer, reloadIssuerRegistry = false }: {
issuer: string | any,
reloadIssuerRegistry: boolean | null
}): Promise<string[] | null> {

if (reloadIssuerRegistry ?? registryNotYetLoaded) {
await registries.load({ config: knownDidRegistries })
}
const issuerDid = typeof issuer === 'string' ? issuer : issuer.id;
const issuerInfo = registries.didEntry(issuerDid);
// See if the issuer DID appears in any of the known registries
// If yes, assemble a list of registries in which it appears
return issuerInfo?.inRegistries
? Array.from(issuerInfo.inRegistries).map(r => r.name)
: null;
}

export async function addTrustedIssuersToVerificationResponse( {issuer, reloadIssuerRegistry = false, verificationResponse} :{
issuer: string | any,
reloadIssuerRegistry: boolean | null
verificationResponse: VerificationResponse
}) : Promise<void>
{
const foundInRegistries = await getTrustedRegistryListForIssuer( {issuer, reloadIssuerRegistry});

const registryStep = {
"id": "registered_issuer",
"valid": !!foundInRegistries,
...(foundInRegistries && { foundInRegistries })
};

(verificationResponse.log ??= []).push(registryStep)

}

Loading

0 comments on commit 1545645

Please sign in to comment.