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

feat: w3c revocation using bit string status list for dedicated and multi-tenancy #171

Draft
wants to merge 19 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f10b842
refactor: add patch to credo to handle change in credential format to…
GHkrishna Jul 2, 2024
94fcaba
chore: start w3c revocation controller
GHkrishna Jul 3, 2024
c2cd406
Merge branch 'develop' of https://github.com/credebl/credo-controller…
GHkrishna Jul 3, 2024
a48c58b
feat: able to create statusListCredential
GHkrishna Jul 4, 2024
197ef0d
Merge branch 'develop' of https://github.com/credebl/credo-controller…
GHkrishna Jul 4, 2024
1a8697c
fix: add signing and storing capability of w3c status list credential
GHkrishna Jul 23, 2024
8b1c1c6
feat: implement w3c revoke functionality
Aug 8, 2024
dfc729e
feat: implement index find and updation when sending offer
Aug 9, 2024
a67acf4
feat: implemented w3c revocation with verification
Aug 13, 2024
211e447
feat: implemented w3c revocation for multi-tenancy
Aug 14, 2024
dede0d9
Merge branch 'develop' of https://github.com/credebl/credo-controller…
Aug 14, 2024
32dc113
fix: optimize the bit string credential function
Aug 16, 2024
9572f1e
fix: bug for create bit status string credential
Aug 16, 2024
1f5a098
fix: added the pako package for the compress the bitstring status lis…
Aug 28, 2024
3983dfc
refactor: added revocation notification for dedicated and multi-tenancy
Sep 3, 2024
3f4f66d
fix: revocation notification payload
Sep 3, 2024
f7d0c8c
feat: w3c revocation notification
Sep 4, 2024
1e775c9
Merge branch 'develop' of https://github.com/credebl/credo-controller…
Sep 4, 2024
415b614
refactor: oob revocation credential function
Sep 5, 2024
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
4 changes: 4 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"port": 4001,
"schemaFileServerURL": "https://schema.credebl.id/schemas/"
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@credo-ts/push-notifications": "^0.7.0",
"@credo-ts/question-answer": "0.5.3",
"@credo-ts/tenants": "0.5.3",
"@digitalbazaar/vc-status-list": "^7.1.0",
"@hyperledger/anoncreds-nodejs": "0.2.2",
"@hyperledger/aries-askar-nodejs": "0.2.1",
"@hyperledger/indy-vdr-nodejs": "0.2.2",
Expand Down Expand Up @@ -82,6 +83,7 @@
"@types/jsonwebtoken": "^9.0.5",
"@types/multer": "^1.4.7",
"@types/node": "^18.18.8",
"@types/pako": "^2.0.3",
"@types/ref-array-di": "^1.2.8",
"@types/ref-struct-di": "^1.1.9",
"@types/supertest": "^2.0.12",
Expand Down
174 changes: 174 additions & 0 deletions patches/@credo-ts+core+0.5.3+004+revocable-credential.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
diff --git a/node_modules/@credo-ts/core/build/modules/credentials/formats/jsonld/JsonLdCredentialFormat.d.ts b/node_modules/@credo-ts/core/build/modules/credentials/formats/jsonld/JsonLdCredentialFormat.d.ts
index d12468b..78253b5 100644
--- a/node_modules/@credo-ts/core/build/modules/credentials/formats/jsonld/JsonLdCredentialFormat.d.ts
+++ b/node_modules/@credo-ts/core/build/modules/credentials/formats/jsonld/JsonLdCredentialFormat.d.ts
@@ -11,7 +11,81 @@ export interface JsonCredential {
expirationDate?: string;
credentialSubject: SingleOrArray<JsonObject>;
[key: string]: unknown;
+ credentialStatus?: SingleOrArray<CredentialStatus>
}
+
+type CredentialStatusType = 'BitstringStatusListEntry'
+// The purpose can be anything apart from this as well
+export enum CredentialStatusPurpose {
+ 'revocation' = 'revocation',
+ 'suspension' = 'suspension',
+ 'message' = 'message',
+}
+
+export interface StatusMessage {
+ // a string representing the hexadecimal value of the status prefixed with 0x
+ status: string
+ // a string used by software developers to assist with debugging which SHOULD NOT be displayed to end users
+ message?: string
+ // We can have some key value pairs as well
+ [key: string]: unknown
+}
+/**
+ "credentialStatus": {
+ "id": "https://example.com/credentials/status/8#492847",
+ "type": "BitstringStatusListEntry",
+ "statusPurpose": "message",
+ "statusListIndex": "492847",
+ "statusSize": 2,
+ "statusListCredential": "https://example.com/credentials/status/8",
+ "statusMessage": [
+ {"status":"0x0", "message":"pending_review"},
+ {"status":"0x1", "message":"accepted"},
+ {"status":"0x2", "message":"rejected"},
+ ...
+ ],
+ "statusReference": "https://example.org/status-dictionary/"
+}
+*/
+
+/**
+* "credentialStatus": [{
+ "id": "https://example.com/credentials/status/3#94567",
+ "type": "BitstringStatusListEntry",
+ "statusPurpose": "revocation",
+ "statusListIndex": "94567",
+ "statusListCredential": "https://example.com/credentials/status/3"
+}, {
+ "id": "https://example.com/credentials/status/4#23452",
+ "type": "BitstringStatusListEntry",
+ "statusPurpose": "suspension",
+ "statusListIndex": "23452",
+ "statusListCredential": "https://example.com/credentials/status/4"
+}]
+*/
+
+export interface CredentialStatus {
+ id: string
+ // Since currenlty we are only trying to support 'BitStringStatusListEntry'
+ type: CredentialStatusType
+ statusPurpose: CredentialStatusPurpose
+ // Unique identifier for the specific credential
+ statusListIndex: string
+ // Must be url referencing to a VC of type 'BitstringStatusListCredential'
+ statusListCredential: string
+ // The statusSize indicates the size of the status entry in bits
+ statusSize?: number
+ // Must be preset if statusPurpose is message
+ /**
+ * the length of which MUST equal the number of possible status messages indicated by statusSize
+ * (e.g., statusMessage array MUST have 2 elements if statusSize has 1 bit,
+ * 4 elements if statusSize has 2 bits, 8 elements if statusSize has 3 bits, etc.).
+ */
+ statusMessage?: StatusMessage[]
+ // An implementer MAY include the statusReference property. If present, its value MUST be a URL or an array of URLs [URL] which dereference to material related to the status
+ statusReference?: SingleOrArray<string>
+}
+
/**
* Format for creating a jsonld proposal, offer or request.
*/
diff --git a/node_modules/@credo-ts/core/build/modules/vc/data-integrity/W3cJsonLdCredentialService.js b/node_modules/@credo-ts/core/build/modules/vc/data-integrity/W3cJsonLdCredentialService.js
index 3fa8bf2..f28be5c 100644
--- a/node_modules/@credo-ts/core/build/modules/vc/data-integrity/W3cJsonLdCredentialService.js
+++ b/node_modules/@credo-ts/core/build/modules/vc/data-integrity/W3cJsonLdCredentialService.js
@@ -39,6 +39,7 @@ const jsonld_1 = __importDefault(require("./libraries/jsonld"));
const vc_1 = __importDefault(require("./libraries/vc"));
const models_1 = require("./models");
const W3cJsonLdVerifiablePresentation_1 = require("./models/W3cJsonLdVerifiablePresentation");
+const pako = require('pako');
/**
* Supports signing and verification of credentials according to the [Verifiable Credential Data Model](https://www.w3.org/TR/vc-data-model)
* using [Data Integrity Proof](https://www.w3.org/TR/vc-data-model/#data-integrity-proofs).
@@ -98,10 +99,35 @@ let W3cJsonLdCredentialService = class W3cJsonLdCredentialService {
credential: utils_1.JsonTransformer.toJSON(options.credential),
suite: suites,
documentLoader: this.w3cCredentialsModuleConfig.documentLoader(agentContext),
- checkStatus: ({ credential }) => {
+ checkStatus: async ({ credential }) => {
// Only throw error if credentialStatus is present
if (verifyCredentialStatus && 'credentialStatus' in credential) {
- throw new error_1.CredoError('Verifying credential status for JSON-LD credentials is currently not supported');
+ // throw new error_1.CredoError('Verifying credential status for JSON-LD credentials is currently not supported');
+ // TODO: add logic to verify credentialStatus
+ // throw new CredoError('Verifying credential status for JSON-LD credentials is currently not supported')
+ const credentialStatusURL = credential.credentialStatus.statusListCredential;
+ const bitStringStatusListCredential = await agentContext.config.agentDependencies.fetch(credentialStatusURL, {
+ method: 'GET',
+ });
+
+ if (!bitStringStatusListCredential.ok) {
+ throw new error_1.CredoError(`HTTP error! Status: ${bitStringStatusListCredential.status}`);
+ }
+
+ const bitStringCredential = await bitStringStatusListCredential.json();
+ const encodedBitString = bitStringCredential.credential.credentialSubject.encodedList
+ const compressedBuffer = Uint8Array.from(atob(encodedBitString), (c) => c.charCodeAt(0))
+
+ // Decompress using pako
+ const decodedBitString = pako.ungzip(compressedBuffer, { to: 'string' })
+
+ if (credential.credentialStatus.statusListIndex < 0 || credential.credentialStatus.statusListIndex >= decodedBitString.length) {
+ throw new error_1.CredoError('Index out of bounds');
+ }
+
+ if(decodedBitString[credential.credentialStatus.statusListIndex] === '1'){
+ throw new error_1.CredoError(`Credential at index ${credential.credentialStatus.statusListIndex} is revoked.`);
+ }
}
return {
verified: true,
@@ -219,6 +245,37 @@ let W3cJsonLdCredentialService = class W3cJsonLdCredentialService {
challenge: options.challenge,
domain: options.domain,
documentLoader: this.w3cCredentialsModuleConfig.documentLoader(agentContext),
+ checkStatus: async ({ credential }) => {
+ if ('credentialStatus' in credential) {
+
+ const credentialStatusURL = credential.credentialStatus.statusListCredential;
+ const bitStringStatusListCredential = await agentContext.config.agentDependencies.fetch(credentialStatusURL, {
+ method: 'GET',
+ });
+
+ if (!bitStringStatusListCredential.ok) {
+ throw new error_1.CredoError(`HTTP error! Status: ${bitStringStatusListCredential.status}`);
+ }
+
+ const bitStringCredential = await bitStringStatusListCredential.json();
+ const encodedBitString = bitStringCredential.credential.credentialSubject.encodedList
+ const compressedBuffer = Uint8Array.from(atob(encodedBitString), (c) => c.charCodeAt(0))
+
+ // Decompress using pako
+ const decodedBitString = pako.ungzip(compressedBuffer, { to: 'string' })
+
+ if (credential.credentialStatus.statusListIndex < 0 || credential.credentialStatus.statusListIndex >= decodedBitString.length) {
+ throw new error_1.CredoError('Index out of bounds');
+ }
+
+ if(decodedBitString[credential.credentialStatus.statusListIndex] === '1'){
+ throw new error_1.CredoError(`Credential at index ${credential.credentialStatus.statusListIndex} is revoked.`);
+ }
+ }
+ return {
+ verified: true,
+ }
+ },
};
// this is a hack because vcjs throws if purpose is passed as undefined or null
if (options.purpose) {
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
diff --git a/node_modules/@credo-ts/core/build/modules/credentials/formats/jsonld/JsonLdCredentialFormat.d.ts b/node_modules/@credo-ts/core/build/modules/credentials/formats/jsonld/JsonLdCredentialFormat.d.ts
index d12468b..ae70f36 100644
index 78253b5..0b3dd52 100644
--- a/node_modules/@credo-ts/core/build/modules/credentials/formats/jsonld/JsonLdCredentialFormat.d.ts
+++ b/node_modules/@credo-ts/core/build/modules/credentials/formats/jsonld/JsonLdCredentialFormat.d.ts
@@ -10,6 +10,8 @@ export interface JsonCredential {
issuanceDate: string;
expirationDate?: string;
@@ -12,6 +12,8 @@ export interface JsonCredential {
credentialSubject: SingleOrArray<JsonObject>;
[key: string]: unknown;
credentialStatus?: SingleOrArray<CredentialStatus>
+ //TODO change type
+ prettyVc?: any;
[key: string]: unknown;
}
/**

type CredentialStatusType = 'BitstringStatusListEntry'
Loading