Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Dive into cheqd's product and identity functionality
cheqd is a purpose-built network for decentralised identity. This documentation site provides technical and product information for all identity features & functionality on the cheqd network.
cheqd maintains an array of packages with varying levels of integration complexity to allow its partners and customers to have a variety of ways of plugging into cheqd's identity functionality. Via these different packages, customers and partners can issue and verify Verifiable Credentials, create cheqd DIDs, DID-Linked Resources, Status Lists and Schemas with different levels of integration effort and flexibility.
There are three core ways of integrating and building with cheqd:
cheqd's identity functionality is fully standards compliant, ensuring interoperability and no vendor lock-in. cheqd's tooling and different product offerings offer a variety of building blocks for any Trusted Data Market.
If you want to utilise cheqd DIDs or DID-Linked Resources within applications without a specific cheqd integration, you can incorporate a Universal Registrar or Universal Resolver driver to support did:cheqd alongside other commonly adopted DID methods.
Credential Service is the easiest route to get started with cheqd's identity functionality, or for testing with very low integration effort. Using simple REST APIs, it is possible to integrate Credential Service in a few lines of code, or issue Credentials within a few clicks.
Under the hood, Credential Service utilises the Veramo SDK cheqd Plugin, providing the most feature complete set of functionality and tooling.
If you'd rather build a deeper integration using a Software Development Kit (SDK) or lower level package, we've created a simple diagram to show how our packages are structured below.
One of cheqd's primary motives is to make itself accessible to the widest set of identity applications possible. To accomplish this, cheqd has built a flexible set of packages and tooling to accommodate its identity capabilities into a broad set of external SDKs and applications.
These can be represented through the visual below:
The cheqd Community Slack is our primary chat channel for the open-source community, software developers, and node operators.
Please reach out to us there for discussions, help, and feedback on the project.
Issue Credentials and Presentations
Fully W3C VC Data Model conformant Verifiable Credentials for establishing trust and demonstrating decentralised reputation. Supporting JSON, JSON-LD and AnonCreds.
Charge for Credentials
Setup encrypted Status Lists and other Resources with Payment Conditions to unlock, allowing issuers to set a price for verifying a Credential Status.
Create Decentralised Identifiers (DIDs)
Fully W3C DID Core conformant Digital identifiers for establishing a root of trust in a given ecosystem. Utilising cheqd's DID method (did:cheqd).
Create Status Lists on-ledger
Sophisticated and first-of-its-kind cryptographically verifiable on-ledger files for establishing Trust and Reputability in a Verifiable Credential, utilising DID-Linked Resources.
Create DID-Linked Resources
Digital resources, leveraging the cryptographic verifiability of DIDs and patterns of DID Core to anchor schemas, trust registries, status lists and more.
DID Registrar (and Universal Registrar Driver)
Low complexity
Simple setup for building cheqd DIDs into existing applications using REST APIs, building into the Universal Registrar.
DID Resolver (and Universal Resolver Driver)
Low complexity
Service for resolving cheqd DIDs and DID URLs. Feature complete with query-based DID URL dereferencing. Full integration and driver within the Universal Resolver.
🟢 Get started with Credential Service
Click here to start your journey with Credential Service, create your account and begin issuing Credentials.
Understanding cheqd's Credentials-as-a-Service product offering
The Credential Service is a set of REST APIs for using cheqd's identity functionality in a lightweight and highly efficient way.
With these APIs, it simplifies the developer experience, helping customers build Trusted Data Markets from the ground up, with zero prior knowledge of the technology under the hood. All of cheqd’s existing open-source libraries remain available, and the Credential Service does not necessitate developers to switch their SSI stack in their entirety, but allows them to build into their existing tooling, for example alongside APIs such as the Universal Resolver.
The Credential Service directly leverages our Veramo SDK Plugin, making a wide array of features available from launch, including:
With Credential Service, there are multiple ways it can be deployed and hosted to support clients with different requirements.
This mode is the most simple for users, allowing cheqd to custody both Cosmos AND Identity keys in Veramo KMS. This means that manages both ledger-writes and signing identity transactions on behalf of the customer.
To ensure this is highly secure, we have deployed an instance of a Veramo Key Management Store (KMS) which uses a Postgress DB (TypeOrm) to store Cosmos AND identity keys in one encrypted table, so it cannot be read in plaintext. This design allows us to segment different customers' keys securely and efficiently.
We use similar techniques to Password Managers such as 1Password and Bitwarden to ensure that even if the database were to be compromised, the keys would remain encrypted and unusable.
Within Custodian mode, we also enable clients to toggle
Client-managed mode gives the Credential Service user the ability to utilise their own identity keys for signing identity transactions, while still allowing the Credential Service to manage the CHEQ account keys for writing to the cheqd network. This mode is intended to be used for more production environments where the user signs each identity transaction independently, affording a greater level of security and control to the client.
Full client-managed mode is still in development and we will update this documentation as and when it becomes available
Under the hood, the Credential Service leverages our Veramo SDK Plugin for its identity functionality. Check out our guide on supported SDKs to understand how Credential Service fits together with our other Open Source packages.
Below are a list of alternatives for integrating with cheqd. Each offers a different set of protocols and underlying technical capabilities.
Learn how to set up your account on Credential Service.
The user is required to Log In to the Credential Service and authenticate in order to access the APIs. This guards the API from unauthorized access and is required for both testing production environments.
The following API can be used to fetch the new account information:
customer_id
is used as an identifier for the particular customer using the Credential Service. It is generated as a sub-field of the JWT token used in the authorization header.
cheqd_account
is used to pay for identity transactions on either testnet
or mainnet
. A cheqd account is automatically generated when a new customer_id
is generated.
Users will need to add our token, CHEQ, to their cheqd_account
on mainnet
in order to be able to use the ledger-based identity functionality on Credential Service, such as creating DIDs and DID-Linked Resources.
If you need to add CHEQ tokens to your Credential Service cheqd_account
, there are a few steps you need to follow:
Once you have successfully created an account and have topped up your CHEQ tokens, you are ready to get started!
Learn how to issue and manage Verifiable Credentials and Presentations.
Verifiable Credentials are a tamper-evident data format for asserting a set of claims about a subject. You can issue and verify Verifiable Credentials and Presentations without building complex integrations, using our simple Credential Service APIs.
Below are a list of alternatives for using Credentials with cheqd support. Each offers a different set of protocols and underlying technical capabilities.
Category | Feature | Status |
---|---|---|
Head to our and click Log In to get started.
Credential Service uses a to handle user authentication and login. This allows users to create new accounts as well as sign in using their email, Google single sign-on, or Discord login.
First you need to which is able to hold CHEQ tokens. We recommend using which natively supports all CHEQ transactions in a browser plugin or on mobile. Alternatively, follow the .
You will then need to .
This is super simple. You can add free CHEQ tokens to your cheqd_account by inputting your cheqd account address. Access the .
Learn about Verifiable Credentials and Presentations
If you want to learn more about what
Make sure you've , then you can start to:
Credential Service supports two major digital Credential types and uses our under the hood. Below you can learn about these Credential formats:
Verifiable Credentials (VCs)
Issue Credential
✅
Verify Credential
✅
Revoke Credential
✅
Suspend Credential
✅
Unsuspend Credential
✅
Verifiable Presentations (VPs)
Verify Presentation
✅
Credential Payments
Create payment-gated resource
✅
Update payment-gated resource
✅
Pay-to-verify credential status
✅
Decentralised Identifiers (DIDs)
Create DID and DID Document
✅
Update DID Document
✅
Resolve DID
✅
Deactivate DID
✅
List DIDs
✅
Identity keys
Create identity keys
✅
Fetch identity keys
✅
Status Lists
Create status list
✅
Publish status list
✅
Update status list
✅
Check status list
✅
Search status lists
✅
DID-Linked Resources (DLRs)
Create DID-Linked Resource
✅
Search DID-Linked Resources
✅
Account
Create new account
✅
Fetch account details
✅
Sign in / Sign up
Head to our Credential Service and click Log In to create an account and get started.
Issue a Credential
Issue W3C conformant Verifiable Credentials easily over REST API.
Advanced config options
Run the Credential Service yourself or utilise your own external database.
Veramo
The Veramo SDK Plugin is an extension of the Veramo SDK, a JavaScript framework for Trusted Data, adding support for cheqd functionality.
Credo
Credo is an SDK which supports ZKCreds (AnonCreds) and regular Verifiable Credentials natively with cheqd support.
Walt.id SSI Kit
Walt.id SSI Kit is an SDK that supports the European Architecture and Reference Framework (ARF) standards for identity, with full cheqd support.
Developer guide for running the Credential Service
If you want to run the application without any external databases or dependent services, we provide a Docker Compose file to spin up a standalone service.
This standalone service uses an in-memory database with no persistence, and therefore is recommended only if you're managing key/secret storage separately.
The no-db.env
file in the same folder contains all the environment variables necessary to configure the service. (See section Configuration above.)
Construct the postgres URL and configure the env variables mentioned above.
Spinning up a Docker container from the pre-built credential-service Docker image on Github is as simple as the command below:
Configure the environment variables in the postgres.env
file:
POSTGRES_USER
: Username for Postgres database
POSTGRES_PASSWORD
: Password for Postgres database
POSTGRES_MULTIPLE_DATABASES
: Database names for multiple databases in the same cluster, e.g.: "app,logto"
. This sets up multiple databases in the same cluster, which can be used independently for External Veramo KMS or LogTo service.
Then, make the Postgres initialisation scripts executable:
Configure the environment variables in the logto.env
file with the settings described in section above.
Then, run the LogTo service to configure the LogTo application API resources, applications, sign-in experiences, roles etc using Docker Compose:
Configuring LogTo is outside the scope of this guide, and we recommend reading LogTo documentation to familiarise yourself.
Configure the environment variables in the with-db.env
file with the settings described in section above. Depending on whether you are using external Veramo KMS only, LogTo only, or both you will need to have previously provisioned these services as there are environment variables in this file that originate from Postgres/LogTo.
Then, start the service using Docker Compose:
When upgrading either the external Veramo KMS or LogTo, you might need to run migrations for the underlying databases.
You can run just the migration scripts using Docker Compose profiles defined in the Compose file.
For example, to run Credential Service app migrations on an existing Postgres database (for external Veramo KMS):
Or to run LogTo migrations on an existing Postgres database:
To build your own image using Docker, use the Dockerfile provided.
Setup your wallet to receive credentials
Credential Service currently is setup to work with the Verida Wallet. In 2024, we will be building compatibility with a full suite of other digital identity wallets.
On the "Profile" tab, you will see your did:vda
address under the section "DID".
For example: "did:vda:testnet:0xD7477C4a75143Af16A967381d09650A533Bd0DD7"
Credentials stored with the credential schema will automatically be rendered in the Verida Wallet as a credential. This custom display includes:
A scannable QR code
The profile icon of the Verida DID that issued / signed the credential
A tick of approval indicating the credential has been verified
Issue conformant W3C Verifiable Credentials over REST API
Using the /credential/create
API, it is possible to issue Verifiable Credentials, signed by a cheqd DID, in a few clicks or lines of code.
Make sure you have set up your account with Credential Service and are logged in, using our guide below:
Before you can issue a Verifiable Credential, you need to create an Issuer DID which is used to sign the Credential payload. Use the API in the page below to create an Issuer DID:
Again, before you issue a Verifiable Credential, you need to know to whom you are issuing it. If you need to create a Subject DID, you can take a look at the page here:
Within the JSON object of the API request, you will need to input the issuer
and subject
information, as well as the attributes
which you want to issue in the Credential. You may also want to add additional fields such as a credentialSchema
.
Users have two options for compiling the Credential bodies and issuing Verifiable Credentials:
Filling out a simple form using the application/x-www-url-form-encoded
option on the Swagger UI.
Compiling a Credential body yourself using the application/json
option on the Swagger UI.
This is the easiest way to issue Credentials and is recommended for users who are not overly familiar with compiling JSON objects.
Using the application/x-www-url-form-encoded
option on the Swagger UI, users are able to choose between the following variables and options to issue Verifiable Credentials:
Below are a set of examples of alternative input parameters for users to specify the bitstring index of the issued Credential. The bitstring index is where exactly the issued credential will map to within the Status List. This should be noted and stored by the issuer to keep a record of which issued credentials are active, revoked or suspended:
Ensure that the "statusPurpose"
and "statusListName"
is the same as the existing Status List on-ledger.
Instead of using simple form variables, you can issue a Verifiable Credential using a JSON payload with the application/json
option on the Swagger UI.
Below is an example of the request format for issuing a Verifiable Credential using a custom JSON payload, including some of the possible parameters:
Execute the API below to issue a Verifiable Credential, signed by your issuer DID.
Below are a list of alternatives for using Credentials with cheqd support. Each offers a different set of protocols and underlying technical capabilities.
t
Verify a Credential using Credential Service
Once you have issued your credential and have a JWT as part of the credential proof, you can use the /credential/verify
API to check that the JWT has not been tampered.
To verify a Credential, you can either pass the full Credential body or the JWT proof. These can be either obtained from a Credential that has been issued or from a Verifiable Presentation presented to the user.
The user is able to set verification parameters to filter whether they want to verify certain aspects of a Credential, including:
Simply paste the JWT or the full credential body into the request field of the /credential/verify
API, and the API will give you a response including the following verification policies:
Whether the Credential has been tampered
Whether the Credential has a valid issuance date
Whether the Credential has expired
Whether the Credential Status is valid
A Verifiable Presentation is a collection of multiple Verifiable Credentials that are being presented by a holder
to a verifier
. In addition to checking whether the Credentials are untampered, Verifiable Presentation verification also checks that the holder
subject DID is valid.
To verify a Credential, you can either pass the full VP-JWT string or a JSON object. These can be either obtained from a Verifiable Presentation presented to the user.
The user is able to set verification parameters to filter whether they want to verify certain aspects of a Presentation, including:
Use the API below to verify a Presentation
Users are also able to suspend Verifiable Credentials. The difference between revocation and suspension is that suspended Credentials may be unsuspended at a future date; whereas, revoked credentials are permanently revoked.
It is best practice for issuers to keep a record of the Credentials they have issued, including the "statusListIndex
" of the Credentials. From this record system, issuers should be able to fetch either the full Credential Body or the JWT proof of the Credential they want to suspend.
When suspending a Credential, issuers can decide whether they want to publish an updated Status List on-ledger, with the suspended credential index updated in the bitstring. The parameter below can be changed to reflect this:
Paste the Credential Body or JWT into the API below and execute the API to suspend the Credential.
If a Credential has been suspended, and an Issuer wants to unsuspend the Credential to make it once again valid, the Issuer can reinstate a suspended Credential.
It is best practice for issuers to keep a record of the Credentials they have issued, including the "statusListIndex
" of the Credentials. From this record system, issuers should be able to fetch either the full Credential Body or the JWT proof of the Credential they want to unsuspend.
When unsuspending or reinstating a Credential, issuers can decide whether they want to publish an updated Status List on-ledger, with the unsuspended credential index updated in the bitstring. The parameter below can be changed to reflect this:
Paste the Credential Body or JWT into the API below and execute the API to unsuspend the Credential.
Understand how to issue a Verifiable Credential including an encrypted Status List in the body.
Issuers are able to add encrypted Status Lists to the body of the Credential if they have previously created an Encrypted Status List on-ledger.
Make sure you have set up your account with Credential Service and are logged in, using our guide below:
Before you can create an encrypted Status List for charging for Credentials, you need to create a DID which is used to link the Status List on-ledger. Use the API in the page below to create a DID:
Follow the tutorial here to create an encrypted Status List with a set of Payment Conditions to unlock:
Follow the instructions within the /credential/create
API below to format and issue a Verifiable Credential.
Using cheqd's innovative DID-Linked Resource module, cheqd is able to support decentralized and scalable Verifiable Credential revocation and suspension. Using this API, the user is able to choose whether they would like to publish the revocation status to the cheqd ledger or elsewhere.
It is best practice for issuers to keep a record of the Credentials they have issued, including the "statusListIndex
" of the Credentials. From this record system, issuers should be able to fetch either the full Credential Body or the JWT proof of the Credential they want to revoke.
When revoking a Credential, issuers can decide whether they want to publish an updated Status List on-ledger, with the revoked credential index updated in the bitstring. The parameter below can be changed to reflect this:
Paste the Credential Body or JWT into the API below and execute the API to revoke the Credential.
Credential Payments brings a significant evolution to the Verifiable Credentials landscape, allowing verifiers to directly pay issuers to unlock Credential Status information. Underneath the hood, we've engineered a robust and secure payment flow that streamlines the end-to-end payment process, with accuracy, speed, and cryptographic integrity.
Create encrypted Status Lists on-ledger, and pay to unlock the Access Control Conditions in CHEQ, using our Credential Payments APIs:
Build your understanding of How Credential Payments work, including Access Control Conditions and how the model preserves privacy.
Below are a list of alternatives for using Credential Payments.
Creating an encrypted Status List 2021 Resource using Credential Service
To create an encrypted Verifiable Credential Status List v2021 with a set of Access Control Conditions, an Issuer will need to follow the steps below:
Make sure you have set up your account with Credential Service and are logged in, using our guide below:
Before you can create an encrypted Status List for charging for Credentials, you need to create a DID which is used to link the Status List on-ledger. Use the API in the page below to create a DID:
Using the /credential-status/create/encrypted
API, users have two options for creating an encrypted Status List on-ledger:
Filling out a simple form using the application/x-www-url-form-encoded
option on the Swagger UI.
Compiling a Status List payload yourself using the application/json
option on the Swagger UI.
This is the easiest way to create encrypted Status Lists on cheqd and is recommended for users who are not overly familiar with compiling JSON objects.
Using the application/x-www-url-form-encoded
option on the Swagger UI, users are able to choose between the following variables and options to create an encrypted Status List on-ledger:
From this request, the Credential Service will automatically create and publish an encrypted Status List to the ledger with set Payment Conditions required to be met to unlock.
Instead of using simple form variables, you can create an encrypted Status List using a JSON payload yourself using the application/json
option on the Swagger UI.
An example of the JSON payload needed to be submitted is below:
The table below expands on some of the required parameters:
Once the Issuer has populated the requisite information for the encrypted Status List request, they can use the API below to submit it to the ledger.
The following code snippet shows an example of an encrypted Status List response format, which will be published to the ledger:
Credo is an SDK which and regular Verifiable Credentials natively with cheqd support.
Walt.id SSI Kit is an SDK that supports the standards for identity, with full cheqd support.
Ensure that the "statusListName
" and "statusPurpose
" are the same as the Status List . This makes sure that if the Credential Status is changed, for example, if it is revoked or suspended, the correct Status List will be updated.
When , a user will have the following options:
For the purpose of this tutorial, we will assume the user is creating an encrypted Status List. For unencrypted Status Lists, .
Enter the Decentralized Identifier (DID) of the Status List publisher . For example:
Parameter | Example value | Description |
---|
Note: it is important to save the response, including the "encryptedSymmetricKey
" locally, as this will be used for .
Note: The only encrypted element is the "encodedList
" element. This provides the Verifier sufficient information to be able to make the payment back the the Issuer and to fulfill the , without being able to see the contents of the Status List itself.
Set up your account
Set up your account with cheqd Credential Service and log in to start using the APIs.
Create an Issuer DID
Create a W3C conformant DID on cheqd using the did:cheqd
DID Method.
Create a Subject DID
Create an off-ledger did:key
or did:vda
Subject DID to receive a Verifiable Credential.
Setup Verida Wallet
Learn about setting up your Verida wallet to receive a did:vda
address.
Veramo SDK Plugin
The Veramo SDK Plugin is an extension of the Veramo SDK, a JavaScript framework for Trusted Data, adding support for cheqd functionality.
Credo
Credo is an SDK which supports ZKCreds (AnonCreds) and regular Verifiable Credentials natively with cheqd support.
Walt.id SSI Kit
Walt.id SSI Kit is an SDK that supports the European Architecture and Reference Framework (ARF) standards for identity, with full cheqd support.
|
| This specifies the cheqd address to which the payment fee should be sent. This address is associated with the User who wants to charge for Credential Status |
|
| This defines the amount of the payment fee in CHEQ which the Issuer will charge for a third party to unlock the Credential Status.
The amount may be up to 2 decimal points, e.g. " |
| " | The amount of time, in minutes, after making the payment in which a Verifier is able to unlock an encrypted resource. |
The /credential-status/update/encrypted
API enables users to update the indices of a Status List or rotate the encryption keys. This may be useful for revoking Credentials in bulk, rather than submitting individual /credential/revoke
requests.
When a new encrypted Status List resource is published, this will also encrypt the latest version with a new set of encryption keys. This may therefore be used to rotate encryption keys, even if the listed indices are kept the same.
Create DIDs and identity keys using cheqd's DID Method (did:cheqd)
A Decentralized Identifier "DID" is a globally unique identifier that does not require a centralized registration authority because it is registered with distributed ledger technology or other form of decentralized network.
Learn about DIDs If you want to learn about what DIDs are, please go over to our learning site here.
On-ledger DIDs created using the Credential Service use the cheqd DID Method. This is fully defined below:
Below are a list of alternatives for creating cheqd DIDs.
How a Verifier pays an Issuer to decrypt an encrypted Status List
Credential Service supports payments for verifying Credential Status. This is an innovative feature that is also commonly known as cheqd's Payment Rails. Using the API in this tutorial, there are multiple ways for a Verifier to pay an Issuer to unlock and verify a Credential's status.
A Verifier will need a Credential Service account to take advantage of the /credential-status/check
API and easily use cheqd's Credential Payments. Make sure you are set up and are logged in, using our guide below:
Using the /credential-status/check
API, users have two options for checking whether a particular Credential index is revoked or suspended:
Filling out a simple form using the application/x-www-url-form-encoded
option on the Swagger UI.
Compiling the JSON transaction yourself using the application/json
option on the Swagger UI.
This is the easiest way to check whether a particular credential index is revoked or suspended.
Using the application/x-www-url-form-encoded
option on the Swagger UI, users are able to choose between the following variables to compile your DID:
To automatically make a payment to an Issuer in order to verify an encrypted Status List, there is an additional variable:
If there is sufficient CHEQ in the account of the Verifier, this will automatically make a payment to the Issuer and meet the Access Control Conditions.
In the same action, the Credential Service will perform a verification check on the Credential Status and pay the issuer the fee specified in the Payment Conditions.
The response format below will indicate clearly whether the check is successful and whether the Credential index in question is revoked / suspended or not.
If a Verifier does not want to automatically pay the Issuer using the API, they can choose to make a manual payment to unlock the Credential Status information to build a higher level of trust within the Credential presented to them.
If a Verifier wants to unlock access to the Resource, to gain access to additional information about a Credential presented to them, such as the Credential Status, firstly, the Verifier will be presented Credential, including a link to the Status List within the "credentialStatus"
section of the Credential body.
Through following the link in"credentialStatus"
section of the Credential body. the The Verifier will be directed to an on-ledger Resource, identifiable through a DID URL, for example:
This on-ledger Resource will contain:
An encrypted potion of the Resource, such as a Status List bitstring. identified by the "encodedList"
property.
Unencrypted metadata about the Resource, including the issuers' payment address "feePayerAddress"
and and the Payment Conditions, "feePaymentAmount"
and "intervalInSeconds"
.
This gives the verifier requisite information they need in order to pay the Issuer to unlock the Credential Status. You can learn more about Access Control Conditions below.
Using one of cheqd's supported wallets, Verifiers can make a payment of the amount specified in the "feePaymentAmount"
to the "feePayerAddress"
.
This payment should be made in CHEQ.
Note that the "feePaymentAmount"
may be specified in ncheq. This is lowest denomination of the CHEQ token, "nano" CHEQ which is 1 x 10^-9 CHEQ.
The Credential Service will perform a verification check on the Credential Status and pay the issuer the fee specified in the Payment Conditions.
Note the "intervalInSeconds
" which is the amount of time after making the payment that the Verifier has to hit the API and request access to the encrypted Status List.
The response format below will indicate clearly whether the check is successful and whether the Credential index in question is revoked / suspended or not.
Alternatively, if Verifiers have made the payment manually they can also use the /credential/verify API in the tutorial below:
Create a DID using the did:cheqd method
To create a cheqd DID (did:cheqd
) and associated DID Document there are two ways of building the payload for the request:
Make sure you have set up your account with Credential Service and are logged in, using our guide below:
Using the /did/create
API, users have two options for creating a did:cheqd
DID and associated DID Document on-ledger:
Filling out a simple form using the application/x-www-url-form-encoded
option on the Swagger UI
Compiling a DID Document body yourself using the application/json
option on the Swagger UI
This is the easiest way to create DIDs on cheqd and is recommended for users who are not overly familiar with compiling DID Documents.
Using the application/x-www-url-form-encoded
option on the Swagger UI, users are able to choose between the following variables to compile your DID:
From this request, the Credential Service will automatically create and publish a DID and associated DID Document to the ledger and return it as a response.
Within the /did/create
JSON payload, paste the response of your DID Document template, with your own signing keys.
Request format:
Hit execute on the API below to create your did:cheqd
DID and associated DID Document.
After creating a DID or multiple DIDs, users can list all the created DIDs associated with their account. Using the /did/list
API.
Instead of generating a DID Document using simple parameters, you can create a fully formatted DID Document yourself. Before, submitting a manually created DID, you will need to have to input the key material into the DID document.
Use the to generate a new keypair within the Credential Service key management store. Copy the "publicKeyHex".
To simplify this process of formatting a DID Document using your own keys, we've created a . Simply paste in your publicKeyHex and choose the variables to compile your DID Document template.
Verify Credential
Verify a W3C Verifiable Credential using cheqd's Credential Service APIs.
Create Issuer DID
Create an Issuer DID using the did:cheqd DID method over REST API.
Create Subject DID
Create an off-ledger Subject DID using the did:key
or did:vda
DID methods.
Resolve DID
Resolve a DID to retrieve the associated DID Document.
DID Registrar
Simple setup for building cheqd DIDs into existing applications using REST APIs, building into the Universal Registrar.
Veramo
The Veramo SDK Plugin is an extension of the Veramo SDK, a JavaScript framework for Trusted Data, adding support for cheqd functionality.
Credo
Credo is an SDK which supports ZKCreds (AnonCreds) and regular Verifiable Credentials natively with cheqd support.
Walt.id SSI Kit
Walt.id SSI Kit is an SDK that supports the European Architecture and Reference Framework (ARF) standards for identity, with full cheqd support.
cheqd Cosmos CLI
Cosmos CLI which directly communicates with the cheqd network. This should only be used for testing environments.
Set up your account
Set up your account with cheqd Credential Service and log in to start using the APIs.
Understanding Access Control Conditions
Learn what different Payment Conditions mean and how they affect a Verifier when verifying Credentials.
Create Status List 2021 Resource on cheqd.
Users are able to create Verifiable Credential Status List v2021 entries on-ledger, in order to revoke or suspend Verifiable Credentials. This is a derivation from the core spec made by cheqd to support a more decentralized and resilient approach to storing Status Lists.
Make sure you have set up your account with Credential Service and are logged in, using our guide below:
Before you can create a Status List, you need to create a DID which is used to link the Status List on-ledger. Use the API in the page below to create a DID:
When creating a Status List, a user will have the following options:
For the purpose of this tutorial, we will assume the user is creating an unencrypted Status List. For encrypted Status Lists, follow the tutorial here.
Using the /credential-status/create/unencrypted
API, users have two options for creating an encrypted Status List on-ledger:
Filling out a simple form using the application/x-www-url-form-encoded
option on the Swagger UI.
Compiling a Status List payload yourself using the application/json
option on the Swagger UI.
This is the easiest way to create unencrypted Status Lists on cheqd and is recommended for users who are not overly familiar with compiling JSON objects.
Using the application/x-www-url-form-encoded
option on the Swagger UI, users are able to choose between the following variables and options to create an unencrypted Status List on-ledger:
Instead of using simple form variables, you can create an encrypted Status List using a JSON payload yourself using the application/json
option on the Swagger UI.
An example of the JSON payload needed to be submitted is below:
Once the Issuer has populated the requisite information for the unencrypted Status List request, they can use the API below to submit it to the ledger.
Create a Verifiable Credential Status List v2021 on-ledger
Credential Status Lists are on-ledger objects which can be used to mathematically derive whether an issued Credential has been revoked, suspended or is still valid.
The Status List 2021 Specification utilises bitstrings to represent whether a Verifiable Credential has been suspended/revoked or not. A bitstring can be thought of as a long list of 1s and 0s, where, if the binary value of the position in the list is 1 (one), the verifiable credential is revoked, if it is 0 (zero) it is not revoked.
Figure 1: Graphic showing the StatusList2021 bitstring
Each issued Credential correlates with a position and index on the bitstring, so that a verifier will be able to correlate the value within the Credential against the public bitstring to ascertain whether the Credential has been revoked or not, using a validate algorithm as well as a bitstring expansion algorithm.
The issuer keeps a bitstring list of all Verifiable Credentials it has issued. The StatusList is usually published by the issuer in the format of its own Verifiable Credential. This Verifiable Credential is generally hosted publicly on a centralised server or domain to enable third-party read-access.
cheqd stores each Status List and subsequent entries on-ledger as DID-Linked Resource versions. This has notable benefits, including the provenance, legitimacy and security of the Status List. For a full list of benefits, see the context for creating DID-Linked Resources.
Below are a list of alternatives for creating cheqd Status Lists.
t
Resolve a DID to fetch the associated DID Documet
A user is able to input a DID (string) as a request format and resolve the DID to fetch the associated DID Document, DID Resolution Metadata and DID Document metadata.
Issuers may want to create identity keypairs for multiple reasons, such as for signing payloads or for creating did:key
DIDs.
There is also an option to fetch an identity keypair by inputting a Key ID (kid) as a request format.
Credential Service currently supports two types of subject
DIDs:
did:key
did:vda
With the former, you can follow the did:key specification to create a subject DID based on a generated keypair.
With the latter, you can setup your did:vda subject DID on your Verida wallet. Using the Credential Service, you will be able to send credentials to your Verida wallet and use it to store and securely back them up.
Update indices in Status List
The /credential-status/update/unencrypted
API enables users to update the indices of a Status List. This may be useful for revoking Credentials in bulk, rather than submitting individual /credential/revoke
requests.
Querying Status List entries or indices
Using the /credential-status/check
API, users are able to query specific Credential indices within a Status List to ascertain whether the Credential is revoked, suspended or currently valid.
Using the /credential-status/check
API, users have two options for checking whether a particular Credential index is revoked or suspended:
Filling out a simple form using the application/x-www-url-form-encoded
option on the Swagger UI.
Compiling a DID Document body yourself using the application/json
option on the Swagger UI.
This is the easiest way to check whether a particular credential index is revoked or suspended.
Using the application/x-www-url-form-encoded
option on the Swagger UI, users are able to choose between the following variables to compile your DID:
To automatically make a payment to an Issuer in order to verify an encrypted Status List, follow the tutorial here:
Instead of using simple parameters, users can submit a JSON payload to the same effect using the application/json
option on the Swagger UI. For example:
Execute the API request using the API below:
Set up your account
Set up your account with cheqd Credential Service and log in to start using the APIs.
Create an Issuer DID
Create a W3C conformant DID on cheqd using the did:cheqd
DID Method.
Create Status List
Create an on-ledger Verifiable Credential Status List v2021 over REST API.
Update Status List
Update an on-ledger Verifiable Credential Status List v2021 over REST API.
Check Status List
Check an on-ledger Verifiable Credential Status List v2021 to determine whether a particular Credential is revoked or suspended.
DID Registrar
Simple setup for building cheqd DIDs into existing applications using REST APIs, building into the Universal Registrar.
Veramo SDK Plugin
The Veramo SDK Plugin is an extension of the Veramo SDK, a JavaScript framework for Trusted Data, adding support for cheqd functionality.
The /credential-status/search
API allows users to search for specific entries of a Status List on the cheqd network. For example, if there are multiple Status Lists associated with the same DID, the search functionality allows applications to make requests only to a specified Status List.
Users are able to filter by:
Execute the filters from Step 1 on the API below:
Understanding the context and construction of DID-Linked Resources
Our objective in building DID-Linked Resources on cheqd is to improve the way resources are stored, referenced and retrieved for our partners and the broader SSI community, in line with the existing W3C DID Core standard.
📝 Architecture Decision Record for On-ledger Resources
Full discussion and details on the design of cheqd's on-ledger resources are available in its ADR
Create digital Resources linked to cheqd DIDs on-ledger
"DID-Linked Resources" are identified with a did:cheqd
Decentralized Identifier with a Universally Unique Identifier (UUID) that acts as a permanently-accessible link to fetch the resources from the cheqd ledger. We refer to this as the "resource ID". Through the "resource ID" or a set of DID URL query parameters, applications are able to persistently access a digital resource on the cheqd network.
Below are a list of alternatives for creating cheqd DID-Linked Resources.
Create DID-Linked Resource
Create a custom DID-Linked Resource for a schema, Trust Registry or other persistent data file.
Search DID-Linked Resources
Search and query for existing DID-Linked Resources on cheqd.
Understanding DID-Linked Resources
Detailed guide explaining the context and technical composition of DID-Linked Resources on cheqd.
DID Resolution and DID URL Dereferencing
Architecture decision record explaining the different parameters for fetching DID Document data on cheqd, including DID-Linked Resources.
cheqd Cosmos CLI
Cosmos-native CLI for creating transactions on cheqd. Should be used for testing purposes only.
DID Registrar
Simple setup for building cheqd DIDs into existing applications using REST APIs, building into the Universal Registrar.
Veramo SDK Plugin
The Veramo SDK Plugin is an extension of the Veramo SDK, a JavaScript framework for Trusted Data, adding support for cheqd functionality.
Aries Framework JavaScript
Aries Framework JavaScript is an SDK which supports ZKCreds (AnonCreds) natively with cheqd support.
In self-sovereign identity (SSI) ecosystems, “resources” are often required in tandem with W3C Verifiable Credentials, to provide supporting information or additional context to verifiers receiving Verifiable Presentations.
For example, common types of resources that might be required to issue and validate Verifiable Credentials are:
Schemas;
Status lists;
Trust registries;
Visual Representations of Verifiable Credentials;
Documents; or
Logos
Schemas describe the fields and content types in a credential in a machine-readable format. Prominent examples of this include schema.org, Hyperledger Indy schema objects, etc. You can think of them as a template for what is included in a Verifiable Credential.
Below is an example of a schema.org residential address with full URLs:
This might also take the form of evidence schemes, which describe additional information about the processes used to validate the information presented in a Verifiable Credential in common, machine-readable format.
Prominent examples of this include Schema.org, Hyperledger AnonCreds SCHEMA
objects, etc.
Status lists allow recipients of a Verifiable Credential exchange to check the status of a credential for validity. Prominent examples of this include the W3C Status List 2021
specification, Hyperledger AnonCreds Revocation, etc.
Trust registries enable recipients of a Verifiable Credential exchange to check that the Decentralized Identifier of the issuer is listed in a trusted registry. This provides a level of assurance in the authenticity of the issuer. Examples of Trust Registries include the ToIP Trust Registry Specification, EBSI Trust Registry API, etc.
Although Verifiable Credentials can be exchanged digitally, in practice most identity wallets want to present “human-friendly” representations. Examples of this include the Overlays Capture Architecture (OCA) specification, Apple Wallet PassKit (".pkpass
"), Google Wallet Pass, etc. A resource, using something like Overlay Capture Architecture (OCA) may enable a credential representation to be shown according to the brand guidelines of the issuer, internationalisation (“i18n”) translations, etc.
Figure 1: Overlays Capture Architecture Specification Version 1.0.0
Such visual representations can also be used to quickly communicate information visually during identity exchanges, such as airline mobile boarding passes.
Figure 2: Mobile boarding passes in Apple Wallet showing different visual styles (source: British Airways media centre)
In the example above from British Airways, the pass at the front is for a “Gold” loyalty status member, whereas the pass at the back is for a “standard” loyalty status member. This information can be represented in a Verifiable Credential, of course, but the example here uses the Apple Wallet / Google Wallet formats to overlay a richer display.
While it’s useful to have digital credentials that can be verified cryptographically, the reality is that there are often occasions when a quick “visual check” is done instead. For example, when at an airport, an airline staff member might visually check a mobile boarding pass to direct people to the correct queue they need to join. The mobile boarding pass does get scanned at points like check-in, security, boarding etc., to digitally read the information, other scenarios where this is not done are equally valid. However, most Verifiable Credential formats do not explicitly provide such “human-friendly” forms of showing the data held in a credential.
More broadly, there are other types of resources that might be relevant for companies beyond SSI vendors, that want a way to represent information about themselves in an immutable and trustworthy way.
Many companies require documentation such as Privacy Policies, Data Protection Policies or Terms of Use to be made publicly available. Moreover, Trust over IP (ToIP) recommends making Governance Frameworks available through DID URLs, which would typically be a text file, a Markdown file, PDF etc.
Companies may want to provide authorised image logos to display across different websites, exchanges or block explorers. Examples of this include key-publishing sites like Keybase.io (which is used by Cosmos SDK block explorers such as our own to show logos for validators) and “favicons” (commonly used to set the logo for websites in browser tabs).
The current uses for resources are therefore very broad across the SSI ecosystem, and in addition, for other companies that may want to use DIDs to reference relevant information on ledger. For this reason, it is essential that the SSI community strengthens the way that resources are stored, referenced and retrieved in SSI ecosystems.
In our demo for IIW, we showed an IIW logo as a resource on-ledger, being used within the body of a Verifiable Credential. In the JSON below, you will be able to see the resources being used in both the "@context" and "logo" sections.
By clicking the image below, you will see that this is actually being pulled and resolved from the cheqd ledger:
There are multiple approaches to decentralised identity which rely on centralised infrastructure across different technical layers. Decentralised Identifiers (DIDs): are often stored on ledgers (e.g., cheqd, Hyperledger Indy, distributed storage (e.g., IPFS in Sidetree), or non-ledger distributed systems (e.g., KERI). Yet, DIDs can be stored on traditional centralised-storage endpoints (e.g., did:web, did:git.
The issue of centralisation affects resources providing extra context and information to support Verifiable Credentials. These resources, such as schemas and revocation lists, are often stored and referenced using centralised hosting providers.
Using centralised hosting providers to store resources may have a significant difference in the longevity and authenticity of Verifiable Credentials. For example, a passport (which typically has a 5–10 year validity) issued as a Verifiable Credential anchored to a DID (regardless of whether the DID was on-ledger or not) might stop working if the credential schema, visual presentation format, or other necessary resources were stored off-ledger on traditional centralised storage.
DIDs could be tampered by compromising the hosting provider: DIDs and DID Documents ("DIDDocs") stored at a centralised web endpoint can be compromised and replaced by malicious actors.
Hosting providers could unilaterally cease to host particular clients: Hosting providers could terminate accounts due to factors such as non-payment of fees, violation of Terms of Service, etc.
Single point-of-failure in resiliency: Even for highly-trusted and sophisticated hosting providers who may not present a risk of infrastructure being compromised, a service outage at the hosting provider can make a DID anchored on their systems inaccessible.
Even for highly-trusted and sophisticated hosting providers who may not present a risk of infrastructure being compromised, a service outage at the hosting provider can make a resource anchored on their systems inaccessible.
The high centralisation of cloud providers and history of noteworthy outages clearly demonstrates why we should not host resources on centralised cloud storage in production environments. In Q1 of 2022, the three largest players in the cloud (AWS, Google Cloud, Microsoft Azure) dominated with 65 per cent in nearly all regions (outside of China).
Figure 3: Breakdown of global cloud provider market share (source: CoinTelegraph)
Beyond cloud providers, there are other events that exemplify the issuers relying on larger players. The Facebook outage of 2021 (shown in the graph below) took down apps that used “Login with Facebook” functionality. This highlights the risks of “contagion impact” (e.g., a different Facebook outage took down Spotify, TikTok, Pinterest) of centralised digital systems — even ones run by extremely-capable tech providers.
Figure 4: Graph showing drop in Facebook traffic from their global service outage in 2021 (source: Kentik)
Likewise, with decentralised identity, there has been excellent work to decentralise, with standards that remove the need for centralised intermediaries — notably around Verifiable Credentials and the decentralised trust provided by DID Authentication. Yet, all of this excellent work may be eroded in practice, unless every component of an SSI ecosystem is able to maintain an equivalent level of decentralised trust. Resources are currently an area that has been centralised for the sake of convenience.
"Link rot" happens when over time, URLs become inaccessible, either because the endpoint where the content was stored is no longer active, or the URL format itself changes. The graph below from an analysis by The New York Times of linkrot shows degradation over time of URLs.
Figure 5: Linkrot analysis over 1996-2019 by New York Times (source: Columbia Journalism Review / New York Times)
For this reason, keeping an up-to-date version of the links themselves is crucial. Furthermore, a study of link rot found at least 66.5% of links to sites in the last 9 years are dead. This can have an adverse impact on the digital longevity of Verifiable Credentials if there’s “link rot” in the resources necessary to process the credential. For this reason, projects such as The Internet Archive’s Wayback Machine exist to snapshot digital ephemera before they are lost forever.
Figure 6: Pie chart showing root causes of link rot (source: Ahrefs)
This illustrates that link rot can affect a significant proportion of links in a relatively small amount of time, and once again, looking at how resources are currently stored in SSI ecosystems, if the resource locations are moved and the links are broken, the Verifiable Credentials relying on these resources become unusable. Therefore, resources, once defined, should be architected to be used and referenced indefinitely, without being changed.
Finally, the centralised way that resources are currently stored and managed is not immutable, and as a result, it is liable to tampering. For example, if a hosting provider is compromised, or if malicious actors are working for the company, resources may be changed and previous resource versions may be purged from the central database.
As we move towards a new web infrastructure with Web 3 (and beyond…), and as more projects leverage blockchain and distributed ledgers, it’s important not to port the previous issues of the web, and instead find novel ways to better manage information, with longevity in mind. This is why at cheqd, we have decided to redesign the way resources are captured on the ledger.
Solutions that do currently store schemas on ledger (e.g., Hyperledger Indy) don't have semantic linkage between old and new versions. In this instance, current ledgers allow new versions to be made but don't offer an easy way for client apps to discover linkages as they evolve over time.
We took the following design principles into consideration, along with an explanation of how we addressed them:
Built using existing, familiar DID Core Spec patterns: Wherever possible, our design attempts to utilise existing patterns and behaviours within the W3C DID Core specification (such as the use of DID URLs to identify resources), instead of trying to implement proprietary/custom approaches. We believe that similar designs could be adopted by other DID methods if they choose.
Protection against linkrot for long-term retrieval: Any Resource stored on-ledger is replicated across multiple nodes.
If any individual node or endpoint is down, lookup requests can be sent to any other node on the network.
In a catastrophic scenario where the network itself stops to exist, e.g., companies shutting down, getting acquired etc the on-ledger data can still be restored by digital archivists using ledger snapshots. A practical example of this is how Cosmos Hub makes historical chain archives available which can be restored. While this can be cumbersome, we wanted to design for this as a fail-safe.
Extensible by default: Our objective was to build a flexible design pattern that allowed developers to define and extend their own resource types. Trying to control what kinds of resources could be written to ledger would make the ledger-side logic complex. Instead, we opted for a design where the cheqd ledger acts agnostically to store resources, as long as correctly authorised, as a permanently-accessible endpoint.
Design for DID-spec "dumb" as well as DID-spec "smart" client applications: Many approaches in this space assume that client applications must be adept at parsing DIDDocs and resolving complex inter-DIDDoc relationships. We saw describing resources using DIDDocs as metadata about the resource which could be independently-parsed by "smart" client applications; while also providing a fallback approach for "dumb" client applications. We internally considered this as "What if an identity wallet understood how to parse JSON, but didn't understand the DID Core spec?"
Version controlled: The ability to evolve a resource over time is critical for identity use cases. As described above, examples of this include when identity document schemas change, logos evolve, etc. Current approaches (such as Hyperledger Indy CredDefs) deal with this by creating entirely new, unlinked resources. We designed to make it easy, using existing DID Core specification techniques, so that client applications could query "What was the version of a resource with this name on this date/time?"
Make re-use of resources simple: We liked the concept of Schema.org in the sense that it promotes a common, machine-readable specification. Therefore, our design allows for patterns where the controllers of a DID can reference resources created by other DID owners/controllers, e.g., referencing a pre-existing schema. Taking this line of thought further, it allows for an arbitrary depth of how resources can be nested, as long as they are discoverable/resolvable.
Notalltypes of resources should be stored on a ledger...but can be made discoverable through similar design patterns: Distributed ledgers are great for redundancy, but the cost of this duplication (in terms of storage required by node, block size, transaction finality speeds, etc) can be quite significant. For instance, a distributed ledger is probably not the best storage and retrieval mechanism for a video file (which can run into many GBs/TBs); or even a PDF larger than a few MBs. cheqd network restricts the block size for an individual block to ~200 KB. This can be updated via an on-ledger vote, but the trade-off of asking node operators to provision ever-expanding storage would be not ideal. Our design therefore restricts the file/payload size of on-ledger resources (in our case, ~190 KB - giving enough room for transaction data besides the resource itself), while allowing the same techniques below to be used for describing off-ledger resources. E.g., our first DID on cheqd network references a 7+ MB image accessible via IPFS. We recognise and accept that DID owners/creators may choose to use their own centralised/decentralised storage, and the design patterns described below accommodate that.
Learn more about the technical details on learn how we have architected DID-Linked resources, and how we achieve these design principles.
Once created, issuers of Verifiable Credentials may want to reference resources within the body of issued Verifiable Credentials.
As mentioned in the section on Context for Resources, this may be useful for referencing:
Schemas;
Status lists;
Trust registries;
Visual Representations of Verifiable Credentials;
Documents; or
Logos
within the contents of Verifiable Credentials themselves.
Below is an example of a Verifiable Credential for an IIW event ticket which includes a fully qualified DID URL for the schema and logo, using resources on-ledger.
The schema in the above Credential dereferences to the following data:
Search and query for DID-Linked Resources
The /resource/search
API allows users to search for specific entries of a Resource on the cheqd Network. For example, if there are multiple Resources associated with the same DID, the search functionality allows applications to make requests only to a specified Resource.
Create a DID-Linked Resource associated with a cheqd DID over REST API
Using the /resource/create
API, users are able to create custom DID-Linked Resources, including:
Schemas
Credential Definitions
Trust Registries
Logos associated with DIDs
Governance files
Make sure you have set up your account with Credential Service and are logged in, using our guide below:
Before you can create a DID-Linked Resource, you need to create a "parent" DID which is used to link the Resource on-ledger. Use the API in the page below to create a DID:
DID-Linked Resources can be any type of file or content that is below ~45kb in size.
For the purpose of an example, lets use an AnonCreds schema (JSON file) as the resource:
Save this file locally and call it something like resource.json.
Prepare a file with resource and encode it into base64, base64url
or hex
. On Unix systems, you can use the following command input:
Expected output:
Resources are grouped by having identical names and types. This means if you want to create a new version of the same Resource, you will need to specify the same name and type in the following request.
Understand cheqd's SDK suite and choose the best fit for your project.
cheqd has integrated into a series of SDKs to enable third parties to create DIDs and resources, issue and verify Verifiable Credentials, using cheqd DIDs, DID Documents and Schemas.
cheqd is continually integrating into different software development kits to suit the needs of different partners and their clients.
Below is a comparison between our three initial supported SDKs, Veramo SDK for cheqd, Credo (formerly Aries Framework JavaScript) and Walt.id's SSI Kit.
"Resources" are identified with a did:cheqd
Decentralized Identifier with a Universally Unique Identifier (UUID) that acts as a permanently-accessible link to fetch the resources from the cheqd ledger. We refer to this as the "resource ID".
Using UUIDs, we can have a high level of confidence that no two identical resource IDs will ever be created. This is important for ensuring the integrity and uniqueness of each individual resource.
Figure 1: DID-linked Resource DID URL path
This will be explained further in the section on DID URL dereferencing to fetch a resource.
Resources are organised into groups called "Collections". Each DID may have an associated Collection, and the Collection ID is derived from the unique identifier of the DID.
Collections can store any type of Resource, but for the purpose of this documentation we will focus on the use case where the Collection is used for storing a set of schemas.
The most important concept used in this design is that each on-ledger Collection is identified using a DID and is described using a DID Document.
The DID Document acts as metadata, providing information about the Collection, such as who is able to update it, when it was created and what are the latest and deprecated versions of Resources within the Collection.
For example, the following DID:
did:cheqd:mainnet:1f8e08a2-eeb6-40c3-9e01-33e4a0d1479d
will derive the Collection ID: 1f8e08a2-eeb6-40c3-9e01-33e4a0d1479d
Figure 2: Relationship between a DID and Resource Collection
A Collection is created using a createResource
transaction, and specifying the Collection ID as the same identifier as that of the parent DID.
Note that the Collection ID may take the syntactical form of a 'Hyperledger Indy' DID identifier or may be a Universally Unique Identifier (UUID). This is described in the cheqd DID method.
To create a "DID-Linked Resource", you must already have created a 'parent' DID, from which the Collection ID can be derived. When you carry out the createResource
transaction, you must:
Generate a new, unique UUID for the Resources
Specify the same Collection ID as the unique identifier of the parent DID
Sign the createResource
transaction with the Verification Method keys of the parent DID.
This is shown in the diagram below:
Figure 3: Relationship between a DID and DID-linked Resource
Example of createResource
transaction using Veramo SDK:
Multiple, DID-Linked Resources can be stored in a Collection, for example, this could be different versions of the same Resource over a period of time or semantically-linked resources. This enables unique resources to be stored directly on-ledger and be retrievable through DID resolution and dereferencing.
Once you have created a resource, the DID Document will automatically reference the resource and the collection within the didDocumentMetadata
in a newly defined section called linkedResourceMetadata
.
This relationship is shown in the diagram below:
Figure 4: DID Document metadata with DID-linked Resource metadata
For simplicity, we will focus on the use case where a Resource is a schema. The same logic used in fetching schemas from the ledger can be applied to any of the aforementioned types of Resources.
The syntax of a Resource metadata for a single schema is as follows:
Any valid IANA Media Type (colloquially known as "file type") is allowed as an on-ledger Resource. The only restriction is that the Resource should fit within a block, which de-facto restricts it to ~190KB to fit within the ~200KB block limit. Any files larger than this are recommended to be stored and linked via long-term immutable file discovery mechanisms such as IPFS.
A Golang library is used to derive and set media type based on the file extension of provided resource file. This makes it much simpler to maintain, since there is no list of file types that the cheqd ledger needs to gatekeep.
The following list defines which specific parameters a resource request format may contain:
The following list defines which specific parameters a resource response format may contain:
Let’s take a look at a fully resolved output response for a DID with a Collection and single associated Resource:
Let’s take a look at a fully resolved output response for a DID with a Collection and multiple associated Resources:
Collections are identified by a Collection ID which is a unique identifier of the linked, parent DID. Within the DID Document Metadata of the Collection DIDDoc, the Linked Resource metadata describes Resources within this Collection:
Note that the Linked Resource output above does not show the actual data / schema attributes when displaying all Resources in this Collection. It only shows Resource metadata.
This logic prevents GetResourceCollection
requests returning large quantities of data, which may be stored across multiple Resources within a Collection.
In order to fetch the actual data, it is necessary to query the specific Resource, rather than the entire Collection.
For more information about the particulars of requests and responses, please refer to our ADR on Resources on ledger.
As shown in the examples above, there may be previous and next versions of the Resource ID.
Whenever a Resource is updated, a new UUID must be generated. The new Resource references the older version, so the UUID is effectively a version number.
Importantly, the collectionId,
resourceName
and the resourceType
of the Resource must remain the same.
For example, a Resource with the name PassportSchema
must always have the same name and resource type to be considered for previous/next version linking.
This could be used, for example, to find the version active at a particular point in time:
Fetching resources using DID resolvers and DID URLs is hugely desirable. Up until this point, we have shown resources identified using path-based syntax.
However, query-based syntax should also be enabled to allow more granular and specific searches within a particular Collection.
To enable combined resolution/dereferencing behavior, cheqd are defining multiple query-based DID URL parameters to fetch resource
or associated metadata. If a DID method specification supports these parameters, and if a DID URL using that method includes the parameter with a valid value, then when a resolver calls the associated VDR using that DID URL, the VDR returns the identified digital resource, not the DID document.
IMPORTANT: DID URL queries should be fully qualified so that they uniquely identify a single resource, or single resource version unless expressly specified.
@cheqd/did-provider-cheqd
This error typically happens when the version of did-provider-cheqd
is incompatible with the version of Veramo CLI being used.
This can happen if you didn't use the npm -g
("global") flag when installing the packages, and have a conflicting package version for any of the required packages in the folder where you executed this command from.
To verify if this is the case, check the version number of globally-installed NPM packages. Your list may be shorter or longer than this list, but pay close attention to the @cheqd/did-provider-cheqd
and @veramo/cli
versions.
Compare and contrast this from the output from the same folder where the command failed without the --global
/ -g
flag:
In this example above, you'll see that the version of the @veramo/cli
package is not the same one as the global one. This could equally happen with the @cheqd/did-provider-cheqd
version.
Doing a global install for both packages will ensure that you've got the correct packages, regardless of which folder the agent.yml
file is kept in.
This error is thrown if the cosmosPayerMnemonic
value is set to an incorrect number of words (it should either be 12 or 24 words), or if it's left to the default value of 'your cosmos payer mnemonic'
.
Note: You can use the same mnemonic for both mainnet and testnet, since the same account address has separate balances on different networks.
Heads-up: Even if you're trying it on testnet
you still need to put cosmosPayerMnemonic
for your mainnet
(You can use the same cosmosPayerMnemonic
). Otherwise, you will still be getting the same error as above when you run veramo config check -f agent.yml
.
wget -c https://raw.githubusercontent.com/cheqd/did-provider-cheqd/main/agent.yml
command is giving you errorsFirst, create agent.yml
file at root
directory level.
Veramo SDK plugin supports two major digital Credential types. Below you can learn about these Credential formats:
Below are a list of alternatives for using Credentials with cheqd support. Each offers a different set of protocols and underlying technical capabilities.
Veramo SDK plugin for cheqd identity functionality
Utilise cheqd's identity functionality through the Veramo SDK Plugin by installing the Veramo CLI and getting started below:
We chose to build a cheqd plugin into Veramo SDK for a few key reasons.
Design Principles — The Veramo SDK was designed to be highly flexible and modular making it highly scalable and fit for a lot of complex workflows. As a result, we felt it offered a route to minimise how much needs to be built from scratch. Through its flexible plug-in system, it’s easy to pick and choose which plug-ins are most beneficial, plus it’s possible to add in our custom packages where required which we knew would be necessary from Cosmos-based transactions.
Developer Experience — The Veramo SDK has been designed in a way that offers a fast end-to-end process. Ultimately, at cheqd, we want to reduce the amount of time our team spends on SDKs and so we can maintain our focus on building ledger functionality (i.e. building our implementation of the revocation registry and the credentials payment rails).
Attractive & Simple CLI — The Veramo core API is exposed by its CLI which makes it easy to create DIDs and VCs directly from a terminal or local cloud agent.
Platform Agnostic — The Veramo packages run on Node, Browsers and React & React Native right out of the box.
Veramo provides an excellent foundation for clients that want to build verifiable data applications. This is because Veramo Core, the Veramo CLI and any specific plugins are available as NPM packages, enabling:
Identity functionality to be carried out through a native CLI interface; or
Identity functionality to be integrated directly into client applications through NPM packages.
Using the DID-Provider-cheqd package, we have also been able to reuse identity functionality and abstract the complexity of cheqd/SDK and cheqd Network in less complex packages.
did:cheqd
-specific functionalityNew DID creation can also be done by passing a full-body DIDoc payload in JSON, rather than having to assemble the document field-by-field.
This package works alongside other base Veramo packages:
The @cheqd/sdk
package adds Cosmos SDK specific functionality such as signing transactions, paying for ledger fees, etc.
You can use our Veramo plugin in non-CLI contexts as well, for example, for integrating into custom applications
Depending on the type of application you are looking to develop, you will need to install a different set of packages.
For other applications, see:
Note: Depending on your system permissions, you might be prompted for additional permissions. Add sudo
to the beginning of the command in case that happens.
Verify the installation was correct. Command below should output latest version of veramo you installed.
did-provider-cheqd
packageInstall the did-provider-cheqd
NPM package in a similar fashion:
You can check all of your NPM package versions by running the command:
agent.yml
configuration fileYou can do this in terminal through:
agent.yml
file in an editor to customise the configYou can open the agent.yml
in a text editor/IDE of your choice to edit a few mandatory settings.
In terminal, you can edit the agent.yml
file using an editor like nano
:
Make sure you provide the actual relative/absolute path to the file.
By default, the did-provider-cheqd
package has a default SQLite database password, but it's a good idea to modify and change this to a new key unique to your install.
Take the key generated and replace the value under dbEncryptionKey
in the agent.yml
file.
The default value is set to resolver.cheqd.net
, which is an instance of the cheqd DID Resolver hosted by the cheqd team. This DID Resolver instance can handle requests for did:cheqd:mainnet
as well as did:cheqd:testnet
namespaces.
If you want, you can replace the url
property with a different REST API endpoint for a different instance of the cheqd DID Resolver.
Note: This configuration is an advanced step and not recommended for most users. Skip it and continue to the next step in most cases, unless you know why you want to switch the resolver interface.
Firstly, comment out the custom did-cheqd-resolver
entry and uncomment the universal-resolver
entry. This tells Veramo CLI to use the Universal Resolver interface for did:cheqd
.
Also comment out this section for the did-cheqd-resolver
:
Finally, uncomment and configure the universal-resolver
interface:
In order to add cheqd-testnet to your Keplr extension, please follow the following instructions:
You need to configure this in under didManager
section as shown above, where you'll need to edit:
defaultProvider
: The default cheqd network is set to did:cheqd:testnet
to allow developers to test out network functionality. However, if you prefer, you can switch this out to did:cheqd:mainnet
instead.
agent.yml
file and exitMake sure all your edits above are persisted and saved to a file that you can access.
Once you've completed Step 2 above, verify that your Veramo configuration is accurate using the following command. If your configuration is correct, you should get a success message like the one below.
Functionality | Veramo | Credo | Walt.id SSI Kit |
---|---|---|---|
Parameter | Description |
---|---|
Parameter | Description |
---|---|
This guide provides common errors and potential fixes for them if you encountered errors when .
Second, go to this , copy everything from there and paste it in your agent.yml
file. And you're good to go. 😉
Learn about Verifiable Credentials and Presentations
If you want to learn more about what
is a modular and pluggable client app SDK for decentralised identity and SSI applications. Our Veramo plugin - the - enables developers to interact with the cheqd ledger using Veramo SDK.
This package includes for use with the . It can also be consumed as an NPM package outside Veramo CLI for building your own applications with NPM.
The package's core functionality is borrowed from and extends this to include cheqd ledger functionality, such as creating and managing DIDs.
did-provider-cheqd
is the first Veramo SDK plug-in that utilises the DID Manager Update method to offer a full-body DIDDoc update for a DID on cheqd ledger, rather than individual field update transactions used more commonly in other DID methods such as .
Learn how to network
Our provides step-by-step instructions on how to configure your installation for cheqd network
Figure 1: Veramo SDK for cheqd architecture with components ()
did-provider-cheqd
consumes functionality that exists within the in a way that complies to the Veramo AbstractIdentifierProvider
. (You don't need to call this package separately as it's already included as a dependency in package.json
.)
For identity-related keys, this plugin uses to manage keys for create and update operations.
Find out about .
Our natively supports the following Credential formats:
We provide a quick-start .
If you're looking to use the Veramo CLI with cheqd or develop a proof-of-concept application, use the .
Node version recommended Nodev16
. You can install Node
This step is exactly :
Download the file that contains the configuration for cheqd network to be used with Veramo CLI.
Note: Alternatively, you can also fetch this by the repository.
In order to be able to read/query did:cheqd
entries from the ledger, you need to configure a REST API endpoint for a instance.
If you plan on interacting with multiple DID methods using Veramo CLI, you can alternatively query did:cheqd
using instead. This allows your CLI configuration to handle .
Go to , then replace everything with cheqd-testnet json configuration below.
While reading/querying from the cheqd ledger incurs no cost, if you want to to cheqd ledger, you need to pay transaction fees for the ledger writes.
cosmosPayerMnemonic
: . This is only stored locally, and the mnemonic is used to reconstitute the account address and keys used to pay for the transaction.
rpcUrl
: For both did:cheqd:mainnet:
as well as did:cheqd:testnet:
sections, you can specify a Cosmos SDK RPC endpoint. This endpoint is where transactions are sent to. By default, this is populated with rpc.cheqd.net
(for mainnet) and rpc.cheqd.network
(for testnet), but you can can modify this to or even your own local/private RPC endpoint.
If the config check
throws an error, check out our to see common errors and fixes.
Now that your Veramo CLI installation is successfully set up to work with cheqd, try following our tutorials for or .
Create cheqd DIDs (ADR)
✔️
✔️
✔️
JSON based JWT Verifiable Credential (spec)
✔️
❌
✔️
JSON-LD Verifiable Credential (spec)
✔️
✔️
✔️
AnonCreds (spec)
❌
✔️
❌
Selective Disclosure-JWT Credential (spec)
⌛(roadmap)
✔️
✔️
Create on-ledger Schema (ADR)
✔️
✔️
❌
Create Credential Definition (spec)
❌
✔️
❌
DIDComm v1.0 (spec)
✔️
✔️
❌
DIDComm v2.0 (spec)
✔️
✔️
❌
DID Exchange Protocol (RFC 0023)
❌
✔️
❌
Agent Connection Protocol (RFC 0160)
❌
✔️
❌
Out of Band Protocol (RFC 0434)
❌
✔️
❌
Self Issued OpenID Provider v2 (OIDC-SIOP) (spec)
⌛(roadmap)
✔️
✔️
OpenID for Verifiable Credential Issuance (spec)
⌛(roadmap)
✔️
✔️
OpenID for Verifiable Credential Presentations (spec)
⌛(roadmap)
✔️
✔️
Status List v2021 Revocation (spec)
✔️
❌
✔️
AnonCreds Revocation Registry Definitions (spec)
❌
✔️
❌
AnonCreds Status List Entries (spec)
❌
✔️
❌
Issue Credential Protocol (RFC 0036)
❌
✔️
❌
Issue Credential Protocol V2 (RFC 0453)
❌
✔️
❌
DIF Presentation Exchange (spec)
✔️
✔️
✔️
Aries Present Proof 2.0 (spec)
❌
✔️
❌
DID-Linked Trust Registries
⌛(roadmap)
❌
❌
resourceUri
A string or a map that conforms to the rules of RFC3986 URIs which SHOULD directly lead to a location where the resource can be accessed from. For example: dic:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c/resources/0f964a80-5d18-4867-83e3-b47f5a756f02
resourceCollectionId
A string that conforms to a cheqd-supported unique identifier format. For example a UUID: 46e2af9a-2ea0-4815-999d-730a6778227c
resourceId
A string that uniquely identifies the resource, cheqd uses UUIDs. For example a UUID: 0f964a80-5d18-4867-83e3-b47f5a756f02
resourceName
A string that uniquelt names and identifies a resource. This property, along with the resourceType below, can be used to track version changes within a resource.
resourceType
A string that identifies the type of resource. This property, along with the resourceName above, can be used to track version changes within a resource. Not to be confused with media type.
resourceVersion
(Optional) A string that identifies the version of resource. This property is provided by the client and can be any value
alsoKnownAs
(Optional) An array that describes alternative URIs for the resource.
resourceUri
A string or a map that conforms to the rules of RFC3986 URIs which SHOULD directly lead to a location where the resource can be accessed from. For example: dic:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c/resources/0f964a80-5d18-4867-83e3-b47f5a756f02
resourceCollectionId
A string that conforms to a cheqd-supported unique identifier format. For example a UUID: 46e2af9a-2ea0-4815-999d-730a6778227c
resourceId
A string that uniquely identifies the resource, cheqd uses UUIDs. For example a UUID: 0f964a80-5d18-4867-83e3-b47f5a756f02
resourceName
A string that uniquelt names and identifies a resource. This property, along with the resourceType below, can be used to track version changes within a resource.
resourceType
A string that identifies the type of resource. This property, along with the resourceName above, can be used to track version changes within a resource. Not to be confused with media type.
resourceVersion
(Optional) A string that identifies the version of resource. This property is provided by the client and can be any value
alsoKnownAs
(Optional) An array that describes alternative URIs for the resource.
mediaType
A string that identifies the IANA-media type of the resource.
created
A string that identifies the time the resource was created in XML date-time.
updated
(Optional) A string that identifies the time the resource was updated in XML date-time.
checksum
A string that may be used to prove that the resource has not been tampered.
previousVersionId
(Optional) A string that identifies the previous version of the resource.
nextVersionId
(Optional) A string that identifies the next version of the resource.
Set up your account
Set up your account with cheqd Credential Service and log in to start using the APIs.
Create an Issuer DID
Create a W3C conformant DID on cheqd using the did:cheqd
DID Method.
Learn more about DID-Linked Resources
Understand the context and technical composition of cheqd's DID-Linked Resources.
Veramo
The Veramo SDK Plugin is an extension of the Veramo SDK, a JavaScript framework for Trusted Data, adding support for cheqd functionality.
Credo
Credo is an SDK which supports ZKCreds (AnonCreds) as well as regular Verifiable Credentials natively with cheqd support.
Walt.id SSI Kit
Walt.id SSI Kit is an SDK that supports the European Architecture and Reference Framework (ARF) standards for identity, with full cheqd support.
This tutorial offers step-by-step guidance on how to verify a JSON credential, encoded as a JWT (JSON Web Token), a W3C compliant proof format.
⚠️ Before you begin...
Make sure you've correctly configured the cheqd plugin's agent settings for Veramo CLI
This tutorial assumes you have already issued a JSON/JWT Verifiable Credential so that it can be cryptographically verified as untampered.
credential verify
functionIf you have the issued Verifiable Credential stored in a file, say, cred.json
, pass it to the credential verify
function:
Instead of piping the file like above, you can also verify the credential using the raw credential or JWT as follows:
Then enter the JWT or entire JSON credential including the JWT.
If the credential can be verified correctly, the response will be:
Credential verification is done by decoding the JWT proof and checking if it's tampered or not. Feel free to test this yourself by tampering with the jwt
contents in the credential:
If you belive you did everything right(created a verifiable credential and you did not tamper it), and for some reason you're getting
First, make sure you are using a node
with version 16
or above.
Second, change Veramo CLI version to @veramo/cli@latest -g
as previous versions cause few issues in verification. This will override the previous version you have installed.
Run command below to verify your JWT credential.
Look into how this credential can be shown to others through Verifiable Presentations.
This tutorial offers step-by-step guidance on how to verify a Verifiable Presentation.
⚠️ Before you begin...
Make sure you've correctly configured the cheqd plugin's agent settings for Veramo CLI
The cryptographic verification in this tutorial will be based on JWT proof of a previously-created Verifiable Presentation.
presentation verify
functionIf you have the generated Verifiable Presentation stored, pass it to the presentation verify
function:
If the verification is successful, you'll receive this response:
If you belive you did everything right(created a verifiable presentation and you did not tamper it), and for some reason you're getting
First, make sure you are using a node
with version 16
or above.
Second, Change veramo cli version to @veramo/cli@latest -g
as previous versions cause few issues in verification. This will override the previous version you have installed.
Run command below to verify your JWT presentation.
This tutorial offers step-by-step guidance on how to create a Verifiable Presentation.
⚠️ Before you begin... Make sure you've correctly configured the cheqd plugin's agent settings for Veramo CLI
A Verifiable Presentation is a way a credential holder can generate cryptographicall-verifiable proof that they are in posession of the identity keys (e.g., did:key
) the credential was issued to.
This is important because just the Verifiable Credential and its JWT proof, on its own, is susceptible to replay attacks where intercepted Verifiable Credentials could be played back.
The process of creating a Verifiable Presentation is one way of addressing these security concerns.
Begin the process of creating a Verifiable Presentation using:
Specify the subject identity key to be used for signing Verifiable Presentation, e.g., chosen holder did:key
.
Tag
for the Verifiable PresentationHit Enter to accept the default at this step
Select how many verifiers will need to be able to verify the presentation.
This can be the same as the Verifiable Credential, or a sub-section of it. Choose Enter for default.
Select the DID of the verifier from the options presented. In a very simplistic scenario, the verifier could be the same as the issuer, e.g., a scenario where the holder returns a period of time to show they were issued a credential.
You can select one or more Verifiable Credentials to bundle up into the Verifiable Presentation.
After these choices are made, the Verifiable Presentation will be displayed in JSON format along with JWT proof.
Save this output in the folder you have been using throughout, saving as pres.txt
.
You will need to call on this to verify the presentation in the next step.
In a real-world usage scenario, the Verifiable Presentation output generated above would be electronically (e.g., as API messages) or non-electronically (e.g., encoded to a QR code) shared with the verifier/recipient.
Verifiers/recipients would then be able to verify the Verifiable Presentation to check cryptographically the contents are untampered.
This tutorial offers step-by-step guidance on how to issue a verifiable credential
⚠️ Before you begin...
Make sure you've correctly configured the cheqd plugin's agent settings for Veramo CLI
The subject (holder) of this credential will be an off-ledger did:key
DID. The rationale for using off-ledger DIDs when issuing a credential is because the fact that they aren't persisted on ledger means they cannot be correlated or tracked to specific users/individuals.
This allows a user to have multiple did:key
identities, and the identifier/handle they reveal when sharing a Verifiable Credential is context-dependent and better for privacy.
The issuer of the credential, on the other hand, uses an on-ledger did:cheqd
DID since this needs to be publicly-accessible and cryptographically verifiable.
did:key
subject DIDNormally, the credential holder will provide a did:key
DID they have generated themselves (usually done in the background by apps they are using). So, this step typically isn't done by a credential issuer.
For the purpose of this tutorial though, we recommend you create a did:key
subject DID for the later steps.
Start credential generation using:
You'll be presented with an multiple options select:
jwt
for JSON credential, encoded as a JSON Web Token (JWT), a W3C compliant proof format.
lds
for JSON-LD credential, encoded as a Data Integrity Proofs, a W3C compliant proof format.
If you want to learn more about different types of verifiable credentials please go over to our learning site here.
Select which Issuer DID stored in your local storage you'd like to issue the credential from, e.g., did:cheqd:mainnet:zAXwwqZzhCZA1L77ZBa8fhVNjL9MQCHX
The assumption here is that you've either created the issuer DID or stored the DIDDoc by querying it.
Select which subject DID from your local agent storage the credential should be issued to, e.g., did:key:z6Mkktr27VZ7TTFoTsD9p79JwtGnQDgJWKGrxJ79quE7M5Yx
.
This could the subject DID created in Step 1.
This is currently free-text. However, you can hit Enter to use VerifiableCredential
as the default credential context.
The claim type can be thought of as the label in a form field. It can denote the purpose/attribute being stored in the credential.
For example, the claim type name
could refer to the name of an individual.
Enter the value of the claim type. For example, you specified name
as the claim type, the value could be Alice
.
In this tutorial, we will create a credential with only a single name-value pair.
JSON/JWT credentials with DIDs anchored on cheqd are currently not revocable, so please choose No
at this step.
Privacy-preserving credential revocation is a major element of cheqd's roadmap.
At this last step, Veramo CLI generates the credential based on the inputs above.
Note: The human-readable JSON body below is purely for easier parsing by developers/applications. The proof is encoded as JWT or JWS at the bottom of the credential, which can be decoded to reconstruct the entire credential.
Note that the JSON is unordered so the output of the fields could be in a different order
You can save the generated Verifiable Credential, as you can later use it to verify the credential cryptographically or generate presentations to show the credential to others.
Understand how privacy is protected throughout the payment flow
There are multiple areas within this flow where privacy needs to be maintained:
Verifier pays Issuer: Any payment for decrypting a Status List should not be correlatable to a Holder presenting or sharing a Credential.
As part of the bitstring construction. there is a minimum bitstring length of 131,072 entries (16kb uncompressed). Moreover, in this string, the indexes that are not specified are randomised between revoked and unrevoked. This means that there will never be a bitstring with a single entry, or a small amount of entries.
Using this type of construction, the privacy of the Holder is protected through "Herd Privacy" because there is no way that a third party can externally view the Status List and can correlate indices with a particular individual's credential without direct knowledge of a Holders' credential index.
As part of the Access Control Condition setup, the Issuer can set a single payment fee for meeting the Access Control Conditions and decrypting a particular Status List.
Through setting a flat price for decryption, there is no price variation from checking one persons' credential status versus another's. This means that for a particular Status List, all payments on the network will be made at the same price.
Once again, this creates a layer of "Herd Privacy" for the Holder, since the Credential index itself is decoupled from the payment fee. Therefore. while transactions will be visible on the network, there will be no way for a third party to surveil the network or draw conclusions about who's Credential status is being checked.
If there was a variation in the price per Credential status check within the same status list, this would be more likely to become correlatable, alongside other information, back to a specific individual.
We will continue to improve and assess the privacy considerations as we roll out Credential Payments. Some areas we believe there may be scope for privacy leakage are as follows:
Holders' Credential index is doxxed: If a Holder has a particular Credential index doxxed, as well as a link to the status list, there may be scope to monitor the Credential Status of that individual, through a payment. However, third parties will not know when that Holder is using their Credentials.
Issuer creates single entry Status List with specific unlock price: If an Issuer does not use our preset Status List length and creates their own resource with a single or few entries, they may provide a higher likelihood of doxxing when an individual uses their Credential. This is why cheqd, and the specification, has enforced a minimum Status List length.
Getting started with Payment Rails for Verifiable Credentials
Credential Payments brings a significant evolution to the Verifiable Credentials landscape, allowing verifiers to directly pay issuers to unlock Credential Status information. Underneath the hood, we've engineered a robust and secure payment flow that streamlines the end-to-end payment process, with accuracy, speed, and cryptographic integrity.
Below are a list of alternatives for using Credential Payments.
Learn how cheqd's Credential Payments work
Build your knowledge about how cheqd's Credential Payment model works, including setting Access Control Conditions, and privacy-preserving payment flows.
Using the Veramo SDK Plugin for cheqd, you can get started setting up your encrypted Status Lists with Access Control Conditions below:
t
Understand how cheqd's Payment Rails work with Access Control Conditions
The Access Control Conditions outlined in this section establish a secure and structured framework for unlocking encrypted Status Lists and other DID-Linked Resource.
By employing a combination of Decentralised Identifiers (DIDs), DID-Linked Resources, encryption, and timed payment mechanisms, these access control conditions safeguard the integrity of the Resource, promote transparency, and control access to its data.
For Credential Payments, the predominant Access Control Condition is a payment made from the Verifier of a Credential back to the Issuer.
These conditions are established to ensure that authorized entities or users contribute a specified fee before gaining access to the Resource.
The parameters within the payment conditions are defined as follows:
By including these payment conditions in the Status List Payload, the ledger enforces a financial gate from verifiers seeking access. Additionally, the timelock mechanism adds a layer of time-based verification to the payment process. With the timelock, the payment can only be made in a specific time-interval from the latest block-time on the cheqd network. This ensures that historical payments cannot be used to meet the access control conditions, and fresh payments need to be made to access the Resource, helping to maintain the integrity of the payment and access process.
If a Payment Condition is set upon creation of a Status List or other Resource, this will populate an Access Control Condition which is broadcasted across series of nodes to monitor whether the conditions have been met. The Access Control Condition uses query language to directly fetch information from the cheqd ledger, and is fully derived from the inputs made into the Payment Condition.
Each of these conditions are defined as follows:
Once an Access Control Condition has been set, the decryption keys are sharded between an array of nodes to prevent any single node or few malicious nodes from decrypting the data. This comprehensive setup ensures secure and controlled access to the specified resource based on specified criteria and events from the cheqd blockchain.
Using the Veramo SDK Plugin for cheqd, you can get started setting up your encrypted Status Lists with Access Control Conditions below:
Aries Framework JavaScript is an SDK which natively with cheqd support.
Walt.id SSI Kit is an SDK that supports the standards for identity, with full cheqd support.
Learn about different types of Verifiable Credentials
cheqd's implementation of Credential Payments uses encrypted (such as a Status Lists), with Payment Conditions required to unlock. Learn about cheqd's Access Control Condition logic below:
Status List construction: Credential information within Status List should not constitute .
The , which cheqd encrypts with payment conditions, utilises to represent whether a Verifiable Credential has been suspended/revoked or not. A bitstring can be thought of as a long list of 1s and 0s, where, if the binary value of the position in the list is 1 (one), the is revoked, if it is 0 (zero) it is not revoked.
This works by tying each issued Credential with a position and index on the bitstring, so that a Verifier will be able to check the value within the Credential against the public bitstring to ascertain whether the Credential has been revoked or not, using a as well as a .
The .
The payment conditions outlined in the code snippet below define the payment requirements that must be met to access and interact with an encrypted Resource. These are written into a payload.json
file when a create Status List transaction is made to the ledger ().
Parameter | Value | Description |
---|
Parameter | Value | Description |
---|
Access Control Conditions
Understand how cheqd gates encrypted resources using payment conditions and Access Control logic.
|
| Indicates that a timelock payment mechanism is employed. Currently, this is the only type that is supported. |
|
| Specifies the cheqd address to which the payment fee should be sent. This address is associated with the entity managing the Status List (Issuer) and who will receive the payment. |
|
| Defines the amount of the payment fee. In this case, the fee is specified in the smallest unit of CHEQ, (ncheq). |
|
| Sets the duration of the timelock interval, measured in seconds. The verifier must make the payment within the specified time frame relative to a particular block-time on the cheqd blockchain. If the payment is successfully confirmed within this interval, the Verifier's access to the Resource is granted. However, if the payment claim is made outside of this window, it may be considered invalid, and the verifier's access to the Resource may be denied. |
|
| Specifies the type of condition being employed, indicating that the access control condition is related to the Cosmos blockchain ecosystem |
|
| Defines the query path to retrieve specific transaction events from the cheqd blockchain. It filters transactions with a recipient address and amount matching certain criteria, orders the results, and limits the query to one transaction. |
|
| Specifies the blockchain network (chain) being used, indicating that the condition applies to the cheqd Mainnet. |
|
| Specifies the access control method being utilized, which is a timelock mechanism. |
|
| Provides parameters for the access control method. In this case, it refers to the "latest" state on the blockchain |
|
| Specifies the key path within the transaction responses to extract the timestamp of the transaction. |
|
| This checks if the extracted timestamp is less than or equal to the provided value. |
|
| Defines the value (in seconds) against which the extracted timestamp is compared. This value represents a time interval. |
Access Control Conditions
Familiarise yourself with how the Payment gating and Access Control Condition logic works.
To create an encrypted Verifiable Credential Status List v2021 with a set of Access Control Conditions, an Issuer will need to:
Compile a payload.json
file with requisite Access Control Conditions;
Submit a create Status List
transaction the the ledger.
Below are examples of encrypted Status List Payload files:
The provided code snippets above show two Status List Payload files for both Revocation and Suspension.
The Payload files are a crucial configuration element that establishes Payment Conditions for unlocking a Status List Resource. Let's break down the components of this code to understand how it achieves this access control mechanism:
Once an Issuer has compiled the Payload file, they can submit this to the ledger using the following transaction:
The ledger will acknowledge that this StatusList bitstring should be This indicates to the ledger that the Resource should be fully encrypted and only be decrypted upon the set conditions being met.
The following code snippet shows an example of an encrypted Status List broadcast on-ledger as a DID-Linked Resource:
Importantly, the only encrypted element is the "encodedList"
element. This provides the Verifier sufficient information to be able to make the payment back the the Issuer and to fulfill the Access Control Conditions, without being able to see the contents of the Status List itself.
By utilizing cryptographic operations, specifying payment requirements, and ensuring data encryption, this configuration enhances the security, integrity, and controlled access to the Status List, aligning with the principles of decentralized and secure identity management.
Issue Verifiable Credential with Encrypted Status List 2021 and index
There is a specific transaction type for issuing Verifiable Credentials that reference encrypted Status List Resources.
Follow the tutorial here to create an encrypted Status List 2021 Resource on cheqd.
Users should maintain and manage a list of which Credentials match with which specific bitstring indices to be able to revoke or suspend Credentials in the future, and to avoid collisions.
When issuing a Credential, you have the choice of whether to manually specify an index for the Credential within the bitstring, or randomly generate an index number anywhere in the bitstring, or within a given range.
As mentioned above, when constructing the payload for your Credential, including the encrypted Resource, you have a choice of how you would like to specify the index.
The following parameters may be included:
Below are a set of examples of how these parameters may be included in Credential payload files for different purposes:
Once you have constructed your payload file, and have saved it as a JSON file, use the transaction below to issue the Verifiable Credential.
If the transaction is successful, you will get returned a formatted Verifiable Credential, including a populated "credentialStatus"
section.
Paying an Issuer to unlock a Credential Status
A Verifier may need to pay an Issuer to unlock Status information about the presented Credential. Without meeting the payment conditions, the Verifier will not be able to ascertain whether the Credential has been revoked (or suspended) or not.
A Verifier can choose to make a payment to the Issuer if they want to obtain this extra Credential Status information to build a higher level of trust within the Credential presented to them.
If a Verifier wants to unlock access to the Resource, to gain access to additional information about a Credential presented to them, such as the Credential Status, firstly, the Verifier will be presented Credential, including a link to the StatusList within the "credentialStatus"
section of the Credential body.
Through following the link in"credentialStatus"
section of the Credential body. the The Verifier will be directed to an on-ledger Resource, identifiable through a DID URL, for example:
This on-ledger Resource will contain:
An encrypted potion of the Resource, such as a Status List bitstring. identified by the "encodedList"
property.
Unencrypted metadata about the Resource, including the issuers' payment address "feePayerAddress"
and and the Payment Conditions, "feePaymentAmount"
and "intervalInSeconds"
.
This gives the verifier requisite information they need in order to pay the Issuer to unlock the Credential Status. You can learn more about Access Control Conditions below.
This payment should be made in CHEQ.
Note that the "feePaymentAmount"
may be specified in ncheq. This is lowest denomination of the CHEQ token, "nano" CHEQ which is 1 x 10^-9 CHEQ.
Note the "intervalInSeconds"
which indicates how long after making the payment the Verifier has to verify the Credential.
The Verifier should input the presented Credential into a payload file, including the parameter:
"fetchList": true
This indicates that the Verifier wants to claim that they have met the Access Control Conditions, and for the nodes to query whether the Access Control Condition has been met. For example:
Using the Veramo CLI. Verifiers can submit the following transaction, alongside the payload file to verify the Credential:
If successful, the Verifier will obtain the keys to decrypt the Status List and access the Credential Status information. The Verifier will receive a response indicating whether the Credential:
Is verified and untampered
Has been revoked (or suspended) or not
This provides the Verifier the full information to make a trust decision, having paid the Issuer for the Credential Status information.
Parameter | Value | Description |
---|
Each encrypted Status List is a , where each bit represents a Credential which is either revoked or unrevoked (or suspended or unsuspended).
Parameter | Value | Optional |
---|
Ensure that the "statusPurpose"
and "statusListName"
is the same as the existing Status List on-ledger, .
Using one of , Verifiers can make a payment of the amount specified in the "feePaymentAmount"
to the "feePayerAddress"
.
Once the Verifier makes a payment of the specified amount in the payment conditions back to the Issuer, the will be met.
|
| This indicates that a local Key Management System (KMS) is being used for cryptographic operations, ensuring secure key handling. |
|
| Specifies the issuer's Decentralized Identifier (DID), uniquely identifying the entity responsible for managing and issuing verifiable credentials. |
|
| Names the Verifiable Credential Status List, providing context for its purpose. |
|
| Defines the purpose of the status list. This can be either revocation or suspension. |
|
| Indicates that the Verifiable Credential Status List, crucially, is encrypted, enhancing data privacy and security. This can be either true or false (unencrypted). |
|
| Describes the payment conditions required for accessing the status list. In this case, a timelock payment mechanism is used, specifying the fee payment address, amount, and interval. |
|
| Specifies that the symmetric key for decrypting the status list will be returned. |
|
| Specifies whether the encrypted keys should be broadcast on |
|
| Specifies the network where the sharded decryption keys will be stored (across Lit Protocol) |
|
| No |
| string | No |
| string | Yes |
| number | Yes |
| number | Yes |
| number, or set of numbers | Yes |
Follow these instructions to update an existing did:cheqd
entry on cheqd ledger.
⚠️ Before you begin...
Make sure you've correctly configured the cheqd plugin's agent settings for Veramo CLI
Construct your payload.json
file like this:
Where importantly:
denom
: ncheq (smallest denomination classification)
amount
: 10000000000 (This is 10 CHEQ by default and will not work with a different value)
Then try running the command below to deactivate the did
:
If you would like to fetch the deactivated DIDDoc, execute the resolve
command as outlined here. You can check if didDocumentMetadata
has the deactivated
flag set to true.
Follow these instructions to update an existing did:cheqd
entry on cheqd ledger.
⚠️ Before you begin...
Make sure you've correctly configured the cheqd plugin's agent settings for Veramo CLI
Before updating the DID, you will need to prepare the updated DIDDoc and parameters for the transaction in an payload.json
file.
This file can be saved whereever you choose, but the location must be specified in the create DID command used in Step 2. (By default, it will be saved under the project root directory.)
kms
(default local
): Key Management System (KMS) to be used for storage.
did
: The did
that resolves to your DIDDoc
.
alias
: A human-friendly alias for the DID. Only used locally when referencing operations in Veramo CLI.
document
: Full body of the DID Document including updated sections.
versionId
: (optional) Custom versionId for the DID Document. If this is not set manually, then a UUID will be automatically generated for the DID Document version.
keys
: Keys used to sign the DIDDoc. These must match the ones specified in the DIDDoc, otherwise an error will be thrown.
fee
amount
: An array of coins, coins are represented as an object with 2 fields
denom
: ncheq (smallest denomination classification)
amount
: 25000000000 (This is 25 CHEQ by default and will not work with a different value)
gas
: Each transaction must specify the maximum amount of gas it may consume.
payer
(optional): The cheqd fee payer address
granter
(optional): The cheqd fee granter address, Provided the grantee has an allowance by the granter
Note that transaction fees are paid by the cheqd account set in the
agent.yml
configuration file, setup here. Each of cheqd's on-ledger identity transactions has a fixed fee, the pricing for cheqd DIDs and DID-Linked Resources can be found here. If your account has insufficient balance the transaction will fail.
Use the command below to construct and broadcast update transaction.
So, let's try to update service
section of our DIDDoc
. Then, your payload.json
file will look like this.
Note, that we are updating a service
section of in our DIDDoc
.
After you have updated the payload.json
file, run the command below to update the did
:
If you would like to fetch the updated DIDDoc body following the successful DID update result, execute the resolve
command as outlined here. You can check if service
section of DIDDoc
has been updated.
DID update operations can be complicated, especially when changing or updating keys, using multiple keys etc. Understand the design of the cheqd DID method and Verification Relationships in the W3C DID Core specification to understand the logic that is applied in these scenarios.
Learn about DIDs If you want to learn about what DIDs are, please go over to our learning site here.
A Decentralized Identifier "DID" is a globally unique identifier that does not require a centralized registration authority because it is registered with distributed ledger technology or other form of decentralized network.
Learn about DIDs If you want to learn about what DIDs are, please go over to our learning site here.
Below are a list of alternatives for creating cheqd DIDs.
Follow these instructions to create a new DID and publish the associated DID Document on cheqd ledger.
⚠️ Before you begin...
Make sure you've correctly configured the cheqd plugin's agent settings for Veramo CLI
The first step is generating a template for your DID Document, including a new DID and associated public/private key pair. This process also aligns with method 1 in the key management guide.
It is important to note that this step does not create your DID on ledger, but it generates your identity keys as a draft DID Document for you to use in the on-ledger transaction in Step 3.
You can use the following command in your CLI to create your DIDDoc and associated identity keys:
You can pass the payload of the inputs and arguments as a file rather than inline using:
You can reuse this example file:
Within this command, you are able to choose from the following inputs below to produce different types of DIDDocs:
Once you have submitted the command above, you should receive a DID Document draft template, including a set of identity keys, including your chosen inputs and arguments. You can find an example of this output below:
You can then use this template to populate your payload.json
file in Step 2.
After running the above command, if you see an unexpected error, follow our DID Operations Troubleshooting Guide to fix it. A common error is:
Once you have created a template for your DIDDoc and generated your keys, and before creating a DID on-ledger, you will need to prepare the payload.json
file. This file can be saved where ever you choose, but the location must be specified in the create DID command used in Step 3. (By default, it will be saved under the project root directory.)
You should copy and paste the output of Step 1 as an initial starting template for your payload.json
file.
payload.json
filesThe below examples show the variation in syntax for different verification method key types in the DIDDoc payload file itself. Note that each key type has a slightly different output.
kms
(default local
): Key Management System (KMS) to be used for storage.
alias
: A human-friendly alias for the DID. Only used locally when referencing operations in Veramo CLI.
document
: Full body of the DID Document
versionId
: (optional): Custom versionId for the DID Document. If this is not set manually, then a UUID will be automatically generated for the DID Document version.
keys
: Keys used to sign the DIDDoc. These must match the ones specified in the DIDDoc, otherwise an error will be thrown.
fee
amount
: An array of coins, coins are represented as an object with 2 fields
denom
: ncheq (smallest denomination classification)
amount
: 50000000000 (This is 50 CHEQ by default and will not work with a different value)
gas
: Each transaction must specify the maximum amount of gas it may consume.
payer
(optional): The cheqd fee payer address
granter
(optional): The cheqd fee granter address, Provided the grantee has an allowance by the granter
Note that transaction fees are paid by the cheqd account set in the
agent.yml
configuration file, setup here. Each of cheqd's on-ledger identity transactions has a fixed fee, the pricing for cheqd DIDs and DID-Linked Resources can be found here. If your account has insufficient balance the transaction will fail.
If you do not specify the --argsFile
, you can also paste a JSON inline argument object by using the --argsJSON
flag followed by the JSON payload.
If your transaction is successful, you'll receive a success message along with the transaction details. You can query your DID using the instructions here to see the representation of your DID Document on-ledger.
If you are using testnet, you can top-up your testnet balance using our testnet faucet.
You can also configure your Keplr wallet to support cheqd testnet using the instructions here.
If you are using mainnet, you can purchase CHEQ tokens here.
Check out our troubleshooting guide for DID Operations to see common errors and fixes.
This tutorial offers step-by-step guidance on how to create a subject DID to be used for a holder that will receive a Verifiable Credentials.
⚠️ Before you begin...
It is also easily managable by a client agent as a full ledger backup for the writing of a DID / DID Doc is not required, thereby making it easily reproducable in a client environment.
This off-ledger DID, of type did:key
, is used for the recipient of the Verifiable Credential and Verifiable Presentation using:
did:key
provider and KMSSelect did:key
as the provider when prompted as well as a key management system (KMS) to use (default is local
).
The KMS is stored in a local SQLite database.
This is the nickname for your DID, which will be managed by Veramo KMS. Providing a memorable alias will help reference this for future uses, e.g., Alice off ledger DID
.
Once you have entered this, you will receive a response in a table, e.g:
If you got the table above, your off-ledger did:key
has been created
Follow these instructions to:
Generate identity keys on-the-fly WITH a draft DIDDoc
Generate standalone identity public/private keypairs
Convert identity key pairs generated using Veramo agent to other key encoding formats
⚠️ Before you begin...
Instead of creating identity keys standalone, you can generate them along with a DIDDoc template. This makes it far easier to handle different inputs and arguments, such as generating DID Docs with different key types.
You can use the following command in your CLI to create your DIDDoc and associated identity keys:
You can pass the payload of the inputs and arguments as a file rather than inline using:
You can reuse this example file:
Within this command, you are able to choose from the following inputs below to produce different types of DIDDocs:
Once you have submitted the command above, you should receive a DID Document draft template, including a set of identity keys, including your chosen inputs and arguments. You can find an example of this output below:
If you want to use identity keys outside of Veramo CLI, you can convert keys from one format to another.
For example, if you would like to convert from hex
to base64
, you can use the following generic approach:
This works with other encoding conversion libraries (i.e. multiformats
).
When you try to generate keys
along with DIDDoc
template using command below
If you encounter an error below
Unexpected token v in JSON at position 1
Create a .json
file (e.g. name it something like identity-keys-on-the-fly-with-did-docs.json
in same working directory level).
Copy and paste the content from below into your newly created .json
file. You can choose from any of the inputs and arguments below:
For example:
Then, instead of passing it as argument, we'll pass it as a file. Use command below to do it.
The above command will output something like this (i.e. a template DID DOC with the keys)
Then you can go back to your payload.json
file (if you didn't have one you can simply create one manually, and paste content below as template) which should be something like this at first.
Then you're going to update keys
and document
section of it (payload.json
) with keys
and didDoc
you generated in above step.
After populating keys
and document
section. Your payload.json
file should look something like this:
Assuming you have enough ncheq
tokens inside your wallet, you can now run the command below to create your DID.
If the above cmd
resulted something like this:
Account does not exist on chain. Send some tokens there before trying to query sequence.
This means you don't have enough tokens in your wallet.
After successfully creating your DID, you should see something like this:
Notice, controllerKeyId
is now the publicKeyHex
you generated the firstly. i.e did is know associated to you via publickKeyHex
or you're the controller of this the DID you created. 😄
Make sure you've correctly for Veramo CLI
We chose to use for the holder because the specification has a lot synergy with cheqd did method, .
Using also keeps holder DIDs off-ledger. This is very important for the privacy and data protection of the holder. If holder DIDs and DIDDocs were stored on-ledger, this could constitute a risk where data written within the DIDDoc could not be removed in line with a holder's right to be forgotten.
Creating a subject DID can be achieved through both the Veramo CLI, or directly through an application that has been setup to read and write to the cheqd ledger, using the Veramo SDK for cheqd.
The file used for the Veramo SDK for cheqd has a preloaded local key management system which is bootstrapped along with the CLI.
provider | alias | did |
---|
Make sure you've correctly for Veramo CLI
After running the above command, if you see an unexpected error, follow our to fix it. A common error is:
You can generate identity keys standalone in a plug-and-play format for future use in or transactions.
This guide provides common errors and potential fixes for them if you encountered errors when .
You can go to cheqd's to get your account some test tokens.
Create DID
Create an Issuer DID using the did:cheqd DID method over REST API.
Create Subject DID
Create a Subject DID using the did:key or did:vda DID methods.
Resolve DID
Resolve a DID to retrieve the associated DID Document.
DID Registrar
Simple setup for building cheqd DIDs into existing applications using REST APIs, building into the Universal Registrar.
Credential Service
Credential Service is a SaaS product offering the easiest and quickest way to issue Credentials, using REST APIs and very little integration effort.
Aries Framework JavaScript
Aries Framework JavaScript is an SDK which supports ZKCreds (AnonCreds) natively with cheqd support.
Walt.id SSI Kit
Walt.id SSI Kit is an SDK that supports the European Architecture and Reference Framework (ARF) standards for identity, with full cheqd support.
cheqd Cosmos CLI
Cosmos CLI which directly communicates with the cheqd network. This should only be used for testing environments.
did:key | Alice off ledger DID |
|
Follow the instructions for issuing a Verifiable Credential here, including the credentialStatus
information, as shown in the example below:
Where the values within the credentialSubject field are as follows:
The following process, or one generating the exact output, MUST be followed when validating a verifiable credential that is contained in a cheqd StatusList Resource.
Let credentialToValidate be a verifiable credentials containing a credentialStatus
entry that is a StatusList2021Entry, associated with an entry in a bitstring.
Let status purpose be the value of statusPurpose
in the credentialStatus
entry in the credentialToValidate.
Verify all proofs associated with the credentialToValidate. If a proof fails, return a validation error.
Verify that the status purpose matches the resourceType
value in the StatusList2021 Resource.
Let compressed bitstring be the value of the encodedList
property of the StatusList2021 Resource.
Let credentialIndex be the value of the statusListIndex
property of the bitstring in the StatusList2021 Resource.
Generate a revocation bitstring by passing compressed bitstring to the Bitstring Expansion Algorithm.
Let status be the value of the bit at position credentialIndex in the revocation bitstring.
Return true
if status is 1, false
otherwise.
Create Verifiable Credential Status List v2021 on cheqd
The Status List 2021 Specification indicates that it may be desirable to store the actual StatusList using something like a Content Distribution Network to lessen the load on the server maintained by the issuer to return a result in real-time.
Using cheqd's Resource Module, the same benefits may be achieved. In fact, storing a StatusList as an on-ledger Resource is a much better application of technology than using a Verifiable Credential for the same purpose.
By storing a StatusList on the cheqd Network as a Resource, it creates a much more resilient and decentralised mechanism for storing and maintaining the revocation/suspension status of Verifiable Credentials. The benefits of using the cheqd Resource module over traditional centralised architecture are detailed here.
Moreover, cheqd's Resource Module enables individual Resources to be referenced and retrieved using a DID URL in conformance with DID Core. This is being standardized at the Trust over IP Foundation within a specification called DID URLs for Digital Resources.
Using the cheqd Resource module, the same content and semantics of StatusList2021 can be replicated, with additional benefits of enabling DID Resolvers to fetch the contents of the StatusList.
You can follow the tutorial to create a DID and DID Document here.
Let's assume that the following DID is created.
Prepare a file with the StatusList2021 bitstring encodedList
and encode it into base64
, following the same generate algorithm as in the Status List2021 Specification.
Note: The uncompressed bitstring MUST be at least 16KB in size to maintain herd privacy for the holder.
UUIDs are used to identify Resources. On Unix systems, the uuidgen
tool can be used to generate a new UUID.
Where the fields within the payload have the following meaning:
Note: If an issuer wants to create multiple StatusLists within the same Collection, they must have unique and distinct names.
Once created, the StatusList2021 Resource will be associated with the parent DID, and referenced in the DID Document Metadata as follows:
An issuer may want to regularly update the bitstring whenever there is a certain amount of revocation status updates. The issuer will therefore need to create a new version for the initial StatusList2021 Resource.
Resources with the same Collection ID and name are grouped into version sets. Each resource in such a set has a link to the previous version (except the first version) and the next version (if it's not the most recent version).
To create a resource and mark it as a new version within a particular group, it is necessary to use the same collection-id, name
and type
as in the previous version. Links between versions will be created automatically.
New versions have dedicated unique IDs and can be referenced and retrieved as any other resources.
For example:
Resulting in the following metadata syntax:
Credo, formerly Hyperledger Aries Framework JavaScript (AFJ). with cheqd support
In the recent months Credo has heavily been expanding into a more modular and "less specific" framework. The integration with cheqd is a prime example of this, being the first true showcase of anchoring AnonCreds on non-Indy ledgers Supporting more credential formats, ledgers and DID methods is crucial and essential to the continual development of Credo. cheqd is now fully supported in Credo and can be used for the issuance of Verifiable Credentials as well as the creation of Credential Schemas and Credential Definitions.
Aries Framework JavaScript supports the following Credential formats:
Follow these instructions to create a new DID and publish the associated DIDDoc on cheqd ledger.
⚠️ Before you begin...
Follow exactly the same steps as the first resource. Note that to create a new resource version which belongs to the same set as a previous resource, in the you must specify the same:
collectionId
name
resourceType
Each resource in such a set has a link to the previous version (except the first version) and the next version (if it's not the most recent version).
New versions have dedicated unique IDs and can be referenced and retrieved as any other resources.
Follow these instructions to create a new DID-Linked Resource on cheqd mainnet or testnet.
⚠️ Before you begin...
DID-Linked Resources can be any type of file or content that is below ~200kb in size.
For the purpose of an example, lets use an AnonCreds schema (JSON file) as the resource:
Save this file locally and call it something like resource.json.
Prepare a file with resource and encode it into base64
. On Unix systems, you can use the following command input:
Expected output:
You will need to paste the output of the Base64 into the data
field of the payload.json
file as shown in step 5.
Once you have saved your Resource file locally, you can copy the path and enter it in the file
field of the payload.json
file as shown in step 5.
Before carrying out a Resource transaction, you will need to prepare the payload.json
file. This file can be saved wherever you choose, but the location must be specified in the create Resource command. (By default, it will be saved under the project root directory.)
kms
(default local
): Key Management System (KMS) to be used for storage;
payload
: Resource definition
collectionId
: The last fragment of the corresponding DIDDoc
id
: Use output from the previous step here
name
: Arbitrary human-readable string used to identify the resource
resourceType
: Resource type, such as CL-Schema
, JSONSchema2020
, etc
version
: (Optional) client-given resource version
alsoKnownAs
: (Optional) alternative URI(s) provided for the resource
data
: (Optional) base64 encoded data of resource file
signInputs
: Keys used to sign the corresponding DIDDoc. These must match the ones specified in the DIDDoc, otherwise an error will be thrown
verificationMethodId
: Verification method ID from DIDDoc where key is published
keyType
should match values that you used to create the DIDDoc
privateKeyHex
should match values that you used to create the DIDDoc
file
: (Optional) path to resource file
fee:
amount
: An array of coins, coins are represented as an object with 2 fields
denom
: ncheq (smallest denomination classification)
amount
: See section below on fees
gas
: Each transaction must specify the maximum amount of gas it may consume.
payer
(Optional): The cheqd fee payer address
granter
(Optional): The cheqd fee granter address, Provided the grantee has an allowance by the granter
The Payload file can include a Resource passed either as a file or a base64 encoded string:
The maximum file size for a resource is roughly 46KB which may require a gas fee of up to 2000000.
The fee for a resource transaction changes depending on the file type being passed to the ledger. Currently there are three different variations on the fee:
If you do not specify the --argsFile
in the previous step, you can also paste a JSON inline argument object by using the --argsJSON
flag followed by the JSON payload.
Property | Description |
---|---|
Parameter | Description |
---|---|
is a framework written in TypeScript for building SSI Agents and services that aims to be compliant and interoperable with the standards defined in the European Archicture and Reference Framework.
The Aries Framework JavaScript project has recently been rebranded to "Credo" and was moved from the Hyperledger Foundation to the .
AnonCreds using cheqd are facilitated using the .
Make sure you've correctly for Veramo CLI
Follow tutorial to generate keys and create a DID.
Follow tutorial to create the first version of the resource.
Follow tutorial as for resource creation, but use the same collectionId,
name
and resourceType
as for the previous Resource version.
"DID-Linked Resources" are identified with a with a that acts as a permanently-accessible link to fetch the resources from the cheqd ledger. We refer to this as the "resource ID". Through the "resource ID" or a set of DID URL query parameters, applications are able to persistently access a digital resource on the cheqd network.
Make sure you've correctly for Veramo CLI
Follow tutorial to generate keys and create a DID.
. On Unix systems, the uuidgen
tool can be used to generate a new UUID:
Note that transaction fees are paid by the cheqd account set in the agent.yml
configuration file, . If you do not specify a fee in the transaction, the ledger will automatically deduct the appropriate fee from the account set in youragent.yml
configuration. Each of cheqd's on-ledger identity transactions has a fixed fee, . If your account has insufficient balance the transaction will fail.
id
A specific DID URL dereferencing to the actual status of the Credential
type
The type
property MUST be StatusList2021Entry
statusPurpose
The purpose of the status entry MUST be a string. While the value of the string is arbitrary, the following values MUST be used for their intended purpose: revocation or suspension
statusListIndex
The statusListIndex
property MUST be an arbitrary size integer greater than or equal to 0, expressed as a string. The value identifies the bit position of the status of the verifiable credential.
statusListCredential
The statusListCredential
property MUST is a DID URL to a statusList Resource. When the URL is dereferenced, the resulting Resource MUST have type
property that includes the StatusList2021Credential
value.
collectionId
The unique identifier of the parent DID, to link the Resource to a particular DID
id
A UUID for the resource, to enable it to be specifically referenced and fetched
name
This must be a unique name indicating the type
of Status List,
but also a qualifying name for the List. For example: ExampleStatusList2021
resourceType
This must indicate the statusPurpose.
This value should be either: StatusList2021Revocation or StatusList2021Suspension
data
Base 64 encoded file containing the full bitstring for the StatusList
This is a location to record all high-level architecture decisions for identity features and functionality on cheqd network.
Architecture Decision Records directly linked to on-ledger functionality is documented separately on the cheqd ledger/node documentation site.
An Architectural Decision (AD) is a software design choice that addresses a functional or non-functional requirement that is architecturally significant.
An Architectural Decision Record (ADR) captures a single AD, such as often done when writing personal notes or meeting minutes; the collection of ADRs created and maintained in a project constitute its decision log.
ADRs are intended to be the primary mechanism for proposing new feature designs and new processes, for collecting community input on an issue, and for documenting the design decisions. An ADR should provide:
Context on the relevant goals and the current state
Proposed changes to achieve the goals
Summary of pros and cons
References
Note the distinction between an ADR and a spec. The ADR provides the context, intuition, reasoning, and justification for a change in architecture, or for the architecture of something new. The spec is much more compressed and streamlined summary of everything as it stands today.
If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match.
Use the ADR template when creating a new ADR.
cheqd Cosmos CLI
Cosmos-native CLI for creating transactions on cheqd. Should be used for testing purposes only.
Walt ID SSI Kit with cheqd support
SSI Kit is an Open Source SDK from walt.id which supports cheqd functionality, and other identity networks, via REST API calls or through a native CLI tool.
Walt.id run multiple SaaS offering for customers with varying levels of support and integration requirements.
In order to be able to onboard the did:cheqd
on testnet and mainnet, SSIKit relies on a cheqd universal registrar deployed on walt.id infrastructure. The DID will be created using a key imported into or also created with SSIKit.
SSI Kit natively supports the following Credential formats:
This ADR defines the cheqd DID method and describes the identity entities, queries, and transaction types for the cheqd network: a purpose-built self-sovereign identity (SSI) network based on the Cosmos blockchain framework.
Decentralized identifiers (DIDs) are a type of identifier that enables verifiable, decentralized digital identity. A DID refers to any subject (for example, a person, organization, thing, data model, abstract entity, and so on) as determined by the controller of the DID.
Hyperledger Indy is a verifiable data registry (VDR) built for DIDs with a strong focus on privacy-preserving techniques. It is one of the most widely-adopted SSI blockchain ledgers. Most notably, Indy is used by the Sovrin Network.
The Sovrin Foundation initiated a project called libsovtoken
in 2018 to create a native token for Hyperledger Indy. libsovtoken
was intended to be a payment handler library that could work with libindy
and be merged upstream. This native token would allow interactions on Hyperledger Indy networks (such as Sovrin) to be paid for using tokens.
Due to challenges the project ran into, the libsovtoken
codebase saw its last official release in August 2019.
The cheqd network aims to support similar use cases for SSI as seen on Hyperledger Indy networks, with a similar focus on privacy-resspecting techniques.
Since the core of Hyperledger Indy's architecture was designed before the W3C DID specification started to be defined, the Indy DID Method (did:indy
) has aspects that are not fully-compliant with latest specifications.
However, the rationale for why the cheqd team chose the Cosmos blockchain framework instead of Hyperledger Indy were primarily down to the following reasons:
Hyperledger Indy is a permissioned ledger: Indy networks are permissioned networks where the ability to have write capability is restricted to a limited number of nodes. Governance of such a permissioned network is therefore also not decentralised.
Limitations of Hyperledger Indy's consensus mechanism: Linked to the permissioned nature of Indy are the drawbacks of its Plenum Byzantine Fault Tolerant (BFT) consensus mechanism, which effectively limits the number of nodes with write capability to approximately 25 nodes. This limit is due to limited transactions per second (TPS) for an Indy network with a large number of nodes, rather than a hard cap implemented in the consensus protocol.
Wider ecosystem for token functionality outside of Hyperledger Indy: Due to its origins as an identity-specific ledger, Indy does not have a fully-featured token implementation with sophisticated capabilities. Moreover, this also impacts end-user options for ecosystem services such as token wallets, cryptocurrency exchanges, custodianship services etc that would be necessary to make a viable, enterprise-ready SSI ledger with token functionality.
By selecting the Cosmos blockchain framework, the maintainers of the cheqd project aim to address the limitations of Hyperledger Indy outlined above. However, with an eye towards interoperability, the cheqd project aims to use Hyperledger Aries for ledger-related peer-to-peer interactions.
Our aim is to support the functionality enabled by identity-domain transactions in by Hyperledger Indy into cheqd-node
. This will partly enable the goal of allowing use cases of existing SSI networks on Hyperledger Indy to be supported by the cheqd network.
The following identity-domain transactions from Indy were considered:
NYM
: Equivalent to "DIDs" on other networks
ATTRIB
: Payload for DID Document generation
SCHEMA
: Schema used by a credential
CRED_DEF
: Credential definition by an issuer for a particular schema
REVOC_REG_DEF
: Credential revocation registry definition
REVOC_REG_ENTRY
: Credential revocation registry entry
Revocation registries for credentials are not covered under the scope of this ADR. This topic is discussed separately in a future ADR as there is ongoing research by the cheqd project on how to improve the privacy and scalability of credential revocations.
Schemas and Credential Definitions are also not covered under the scope of this ADR. Their implementation is covered in ADR 002: DID-Linked Resources.
did:cheqd
)The method-name
for the cheqd DID Method will be identified by the string cheqd
.
A DID that uses the cheqd DID method MUST begin with the prefix did:cheqd
. This prefix string MUST be in lowercase. The remainder of the DID, after the prefix, is as follows:
The cheqd DID method's method-specific identifier (method-specific-id
) is made up of the namespace
component. The namespace
is defined as a string that identifies the cheqd network (e.g., "mainnet", "testnet") where the DID reference is stored. Different cheqd networks may be differentiated based on whether they are production vs non-production, governance frameworks in use, participants involved in running nodes, etc.
The namespace
associated with a certain network/ledger is stored in the genesis file on the node and cannot be changed by validators vote. A namespace is optional and can be omitted.
A did:cheqd
DID must be unique. The syntax of the unique-id
component may be defined as a Universally Unique Identifier (UUID) generated by the creator(s) of the DID. UUIDs are the preferred unique identifier format for cheqd network.
Usage of UUID-style identifiers significantly simplifies the generation and implementation of unique identifiers, with extremely-low probability of a collission where the same UUID is generated independently.
Any client application can generate these UUIDs using their own preferred implementation in any programming language, as opposed to the method-specific logic required for Indy-style DID identifiers.
Alternatively, the unique-id
may also be generated similar to the did:indy method
from the initial public key of the DID (e.g., base58 encoding of the first 16 bytes of the SHA256 of the first Verification Method Ed25519
public key). This unique-id
format is referred to as the "Indy-style" unique identifier in our documentation.
Support for Indy-style unique identifiers makes compatibility with Indy-based client SDKs, such as those based on Hyperledger Aries.
If no namespace
is specified, it assumed to be default namespace
for the network/ledger the request is targetted at. This will generally be mainnet
for the primary production cheqd network.
did:cheqd
methodThe cheqd DID method ABNF to conform with DID syntax guidelines is as follows:
Note: The
*id-char unique-id
must be 16 bytes of Indy-style base58 encoded identifier.
Where the formal definition of UUIDs is represented using this ABNF:
did:cheqd
identifiersA DID written to the cheqd "mainnet" ledger namespace
with an Indy-style identifier:
A DID written to the cheqd "testnet" ledger namespace
with an Indy-style identifier:
An Indy-style DID where no namespace is defined, where the namespace
would default to the one defined on ledger where it's published (typically, mainnet
):
A UUID-style DID on cheqd "mainnet" namespace
:
A UUID-style DID where no namespace is defined, where the namespace
would default to the one defined on ledger where it's published (typically, mainnet
):
A DID Document ("DIDDoc") associated with a cheqd DID is a set of data describing a DID subject. The representation of a DIDDoc when requested for production from a DID on cheqd networks MUST meet the DID Core specifications.
The following elements are needed for a W3C specification compliant DIDDoc representation:
@context
(optional): A list of strings with links or JSONs for describing specifications that this DID Document is following to.
id
: Target DID with cheqd DID Method prefix did:cheqd:<namespace>:
and a unique-id
identifier.
controller
(optional): A list of fully qualified DID strings or one string. Contains one or more DIDs who can update this DIDdoc. All DIDs must exist.
verificationMethod
(optional): A list of Verification Methods
authentication
(optional): A list of strings with key aliases or IDs
assertionMethod
(optional): A list of strings with key aliases or IDs
capabilityInvocation
(optional): A list of strings with key aliases or IDs
capabilityDelegation
(optional): A list of strings with key aliases or IDs
keyAgreement
(optional): A list of strings with key aliases or IDs
service
(optional): A set of Service Endpoint maps
alsoKnownAs
(optional): A list of strings. A DID subject can have multiple identifiers for different purposes, or at different times. The assertion that two or more DIDs refer to the same DID subject can be made using the alsoKnownAs
property.
"diddoc:<id>" -> {DIDDoc, DidDocumentMetadata, txHash, txTimestamp }
didDocumentMetadata
is created by the node after transaction ordering and before adding it to a state.
Each DID Document MUST have a metadata section when a representation is produced. It can have the following properties:
created
(string): Formatted as an XML Datetime normalized to UTC 00:00:00 and without sub-second decimal precision, e.g., 2020-12-20T19:17:47Z
.
updated
(string): The value of the property MUST follow the same formatting rules as the created property. The updated
field is null
if an Update operation has never been performed on the DID document. If an updated property exists, it can be the same value as the created property when the difference between the two timestamps is less than one second.
deactivated
(string): If DID has been deactivated, DID document metadata MUST include this property with the boolean value true
. By default this is set to false
.
versionId
(string): A UUID string that represents the version identifier of the DID Document.
resources
(list of resources metadata referred to as Resource previews)| optional. Cannot be changed by CreateDID or UpdateDID transactions. cheqd ledger stores only the resource identifiers in the DID Doc metadata. The remainder of the resources' metadata is added when a DID is resolved.
previousVersionId
(string): A UUID string that represents the version identifier of the previous version of the DID Document. The previousVersionId
field is an empty string if an Update operation has never been performed on the DID document
nextVersionId
(string): A UUID string that represents the version identifier of the next version of the DID Document. The nextVersionId
field is an empty string if an Update operation has never been performed on the DID document
Verification methods are used to define how to authenticate / authorise interactions with a DID subject or delegates. Verification method is an OPTIONAL property.
id
(string): A string with format did:cheqd:<namespace>#<key-alias>
controller
: A string with fully qualified DID. DID must exist.
type
(string)
publicKeyJwk
(map[string,string]
, optional): A map representing a JSON Web Key that conforms to RFC7517. See definition of publicKeyJwk
for additional constraints.
publicKeyBase58
(optional): A base58-encoded string.
publicKeyMultibase
(optional): A base58-encoded string that conforms to a MULTIBASE encoded public key.
Note: A single verification method entry cannot contain more than one of publicKeyJwk
, publicKeyBase58
and publicKeyMultibase
, but must contain at least one of them.
Services can be defined in a DIDDoc to express means of communicating with the DID subject or associated entities.
id
(string): The value of the id
property for a Service MUST be a URI conforming to RFC3986. A conforming producer MUST NOT produce multiple service entries with the same ID. A conforming consumer MUST produce an error if it detects multiple service entries with the same ID. It has a follow formats: <DIDDoc-id>#<service-alias>
or #<service-alias>
.
type
(string): The service type and its associated properties SHOULD be registered in the DID Specification Registries
Since cheqd-node is built using the Cosmos SDK, the data stored directly on ledger is formatted in Protobuf and is transformed back into compliant JSON client-side on request.
Example of how cheqd-node stores verification_method
id
(string): A string with format did:cheqd:<namespace>#<key-alias>
controller
: A string with fully qualified DID. DID must exist.
verification_method_type
(string): A string that represents type of verification method. Supported: Ed25519VerificationKey2018
, Ed25519VerificationKey2020
, JsonWebKey2020
.
verification_material
(string): It represents the exact decoded string value of public key for the verification method. Supported types of public key representations are: publicKeyBase58
, publicKeyMultibase
, publicJwk
.
This operation updates the DID Document associated with an existing DID of type did:cheqd:<namespace>
.
signatures
: UpdateDidRequest
should be signed by all controller
private keys. This field contains a dict
structure with the key URI from DIDDoc.authentication
, as well as signature values.
id
: Fully qualified DID of type did:cheqd:<namespace>
.
versionId
: Transaction hash of the previous DIDDoc version. This is necessary to provide replay protection. The previous DIDDoc versionId
can fetched using a get DID query.
controller, verificationMethod, authentication, assertionMethod, capabilityInvocation, capabilityDelegation, keyAgreement, service, alsoKnownAs, context
: Optional parameters in accordance with DID Core specification properties.
This operation deactivates the DID for a given did:cheqd:<namespace>
. Once deactivated, a DID cannot be re-activated or any DIDDoc update operations carried out.
id
: Fully qualified DID of type did:cheqd:<namespace>
.
signatures
: DeactivateDidDocRequest
should be signed by all controller
private keys. This field contains controller key URIs and signature values.
DIDDocs associated with a DID of type did:cheqd:<namespace>
can be resolved using the GetDidDoc
query to fetch a response from the ledger. The response contains:
did_doc
: DIDDoc associated with the specified DID in a W3C specification compliant DIDDoc structure.
metadata
: Contains the MUST have DIDDoc metadata associated with a DIDDOc.
DID resolution requests can be sent to the Tendermint RPC interface for a node by passing the fully-qualified DID.
The response is returned as a Protobuf, which can be converted to JSON client-side.
For creating a new DID or update the DIDDoc associated with an existing DID, the requested should be signed by all controller
signatures.
To update a DIDDoc fragment without a controller
(any field except VerificationMethods
), the request MUST be signed by the DID's controller
(s).
To update a DIDDoc fragment that has its own controller
(s), the request MUST be signed by the DID's controller
(s) and the DIDDoc fragment's controller
(s).
Changing the controller
(s) associated with a DID requires a list of signatures as before for changing any field.
One of the key design decisions in the cheqd DID method is to use separate sets of key pairs for Cosmos / node layer transactions and identity payloads.
Keypairs and accounts on the Cosmos node layer are public, and can be crawled/explored by inspecting transactions on a node or through a block explorer. This therefore poses a privacy risk through correlation, if the identity payloads were signed using the same keys.
By splitting the keys/accounts for the two layers, we account for identity payloads being signed using keys that can be kept off-ledger.
This also allows for uses cases where the key owners/controllers at the identity layer are different than the key/account owners at the Cosmos node layer. In essence, that this allows is it removes the need for a DID's controllers to also have an account on the cheqd network ledger.
Further discussion on how these boundaries are separated in implementation, with one specific implementation library, is described in cheqd node ADR 003: Command Line Interface (CLI) tools
NYM
transactions to DID
transactionsNYM is the term used by Hyperledger Indy for DIDs. cheqd uses the term DID
instead of NYM
in transactions, which should make it easier to understand the context of a transaction easier by bringing it closer to W3C DID terminology used by the rest of the SSI ecosystem.
role
field from DID transactionsHyperledger Indy is a public-permissioned distributed ledger and therefore use the role
field to distinguish transactions from different types of nodes. As cheqd networks are public-permissionless, the role
scope has been removed.
ATTRIB
transactions droppedATTRIB
was originally used in Hyperledger Indy to add document content similar to DID Documents (DIDDocs). The cheqd DID method replaces this by implementing DIDDocs for most transaction types.
To support the cheqd Resource Module, cheqd ledger includes a reference to resource previews within the DIDDoc metadata.
Identity entities and transactions for the cheqd network may differ in name from those in Hyperledger Indy, but aim enable equivalent support for privacy-respecting SSI use cases.
The differences stem primarily from aiming to achieve better compliance with the W3C DID Core specification and architectural differences between Hyperledger Indy and Cosmos SDK (used to build cheqd-node
).
With better compliance against the DID Core specification, the goal of the cheqd DID method is to maximise interoperability with compatible third-party software librarires, tools and projects in the SSI ecosystem.
The cheqd DID method does not aim to be 1:1 compatible in API methods with did:indy
. It makes opinionated choices to not implement certain transaction types, which in our analysis have been superseded by new developments in the W3C DID Core specification.
Support for Indy-style DID unique identifiers is intended to provide a compatibility mode with existing Indy-based client applications.
cheqd-node
release v0.1.19 and earlier had a transaction type called NYM
which would allow writing/reading a unique identifier on ledger. However, this NYM
state was not fully defined as a DID method and did not store DID Documents associated with a DID. This NYM
transaction type is deprecated and the data written to cheqd testnet with legacy states will not be retained.
Design decisions defined in this ADR aim to make the cheqd DID method compliant with the W3C DID Core specification.
Usage of UUID-style identifiers significantly simplifies the generation and implementation of unique identifiers, since any client application can generate these UUIDs using their own preferred implementation in any programming language, as opposed to the method-specific logic required for Indy-style DID identifiers.
As the client/peer-to-peer exchange layer (at least in the implementation provided by VDR Tools SDK) is built on a library that supports Hyperledger Aries, extending Aries implementations to other W3C compliant DID methods should become simpler for the SSI ecosystem.
Trying to maintain backwards-compatibility with Hyperledger Indy APIs means some functionality will not be available for legacy client applications which cannot support non-Indy DID Document elements, e.g., multiple verification methods in the same DIDDoc.
DID transaction operations at the moment must be assembled using a client-side library with DID specification identity standards support, and then wrapped up inside a Cosmos transaction that is sent to the Tendermint RPC or Cosmos SDK gRPC interface. We aim to build client apps/SDKs that can be used by developers to make the process of interacting with the ledger simpler.
Hyperledger Indy official project background on Hyperledger Foundation wiki
indy-node
GitHub repository: Server-side blockchain node for Indy (documentation)
indy-plenum
GitHub repository: Plenum Byzantine Fault Tolerant consensus protocol; used by indy-node
(documentation)
Indy DID method (did:indy
)
Hyperledger Aries official project background on Hyperledger Foundation wiki
aries
GitHub repository: Provides links to implementations in various programming languages
aries-rfcs
GitHub repository: Contains Requests for Comment (RFCs) that define the Aries protocol behaviour
Cosmos blockchain framework official project website
cosmos-sdk
GitHub repository (documentation)
libsovtoken
: Sovrin Network token library
For example, did:cheqd:testnet:DAzMQo4MDMxCjgwM
can be fetched using the native Cosmos SDK REST API endpoint (or equivalent endpoints). This provides responses that would meet the abstract definition of a resolve
function as defined in the DID Core specification.
As you can see in the response body above, this is the raw Protobuf fetched from the cheqd testnet ledger, marshalled into a JSON form. Crucially, this form has certain deviations from the JSON/JSON-LD production expected in DID Core specification:
DID Core properties with empty values are still shown in this JSON, whereas the requirement is to drop them from standards-compliant DIDDoc representations.
For example, a resolveRepresentation
function could derive a valid standards-compliant representation of did:cheqd:testnet:ea2b76cf-a118-403a-8f49-244e56c9dcb8
from the above resolve
function. The response would be similar to the one below containing Resolution Metadata, DIDDoc, and DIDDoc Metadata:
This objective has certain advantages:
Updates to DID Resolver code can be carried out and released independently of cheqd-node releases. As a consequence, there's no need to go through an on-ledger governance vote, and voting period to make a change to resolveRepresentation
.
A separate web service module would allow for flexibility in how to handle complex scenarios on DID URL Dereferencing, error code handling for DID URL requests, and safely handling content transport for various media types.
Making the DID Resolver a standalone, non-ledger module allows for an operator of this web service to independently scale their service horizontally and vertically.
We explored two architectural patterns for how a DID Resolver could be implemented for the cheqd ledger. The objective here was to explore and provide DID resolution operators multiple approaches for running resolution service, each with their own pros and cons (which are discussed below).
"Full" cheqd DID Resolver
Data retrieved would be in the native Protobuf representation as stored on ledger, thus allowing data integrity computations to be made.
"Light" cheqd DID Resolver
However, a limitation of Cloudflare Workers is they do not allow a gRPC request to be made to an external endpoint. This would force the "Light" cheqd Resolver to use the gRPC-Web / REST endpoint resolve
implementation to fetch data from the ledger. This could be considered a higher risk profile in terms of data integrity by resolver operators / client applications.
The Full cheqd DID Resolver is able to use github.com/cheqd/cheqd-node
as a Golang module for send resolve
requests to a cheqd node instance to fetch DIDDoc / Resources from the ledger.
Since the Full cheqd DID Resolver is wrapped for usage as a Docker container image using the Universal Resolver specification, the end-to-end sequence diagram for our DID Resolver would look like below:
The Full cheqd DID Resolver is designed to handle requests concurrently, while reducing the risk of large quantities of threads and requests blocking the efficiency of the on-ledger services.
Figure 2: "Full" cheqd DID Resolver class diagram
Marshalling/unmarshalling requests back-and-forth between Protobuf and JSON is carried out by services in the "Full" DID Resolver
Given the drawbacks associated with a Light cheqd DID Resolver being unable to send gRPC requests to a cheqd node instance, the decision was taken to (initially) implement the Full cheqd DID Resolver architecture. Future work might separately consider and design a Light DID Resolver profile that can work with Cloudflare Workers while also allowing deployment through Docker.
did:cheqd
Operators should be able to configure gRPC endpoints for mainnet as as testnet (or any other cheqd network namespaces) so that a single DID Resolver instance can resolve requests to any network. (E.g., grpc.cheqd.net
for mainnet, grpc.cheqd.network
for testnet)
For each supported cheqd network namespace (e.g., mainnet, testnet), operators should be able to define one or more upstream cheqd node gRPC endpoints. (E.g., additional fallback endpoints besides grpc.cheqd.net
for mainnet.) In case any one of the upstream endpoints is unavailable, this allows the DID Resolver to try a different upstream gRPC endpoint for resiliency.
Operators should be able to define whether their gRPC pull/request is secure (default, carried out over HTTP.2 with TLS handshake) or insecure (optional, equivalent to a grpcurl -plaintext
connection downgrade). This accommodates scenarios where gRPC endpoints may not necessarily be equipped to handle TLS handshakes, since the default Cosmos SDK / cheqd node configuration endpoints do not have TLS certificates defined.
Not applicable, since this would be the first release of cheqd DID Resolver
Full cheqd DID Resolver reuses existing code to handle some parts of resolve and representing DIDDocs.
Third-party applications that want to implement their own DID Resolver implementations for cheqd can consume the current implementation as a Golang module (e.g., import "github.com/cheqd/cheqd-did-resolver/services"
).
Universal Resolver driver implementation provides a standardised way of incorporating did:cheqd
into Universal Resolver instances that support multiple DID methods.
Lack of a Light cheqd DID Resolver, at least initially, might not give an easy and computationally-cheap alternative to running Docker containers.
The DID create/update/deactivate functions raise architectural questions around key management, since they typically involve the generation and use of private keys and other secrets.
The DID registrar can operate in the following modes:
Internal Secret Mode
External Secret Mode
In this mode, the DID Registrar is responsible for generating the DID controller cryptogprahic keys used in DID operations. Therefore, a DID Registrar used in this mode is considered a highly trusted component which should be fully under the control of a DID controller. If it is operated as a remotely hosted service, secure connection protocols such as TLS, DIDComm, etc. MUST be used.
In this mode, the DID Registrar does not itself have access to the cryptographic keys used in DID operations, but it has a way of accessing an external wallet in order to perform cryptographic operations such as generating signatures.
In this mode, the DID Registrar does not itself have access to the cryptographic keys used in DID operations, but it will ask the client to perform operations such as generating keys and signatures in a separate action from using the Registrar.
In the above diagram you can see the following steps
Request Operation
The client requests a DID operation providing the required fields
Return JobId and Serialized Payload
The registrar responds with a JobId and a base64 encoded serialized payload
The serialized payload should be signed by all the verificationMethods belonging to the controllers of the DID Document
Submit JobId and SigningResponse
Submit the JobId and the SigningResponse's to the same api
Validate signature and Complete Operation
The registrar validates the signature for the provided DID Document
Submits the DID operation request to the network
The payload can also be created using our helper endpoint /1.0/did-document
, which requires the following options to construct the DID Document payload
Verification Method Type
Method Specific Algorithm
Network
PublicKey Hex encoded string
Endpoint: /1.0/update
Only setDidDocument operation is supported in the cheqd-did-registrar. To update a DID Document, fetch the body of the DID Document you want to change from the DID Resolver, make the relevant updates and pass it to the request operation.
Endpoint: /1.0/deactivate
Endpoint: /1.0/{:did}/create-resource
Provide an existing DID as the path parameter, and the request body with resource name, type and base64 encoded data
This ADR defines how resources (e.g., text, JSON, images, etc) can be created and referenced using a persistent and unique did:cheqd
DID URL.
Each resource will be linked with a DID Document, with create/update operations controlled using the specified verification methods in the associated DID Document.
Common types of resources that might be required to issue and validate Verifiable Credentials are:
More broadly, there are other resources that might be relevant for issuers and verifiers in a self-sovereign identity exchange:
DIDs could be tampered by compromising the hosting provider: DIDs and DID Documents ("DIDDocs") stored at a centralised web endpoint can be compromised and replaced by malicious actors.
Hosting providers could unilaterally cease to host particular clients: Hosting providers could terminate accounts due to factors such as non-payment of fees, violation of Terms of Service, etc.
Single point-of-failure in resiliency: Even for highly-trusted and sophisticated hosting providers who may not present a risk of infrastructure being compromised, a service outage at the hosting provider can make a DID anchored on their systems inaccessible.
The issues highlighted above a material difference to the longevity of Verifiable Credentials.
Example schema.org address with full URLs
Using traditional web endpoints to store resources (such as schemas) that are critical for a Verifiable Credential to function undermines the benefits that persistently-accessible Decentralized Identifiers offer.
We took the following design principles into consideration, along with an explanation of how we addressed them:
Built using existing, familiar DID Core Spec patterns: Wherever possible, our design attempts to utilise existing patterns and behaviours within the W3C DID Core specification (such as the use of DID URLs to identify resources), instead of trying to implement proprietary/custom approaches. We believe that similar designs could be adopted by other DID methods if they choose.
Protection against linkrot for long-term retrieval: Any Resource stored on-ledger is replicated across multiple nodes.
If any individual node or endpoint is down, lookup requests can be sent to any other node on the network.
Extensible by default: Our objective was to build a flexible design pattern that allowed developers to define and extend their own resource types. Trying to control what kinds of resources could be written to ledger would make the ledger-side logic complex. Instead, we opted for a design where the cheqd ledger acts agnostically to store resources, as long as correctly authorised, as a permanently-accessible endpoint.
Design for DID-spec "dumb" as well as DID-spec "smart" client applications: Many approaches in this space assume that client applications must be adept at parsing DIDDocs and resolving complex inter-DIDDoc relationships. We saw describing resources using DIDDocs as metadata about the resource which could be independently-parsed by "smart" client applications; while also providing a fallback approach for "dumb" client applications. We internally considered this as "What if an identity wallet understood how to parse JSON, but didn't understand the DID Core spec?"
Version controlled: The ability to evolve a resource over time is critical for identity use cases. As described above, examples of this include when identity document schemas change, logos evolve, etc. Current approaches (such as Hyperledger Indy CredDefs) deal with this by creating entirely new, unlinked resources. We designed to make it easy, using existing DID Core specification techniques, so that client applications could query "What was the version of a resource with this name on this date/time?"
Resources on cheqd ledger are collated under Resource Collections, which are defined as a list of resources linked to and controlled using a DID Document ("DIDDoc").
To create a new Resource, a client application first needs to create a DID (or use an existing not deactivated DID along with its associated DIDDoc.) This DID-Linked Resource is the lowest, direct level of create/update/deactivate operation control that exists.
This allows a specific Resource version to be referenced in a Verifiable Credential, as well as allowing client applications to query historical/updated Resource versions along with metadata that describes how the Resource evolved within a Resource Collection.
Once a Resource has been created under a Resource Collection, the parent DIDDoc will automatically have an updated didDocumentMetadata section, including linkedResourceMetadata.
The syntax of the linked Resource metadata is as follows:
Importantly, we decided not to populate the actual resource data into the didDocumentMetadata, but instead, what we refer to as a Resource Preview which contains all the metadata about the associated resources.
Resource previews will aopear within DIDDocMetadata. These do not include the actual core data of the resource and only reference the metadata:
Resource Collection ID: (did:cheqd:...:) (supplied client-side)**
Resource ID: UUID ➝ specific to resource, also effectively a version number (supplied client-side)
Resource Name: String (e.g., CL-Schema1
(supplied client-side))
Resource Type (supplied client-side)
Resource Version (supplied client-side)
MediaType: (e.g. application/json
/image
/application/octet-stream
/text/plain
) (computed ledger-side)
Created: XMLDatetime (computed ledger-side)
Checksum: SHA-256 (computed ledger-side)
previousVersionId: empty string if first, otherwise ID as long as Name, ResourceType, and MimeType match previous version (computed ledger-side)
nextVersionId: empty string if first/latest, otherwise ID as long as Name, ResourceType, and MimeType match previous version (computed ledger-side)
Also known as: a list of alternative URIs that can be used to get the resource.
Example:
The rationale for linking to Resources in this manner, instead of creating a new top-level section, are as follows:
In practice, we noted that client applications capable of DID Resolution will gracefully fail/ignore unknown Service types. Client applications that do understand a particular Service type can continue parsing/resolving content they are designed to handle.
Historical versions of Resources can always be accessed by traversing forwards/backwards in the Resource Collection by checking if a particular Service ID has old/new versions.
Multi-party control on Resource Collection updates is possible, since DIDs with multiple controllers specified in them already handle this scenario. In the normal process of updating a DIDDoc with multiple controllers, rules can be defined by client applications and/or the ledger on whether all controllers sign an update, or whether an m-of-n threshold needs to be applied. (Currently, the cheqd ledger requires all controllers to sign off on updates.)
Example of referencing a resource using the service section:
To create a new DID-Linked Resource, a client application first needs to create a DID (or use an existing DID along with its associated DIDDoc). This DID-Linked Resource is the lowest, direct level of create/update/deactivate operation control that exits.
Each request to create a Resource must provide the following parameters, supplied by the client application:
Resource Collection ID: (did:cheqd:...:) (supplied client-side)
Resource ID: UUID ➝ specific to resource, also effectively a version number (supplied client-side)
Resource Name: String (e.g., CL-Schema1
(supplied client-side))
Resource Version: String (OPTIONAL). It is a human-readable semantic version for the Resource (e.g., 1.0.0
(supplied client-side))
alsoKnownAs: (OPTIONAL) a list of alternative URIs that can be used to get the resource.
In addition to the above client-provided parameters, the ledger-side code will populate the following additional header fields (for properly-authenticated requests):
MediaType: (e.g. application/json
/image
/application/octet-stream
/text/plain
) (computed ledger-side) This is based on the file extension of the associated resource file.
Created: XMLDatetime (computed ledger-side)
Checksum: SHA-256 (computed ledger-side)
previousVersionId: an empty string if first, otherwise ID as long as Name, ResourceType, and MimeType match previous version (computed ledger-side)
nextVersionId: an empty string if first/latest, otherwise ID as long as Name, ResourceType, and MimeType match previous version (computed ledger-side)
Example using the Veramo CLI:
This section will delineate between expected inputs in JSON and how the cheqd ledger stores the resource input in protobuf
collectionId
: (did:cheqd:...:)<identifier>
(supplied client-side) ➝ unique identifier from DIDDoc.
id
: UUID representing resource ID ➝ specific to resource, also effectively a version number (supplied client-side)
name
: String (e.g., CL-Schema1
(supplied client-side))
version
: String (OPTIONAL) ➝ a human-readable semantic version for the Resource (e.g., 1.0.0
(supplied client-side))
data
: Bytes representing a user data (supplied client-side)
alsoKnownAs
(supplied client-side) a list of alternative URIs for the SAME Resource
signInputs
: Signatures of the corresponding DID Document's controller(s) (supplied client-side).
Resource
is stored on-ledger in protobuf. This is converted back to JSON client side.
Collection ID
: String - an identifier of linked DIDDoc.
Returns collection of resources
created by the specific collection ID
. This is converted to JSON on the client side.
Collection ID
: String - an identifier of linked DIDDoc
ID
: String - unique resource id
Returns Resource
with a given collection ID
and ID
. This is converted to JSON client side.
Collection ID
: String - an identifier of linked DIDDoc
ID
: String - unique resource id
Returns resource's metadata
with a given collection ID
and ID
.
resources-metadata:<collection-id>:<resource-id>
➝ Metadata
<collection-id>
is the last part of DID. It can be UUID, Indy-style or whatever is allowed by ledger. It allows us to evolve over time more easily.
<resource-id>
is a unique resource identifier on UUID format
resources-data:<collection-id>:<resource-id>
➝ Data
<collection-id>
is the last part of DID. It can be UUID, Indy-style or whatever is allowed by ledger. It allows us to evolve over time more easily.
<resource-id>
is a unique resource identifier on UUID format
Input:
Output:
Processing logic:
Check that associated DIDDoc exists;
Authenticate request the same way as DIDDoc creation and updating;
Validate properties;
Validate that ID is unique;
Set created date time;
Set previousVersion
and nextVersion
if this is a new version (a resource with the same collection-id, resource-name and resource-type exists);
Compute checksum;
Persist the resource in state;
cheqd Cosmos CLI Example:
payload-file
: path to the payload file:
resource-data-file
: path to the resource file (e.g.: /path/to/resource.jpeg
)
Input:
Output:
Processing logic:
Retrieves the whole resource collection for the specified DID;
Returns only resource headers (without data
field);
cheqd Cosmos CLI Example:
Input:
Output:
Processing logic:
Retrieves a specific resource by Collection-ID and resource ID;
cheqd Cosmos CLI Example:
Input:
Output:
Processing logic:
Retrieves all resource versions by collection id, resource id
Returns a resource's metadata from a collection with a given collection_id and id
cheqd Cosmos CLI Example:
Resource are immutable, but it is possible to create new versions of it under a new identifier(id
field). When creating a resource whose fields collection_id
, name
and resource_type
match an existing resource:
The latest version of the current resource will be added with a link to the new one. That is, field next_version_id
will contain the new resource identifier.
A new resource with data from the transaction will be created with the previous version resource id in field previousVersionId
.
Example:
Step 1. Resource exists in the ledger:
Step 2. Client send request for creating a new resource with a transaction MsgCreateResource
Step 3. After the transaction is applied
Immutability:
Resources on-ledger are immutable, so can't be destroyed;
Limitations
Resource size is now limited by maximum tx/block size;
Limitations
Introduce module level resource size limit that can be changed by voting
A new module will be created: resource
.
It will have cheqd
module as a dependency.
Will be used for DIDs existence checks.
Will be used for authentication
Simple setup for building cheqd DIDs into existing applications using REST APIs, building into the .
Aries Framework JavaScript is an SDK which natively with cheqd support.
Category | Status |
---|---|
Category | Status |
---|
The defines how DIDs are created and read from ledger. According to the , DID methods are expected to provide .
The is designed to implement the for method.
The DID Resolution specification prescribes that a conforming DID method must be able to produce.
All conforming DID resolvers implement resolve
and resolveRepresentation
abstract functions, as defined in the .
The resolve
function is intended to fetch the abstract form of the DID Document, as stored on the ledger. This abstract/raw form as the underlying data persistence layer where the DIDDoc is stored for any particular method might use different serialisation/storage formats.
Since , the underlying data storage and retrieval ("resolve") mechanisms used rely on those offered by the . Cosmos SDK .
Cosmos SDK framework typically provides and functionality.
In case of the cheqd network testnet, an instance of this resolve
endpoint through the Cosmos SDK REST API would be which returns the following response:
JSON key names that correlate to DID Core properties are listed in , rather than as required. This is because Protobuf standard linting rules require these properties to be defined in snake_case
.
The resolveRepresentation
abstract function, as defined in DID Core specification, is intended to address concerns similar to the ones highlighted above to product a of a DIDDoc.
As described above, the abstract resolve
function is already available for the cheqd ledger via the default Cosmos SDK gRPC/REST API endpoints. Our primary objective with building a DID Resolver for cheqd was to design this resolveRepresentation
piece as a standalone component that was not packaged within the .
Since the / Cosmos SDK is written in Golang, this resolver would consist of Golang libraries imported from the existing ledger code. This promotes code reuse.
Data would be fetched from the ledger using the gRPC endpoint on a node, which allows it (by default) to take place over an encrypted channel .
Universal Resolver drivers are designed to be run as Docker containers. A limitation of this approach is that the computation footprint of a compute resource can be quite high, e.g., a Docker container may be 100 MB+ in size and .
Thus, our "Light" DID Resolver idea was to explore using , a lightweight serverless compute platform. As a comparison, and . (We use Cloudflare Workers in , for example.)
Cloudflare Workers can also be deployed outside the Cloudflare service in a Docker container using . This could be used to provide a Docker container deployment option for the Universal Resolver did:cheqd
driver.
Both of the architectural patterns above are designed so that a could be created. The Universal Resolver project aims to provide a common REST API definition for DID Resolution where each DID method can provide a Docker container that with an easy-to-deploy mechanism for the specific DID method.
Figure 1: "Full" cheqd DID Resolver sequence diagram ()
Since Cosmos SDK SDK encodes data in Protobuf, the DID Resolver "" them to JSON. The software class diagram below describes how these components/methods are tied together:
Figure 3: "Full" cheqd DID Resolver Protobuf <-> JSON marshalling ()
Compiled packages/binaries for the Full cheqd DID Resolver will be made available as a Docker container image with standardised Docker Compose configuration as defined in the to provide an easy mechanism for DID Resolution operators to incorporate did:cheqd
as one of the supported DID methods they handle.
Use of a custom DID URL path (e.g., /1.0/identifiers/{did}/resources/{resource-id}
can be non-standard). Efforts should be made to see if this can implemented instead using DID URL queries according to the .
recommendation
specification
guide
Category | Status |
---|
The defines how DIDs are created and read from ledger. According to the , DID methods are expected to provide .
The is designed to implement the for method to enable create/update/deactivate DID operations easily.
The also supports the creation of for example, schemas, credential definitions, status lists, trust registries and logos.
Client Managed Secret Mode
The cheqd DID Registrar only supports the , considering the security and scalability of the registrar. The workflow for all the operations follows the protocol below:
Endpoint: /1.0/create
Provide a DID Document payload according to the in the request body.
recommendation
specification
guide
Category | Status |
---|
describes . In a self-sovereign identity (SSI) ecosystem, such resources are often required in tandem with , which is a standard way of representing portable digital credentials that represent claims about its subjects and can be verified via digital proofs.
Schemas: Describe in a machine-readable format. Prominent examples of this include , , etc.
Status lists: Allow recipients of a Verifiable Credential exchange to for validity. Prominent examples of this include the specification, , , etc.
Visual representations for Verifiable Credentials: Although Verifiable Credentials can be exchanged digitally, in practice most identity wallets want to present "human-friendly" representations. This allows the credential representation to be shown according to the brand guidelines of the issuer, , etc. Examples of this include the , (".pkpass
"), , etc.
Figure 1: Mobile boarding passes in Apple Wallet showing different visual styles (source
Such visual representations can also be used to quickly communicate information visually during identity exchanges, such as airline mobile boarding passes. In the , the pass at the front is for a "Gold" loyalty status member, whereas the pass at the back is for a "standard" loyalty status member. This information can be represented in a Verifiable Credential, of course, but the example here uses the Apple Wallet / Google Wallet formats to overlay a richer, "human-friendly" display.
Documents related to SSI ecosystems: , which would typically be a text file, a , PDF etc. This, for example, can enable parties building self-sovereign identity ecosystems to use DIDs to reference Governance Frameworks they conform to, at different levels of the technical stack.
Logos: Issuers may want to provide authorised image logos to display in relation to their DID or Verifiable Credentials. Examples of this include (which is used by to show logos for validators) and "" (commonly used to set the logo for websites in browser tabs).
Decentralized Identifiers (DIDs) are often stored on ledgers (e.g., , ), distributed storage (e.g., in ), or non-ledger distributed systems (e.g., ).
DIDs can be stored on traditional centralised-storage endpoints (e.g., , ) but this comes with certain drawbacks:
See from major cloud providers: , , , , , ...\
Source: . Figure 2: Graph showing drop in Facebook traffic from their global service outage in 2021 (source: ).
In particular, also functionality. This highlights the risks of "contagion impact" (e.g., ) of centralised digital systems - even ones run by extremely-capable tech providers.
Link rot: "Link rot" happens when over time, URLs become inaccessible, either because the endpoint where the content was stored is no longer active, or the URL format itself changes. The graph below from shows degradation over time of URLs.
Figure 3: Linkrot analysis over 1996-2019 by New York Times (source: )_
For example, a passport ( issued as a Verifiable Credential anchored to a DID (regardless of whether the DID was on-ledger or not) might stop working if the credential schema, visual presentation format, or other necessary resources were stored off-ledger on traditional centralised storage.
Despite these issues, many self-sovereign identity (SSI) implementations - even ones that use ledgers / distributed systems for DIDs - often utilise centralised storage. From the :
In a catastrophic scenario where the network itself stops to exist, e.g., companies shutting down, getting acquired etc the on-ledger data can still be restored by digital archivists using ledger snapshots. A practical example of this is how which can be restored. While this can be cumbersome, we wanted to design for this as a fail-safe.
Make re-use of resources simple: We liked the concept of in the sense that it promotes a common, machine-readable specification. Therefore, our design allows for patterns where the controllers of a DID can reference resources created by other DID owners/controllers, e.g., referencing a pre-existing schema. Taking this line of thought further, it allows for an arbitrary depth of how resources can be nested, as long as they are discoverable/resolvable.
Notalltypes of resources should be stored on a ledger...but can be made discoverable through similar design patterns: Distributed ledgers are great for redundancy, but the cost of this duplication (in terms of storage required by node, block size, transaction finality speeds, etc) can be quite significant. For instance, a distributed ledger is probably not the best storage and retrieval mechanism for a video file (which can run into many GBs/TBs); or even a PDF larger than a few MBs. cheqd network . This can be updated via an on-ledger vote, but the trade-off of asking node operators to provision ever-expanding storage would be not ideal. Our design therefore restricts the file/payload size of on-ledger resources (in our case, ~190 KB - giving enough room for transaction data besides the resource itself), while allowing the same techniques below to be used for describing off-ledger resources. E.g., references . We recognise and accept that DID owners/creators may choose to use their own centralised/decentralised storage, and the design patterns described below accommodate that.
Figure 4: Overview of Resource and Resource Collection creation )
Individual Resources are uniquely identified by a common Resource Name and common Resource Type that MUST remain consistent across versions. The specific version number of a Resource is described using the Resource ID, which is a . Since UUIDs can be generated by any compatible software library, client applications are able to define this version number independent of the cheqd ledger. This same technique and rationale is described in .
Once a Resource has been created under a Resource Collection, the linked DIDDoc can be updated to provide a link to access it in the .
Client applications capable of doing may have strong architectural assumptions to only expect the default DID Core specification sections in a response. We considered the possibility that such applications might (incorrectly) reject the entire DIDDoc as malformed, or crash in the process of trying to parse the DIDDoc.
On the other hand, is designed to be flexible and extensible by design. New DID Service types can be registered through by anyone. We suggest a new service type called LinkedResource should be used to reference any resource on cheqd within the service section. This is conceptually similar to the existing .
DIDDocs can reference other DIDDocs, such as when the in one DIDDoc is specified as a in another DIDDoc. These links can be traversed using .
Since the , this provides another layer of access control by allowing DIDDoc controllers to rotate keys, if required.
Figure 5: Detailed sequence diagram of Resource creation on cheqd .
Resources must be under the maximum block size restrictions to be able to fit into a transaction. Currently this is plus additional headroom for metadata that needs to be described in the ResourceHeader
.
Resource Type: (e.g JSONSchema 2020, supplied client-side. It is recommended that new Resource Types are included in the )
resourceType
: a string representing type of resource (supplied client-side). It is recommended that new Resource Types are included in the .
specification
official specification
official project website
GitHub repository ()
official project background on Hyperledger Foundation wiki
GitHub repository: Server-side blockchain node for Indy ()
GitHub repository: Plenum Byzantine Fault Tolerant consensus protocol; used by indy-node
()
(did:indy
)
official project background on Hyperledger Foundation wiki
GitHub repository: Provides links to implementations in various programming languages
GitHub repository: Contains Requests for Comment (RFCs) that define the Aries protocol behaviour.
Authors
Ankur Banerjee, Alexandr Kolesov, Alex Tweeddale, Brent Zundel, Renata Toktar, Richard Esplin
ADR Stage
ACCEPTED
Implementation Status
Implemented
Start Date
2021-09-23
Last Updated
2023-02-06
Create a DID
Create a fully conformant DID using SSI Kit.
Issue a Credential
Issue a fully W3C conformant Credential using walt.id CLI or over REST API.
Verify a Credential
Verify a fully W3C conformant Credential using SSI Kit.
JSON (JWT)
JSON Web Token (JWT) Credentials are a simple way to transmit Trusted Data as a JSON object.
JSON-LD
JSON-LD (Linked Data) Credentials are a richer data format, allowing applications to follow embedded links to other pieces of Linked Data across the web.
Authors | Alex Tweeddale, Renata Toktar, Ankur Banerjee, Andrew Nikitin |
ADR Stage | PROPOSED |
Implementation Status | In Progress |
Start Date | 2022-02-22 |
Last Updated | 2023-04-25 |
Authors | Daev Mithran |
ADR Stage | ACCEPTED |
Implementation Status | In Progress |
Start Date | 2023-01-30 |
Last Updated | 2023-01-30 |
Authors | Ankur Banerjee, Alexandr Kolesov, Alex Tweeddale, Renata Toktar |
ADR Stage | ACCEPTED |
Implementation Status | Implemented |
Start Date | 2021-09-23 |
Last Updated | 2023-02-06 |
Rules and architecture of DID resolver to handle DID URL queries, paths and fragments
The did:cheqd
method ADR defines how DIDs are created and read from ledger. According to the W3C DID Core specification, DID methods are expected to provide standards-compliant methods of DID and DID Document ("DIDDoc") production.
The cheqd DID Resolver is designed to implement the W3C DID Resolution specification for did:cheqd
method.
Part of the W3C DID Resolution specification is the notion of DID URL Dereferencing whereby a DID URL identifies either a primary or secondary resource which is returned directly.
When you resolve a DID you get a DID Document.
When you dereference a DID, you may get the DID Document, a portion of a DID document, or the resource at the end of a service endpoint (if the DID contains a service component).
You can only resolve a DID to return a DID document, and you can only dereference a DID reference to return whatever resource is referenced.
Normal dereferencing can be conceived in two steps:
A DID is resolved to a DID Document;
A resource within / associated with the DID Document is identified, based on the portion of the DID URL that follows the DID (path, query, fragment as defined by the ABNF in section 3.2 of the DID 1.0 specification.).
Endpoint: /1.0/identifiers/<did>
Current implementation returns here the full DIDDoc as in example. By default, in didDocumentMetadata
section will be the metadata for the latest version of DIDDoc and the list of all resources.
Endpoint: /1.0/identifiers/<did>#example
If a DID URL contains a fragment #
. the logic is similar to the general web browser logic where #
symbols can be used for linking to the particular document section.
For the DIDDoc, you can equate a specific section within a webpage to a specific section inside the DIDDoc, for example verificationMethod
. To resolve to a particular section, we need to use a request which specifies the section itself.
Take the example excerpt from a DIDDoc below:
Here, to dereference to this verificationMethod, we need to pass key-1
as a fragment parameter:
Example:
All the queries can be divided into 2 main groups:
Queries for fetching a resource referenced within the DIDDoc body.
Queries for fetching an external resource associated with the DIDDoc, referenced within the DIDDoc metadata.
Note: in instances where there is no versionId
or versionTime
parameters specfied, we have set the default dereferencing rules to fetch the latest version of a resource, if it is uniquely identified by the parameters in the query.
Common parameter validation
parameters metadata
and resourceMetadata
are designed to be a bool variables, like true
or false
.
parameters versionTime
and resourceVersionTime
are designed as string representation of time and can be in 2 formats, RFC3339 and RFC3339Nano. Examples are ("2006-01-02T15:04:05Z07:00" and "2006-01-02T15:04:05.999999999Z07:00")
Here we have an ability to specify different parameters to filter to particular parts of a DIDDoc.
All queries can be chained together to make very specific requests using &
within the request format. This makes query parameters particularly powerful because they can be used to fetch specific parts of a DID Document or specific resources associated with a DID Document.
For example, the example below queries a particular service endpoint associated with a particular DIDDoc version.
VersionId
If the user knows the particular versionId
he could ask about it by adding the query versionId=<uuid of DIDDoc version>
It can be combined with any other queries for building more complex requests. linkedResourceMetadata
will contain only resources which were active for this version. In other words, resource which were created before the next version in terms of timeline.
Example:
VersionTime
The user could ask resolver for the nearest DIDDoc which was created/updated before versionTime
value. The logic about linkedResourceMetadata
is the same. Here, resolver figure out what the versionId
is the nearest one for versionTime
and shows all the active resources. If you want to file resources also, you can use resourceVersionTime
parameter and combine the query with versionTime
.
Example:
TransformKeys
The transformKeys parameter changes the representation of verificationMethod
section in DIDDoc. It allows you to change publicKey
representation into the one of next variants. To do so, just pass the parameter transfromKeys
with one of the following values:
Ed25519VerificationKey2020
Ed25519VerificationKey2018
JsonWebKey2020
Example:
Service
Service - is a DIDDoc section which includes serviceEndpoint
field with URL inside. As a result, pair service=<service-id>
will redirect to the serviceEndpoint
value.
Example:
RelativeRef
relativeRef
is an additional part for serviceEndpoint
and can be used only with service parameter. It combines serviceEndpoint
URL with relativeRef
value and does the redirect to the URL.
Example:
Metadata
By default, without metadata=true
pair DID-resolver
returns only particular DIDDoc. If you want to specifically fetch only the metadata for a DIDDoc, you can pass an additional query. It can be helpful in the instance, for example, where you want to get all the resources which were created for the exact versionId
or before versionTime
.
Example:
NotFoundError
raises if there is now resource/metadata with requested set of parameters or the result is ambiguous
RepresentationNotSupported
raises if there are:
unsupported query parameters
value for parameters are empty
unsupported transformKeys
value
metadata
or resourceMetadata
parameter has value not only true
or false
relativeRef
parameter is used without service
one. They must be used only together
InvalidDidUrl
raises if there are:
versionId
or resourceId
are not valid UUID strings
versionTime
or resourceVersionTime
are not in RFC3339 or RFC3339Nano formats.
resourceVersionTime
is used without any other resource parameters.
cheqd's ADR: 002 DID-Linked Resources introduces a new concept to the SSI ecosystem - namely, resources that can be associated with a DID and fetched using existing DID URL dereferencing patterns.
The diagram below shows how a DID-Linked Resource sits beneath a DID and can be fetched using a DID URL.
Requests to fetch on-ledger cheqd Resources are considered as a DID URL Dereferencing scenario it uses DID URL paths to lead to a Resource object, rather than a DIDDoc.
On the other hand, on-ledger cheqd Resources metadata requests are handled like DID URL Resolution since the result is a subsection of didDocumentMetadata
specific to that resource.
API endpoints related to on-ledger cheqd Resources are described below. All of these request types are GET
requests, with POST
and PUT
requests disallowed.
Returns the Resource data/payload stored on ledger for specified resource. HEAD
request type is also allowed for this endpoint since it can be used for HTTP content negotiation phase by client applications. In this case, only the HTTP Response headers are returned without the body.
Endpoint: /1.0/identifiers/<did>/resources/<resource_id>
Request HTTP headers
Accept
should allow */*
or match the mediaType
of the Resource
Accept-Encoding
may be allowed compression methods (e.g., gzip
, compress
, etc.)
Response HTTP headers
Status code 200 OK
Content-Type
should be set to mediaType>
of the Resource
Content-Encoding
should be set to a valid content compression method in Accept-Encoding
and response compressed accordingly
Content-Length
should be set to the Resource size, in decimal bytes
Response HTTP body
Resource, encoded correctly according to the mediaType
Return metadata for a specified resource. This is effectively a portion of the DIDDoc Metadata block.
Endpoint: /1.0/identifiers/<did>/resources/<resource_id>/metadata
Returns metadata for all Resources directly linked to/controlled by a DID. This is effectively the full linkedResourceMetadata
section in DIDDoc Metadata block.
Endpoint: /1.0/identifiers/<did>/resources/all
Alternative endpoints
/1.0/identifiers/<did>/resources/
Status code 301
Redirect to /resources/all
/1.0/identifiers/<did>/resources
Throw an invalidDidUrl
error
Here we have an ability to specify different parameters to filter to particular DID-Linked Resources.
Like with DIDDoc query parameters, these can all be chained together to create complex requests for specific DID-Linked Resources at particular points in time or associated with particular DIDDoc versions.
It is important to understand how our resolver logically handles more complex dereferencing requests. We have set some baseline defaults and rules to ensure a logical and consistent experience for clients who use our resolver.
Ambiguity generally throws an error
If the request specifies a parameter where there are multiple potential results, such as where the DID has two resources of the same resourceType
('String') but resourceName
is not the same, an error will be thrown because there is not enough information to discern which resource is being requested.
Multiple versions of the same resource
If there are multiple resources with the same resourceType
and resourceName
but with different versionIds,
and there is no parameter specified to fetch a particular version, the resolver will fetch the latest resource by default.
This is because the query is not ambiguous in terms of discerning which set of resources to dereference to, but is only ambiguous in terms of which version of that resource to fetch.
Ambiguity + resourceMetadata=true
If there is an ambiguous query, such as where there are two resources with the same name but different types, AND there is a resourceMetadata=true parameter, resource data pertaining to all the resources which could potentially be seen as being ambiguous will be returned.
For example, in the below example, there are multiple resources with the resourceType= string
, but with different resourceName
parameters:
ResourceId
ResourceId
parameter can be used for filtering a particular resource version by specifically identifying its unique ID.
Example:
ResourceCollectionId
resourceCollectionId
parameter filters all the resource by collectionId
field. By default cause we are asking for resources for a particular DID it already includes all the resource with the same collectionId
and this parameter can used mostly as sanity check. Without resourceMetadata=true
parameter will return the latest created resource if there is only one resource or an unambiguous resource.
Example:
ResourceType
This parameter is also just a filter by Type
field through resources. But there is a corner case if the user asks about exact resource (exact data). If after applying all the parameters in request several resources are left with the same Name
- the latest one will be responded. Otherwise - error NotFoundError
will be raised.
Example:
ResourceName
Behavior of this parameter is similar with resourceType one. If there is no ambiguous resource, it will be fetched. Otherwise greater specifity is required.
Example:
ResourceVersion
This parameter filters by Version
field. We introduced it with latest network upgrade and can be optionally set to identify a version of a resource with a particular string.
Example:
ResourceVersionTime
Important: This parameter must always be accompanied by another resource query qualifier.
The main goal here is to get the nearest resource for resourceVersionTime
value. "Nearest" means that if we are asking for time between resource1
and resource2
were created - resource1
will be returned. In case if requested resourceVersionTime
is before the first resource created - NotFoundError
will be returned. The most useful use-case here is checking that some "Credential" (driver's license) was active at resourceVersionTime
(was not revoked from Revocation Registry for example).
Example:
Checksum
It just checks that checksum
is the same as resource's metadata and also can used as a sanity check. For example, if the user knows what is exact checksum then it may be checked before actual downloading.
Example:
ResourceMetadata
This parameter a kind of modifier which works in the same manner as metadata but applies to resources. It allows to get only Metadata information about resource(s) without downloading. Also it changes the flow for resourceType
and resourceName
parameters and general meaning of this parameter - just filter. So, here it allows to create a chain of parameters and apply all of them to the resourceCollection and get only interested resource metadata. Possible variants:
resourceMetadata=true
resourceMetadata=false
Unused
Example:
The cheqd DID Resolver complies with the rules and algorithm defined in Decentralized Identifier Resolution (DID Resolution) v0.3. This section clarifies and expands some descriptions specific to cheqd.
The DID Resolution specification HTTP(S) bindings section states that:
If the output of the DID URL dereferencing function contains the
didDocumentStream
:
If the value of the
Accept
HTTP header is absent orapplication/did+ld+json
(or other media type of a conformant representation of a DID document):
The HTTP response status code MUST be
200
.The HTTP response MUST contain a
Content-Type
header. The value of this header MUST beapplication/did+ld+json
(or other media type of a conformant representation of a DID document).The HTTP response body MUST contain the
didDocumentStream
, in the representation corresponding to theAccept
HTTP header.
Since the cheqd DID Resolver APIs are REST APIs, the default Content-Type: application/did+ld+json
encoding is used if the Accept
header is not explicitly set since it matches the Accept: */*
header that most client applications send.
Accept
header is application/did+ld+json
OR blank OR */*
Response HTTP headers
Status code 200 OK
Content-Type: application/did+ld+json
Response HTTP body
didDocument
/ contentStream
contains @context
section;
didResolutionMetadata
/ dereferencingMetadata
contentType
field is application/did+ld+json
Accept
request HTTP header contains application/ld+json;profile="https://w3id.org/did-resolution"
Response HTTP headers
Status code 200 OK
Content-Type: application/ld+json;profile="https://w3id.org/did-resolution
Response HTTP body
didDocument
/ contentStream
contains @context
section;
didResolutionMetadata
/ dereferencingMetadata
contentType
field is application/ld+json;profile="https://w3id.org/did-resolution
Accept
request HTTP header contains application/did+json
Response HTTP headers
Status code 200 OK
Content-Type: application/did+json
Response HTTP body
didDocument
/ contentStream
DOES NOT contain @context
section;
didResolutionMetadata
/ dereferencingMetadata
ContentType
field is application/did+json
The DID Resolution specification defines an algorithm for how invalid DID URL Resolution/Dereferencing errors should be handled. The cheqd DID Resolver aims to implement all of these scenarios, with the correct HTTP Response status codes based on the specific error encountered.
The DID resolution output should always conform to the following format: ( didResolutionMetadata, didDocument, didDocumentMetadata )
If the resolution is unsuccessful, the DID resolver should return the following result:
didResolutionMetadata
contains "error" : "<Error message>"
didDocument
: null
didDocumentMetadata
: []
The DID dereferencing output should always conform to the following format: ( dereferencingMetadata, contentStream, contentMetadata )
dereferencingMetadata
contains "error" : "<Error message>"
contentStream
: null
contentMetadata
: []
You should run your own registrar to perform DID Operations on the Mainnet.
Environment variables needed for the Registrar are
FEE_PAYER_TESTNET_MNEMONIC
: The cosmos payer mnemonic for the Cheqd Mainnet
FEE_PAYER_MAINNET_MNEMONIC
: The cosmos payer mnemonic for the Cheqd Tesnet, By default it's the Testnet Faucet
LOCAL_STORE_TTL
(default: 600
): The time in seconds for the registrar to store data in cache
PORT
(default: 3000
): The port number
Clone the repository
Build Docker container image using Dockerfile:
Run the Docker container (modify according to your own build tags and other desired parameters):
REST API service for creating cheqd DIDs and DID-Linked Resources
The aim of the Universal Registrar is similar to the Universal Resolver; to transform method-specific APIs for DID transactions into a common format for client applications to easily call.
Therefore, the barrier for integrating cheqd DIDs into existing client applications has been greatly reduced by the Registrar. Instead of having to integrate with the cheqd SDK, applications can now create a simple workflow to call the relevant APIs for issuing, updating or deactivating cheqd DIDs and creating DID-Linked Resources.
There are plenty of other places you can go to get started creating cheqd DIDs. Simply pick the option which is best suited for your needs:
These instructions will help developers create DIDs on cheqd using the DID Registrar.
5 minutes!
Enter the below command in the cli
Select the following options:
Select VerificationMethodType
Select MethodSpecificAlgo
Select network
Enter the publicKeyHex value generated in the previous step
Figure 2: Creating a DID payload from template
Copy the didDoc
field from the output.
Use /create
to publish the DID
Paste the contents of didDoc
from the previous step in the didDocument
field of the /create
api body
Click on execute to perform the request
This response requests an action
for you to sign the serialized payload again in a CLI. This is a security feature which means you are not passing your private key to the Registrar. Note down the serialized payload, jobId from the response
Sign the serialized payload in your CLI with the below command
Fill in the prompts
keyRef: Enter the kid of the keyPair generated in the first step
algorithm: Ed25519
data to sign: Paste the serialized payload from the previous step
enconding: Select base64
NOTE: If there are n verification methods for the controller then n signatures are required to publish a DID.
Copy the Result value from the response.
Use the /create
api again
Create the payload using the following values
jobId
secret
signingResponse
verificationMethodId
signature
Click on Execute
The state in didState should be finished
in the response, the DID is created successfully
You can check your DID on the universal resolver or by going to https://resolver.cheqd.net/1.0/identifiers/{yourDID}
Category | Status |
---|---|
Parameter | Type | Description |
---|---|---|
Parameter | Type | Description |
---|---|---|
This page describes how to use and set up the software package.
If you do not want to install anything and just want to test it using our testnet, you can load the REST API endpoint for in your browser.
The is an open source application created by the which aims to make it far easier to create, update and deactivate across a range of DID Methods without full integration.
Not only does it make it easier for client applications to support DIDs from multiple DID methods, but it also makes it far quicker and easier to create, update and deactivate DIDs — as it calls the with a common API.
Any framework for creating keys and signing payloads, such as ;
cheqd
Figure 1:
This tutorial will be using the Veramo CLI for Key management. Setup the cli following this
Go to and click "try it out" in the top right corner.
Authors
Alex Tweeddale, Abdulla Ashurov, Andrew Nikitin
ADR Stage
PROPOSED
Implementation Status
DRAFT
Start Date
2023-06-05
Last Updated
2023-06-06
versionId
A string that conforms to a method specific unique identifier format.
Used to filter to a specific version id of the DIDDoc
versionTime
A JSON String serialized as an XML Datetime normalized to UTC 00:00:00 and without sub-second decimal precision.
Used to filter to a specific version of the DIDDoc at a point in time
service
Using a string from the serviceid
property within the DID document, this will dereference to the associated serviceEndpoint
Used to navigate to a serviceEndpoint of a DIDDoc, using the serviceId as a query parameter
transformKeys
A string that identifies the intended key type
Used to transform the verificationMethod key material into a different key type, based on the same cryptographic curve
relativeRef
A string that identifies a particular "secondary" resource appended to the serviceEndpoint
Used to fetch a specific part of a serviceEndpoint, such as a particular heading on a website
metadata
Used to fetch the metadata associated with a particular DIDDoc
resourceId
A string that conforms to a method specific unique identifier format.
The unique identifier of a particular DID-Linked Resource
resourceCollectionId
A string that conforms to a method specific unique identifier format.
Can be used to query all resources associated with a DID if combined with resourceMetadata=true
resourceName
A string
The specific name of a DID-Linked Resource
resourceType
A string
The specific type of a DID-Linked Resource
resourceVersionTime
A JSON String serialized as an XML Datetime normalized to UTC 00:00:00 and without sub-second decimal precision.
Used to fetch a version of a resource at a specific point in time
checksum
A string
Used to specify a particular resource checksum to demonstrate it is untampered
resourceMetadata
Used to fetch metadata related to a specific resource or group of resources
did:cheqd
using our DID ResolverThis page describes how to use and set up the cheqd DID Resolver software package.
If you do not want to install anything and just want to resolve a did:cheqd
entry from the ledger, you can load the REST API endpoint for resolver.cheqd.net in your browser.
Or, make a request from terminal to this hosted REST API:
Spinning up a Docker container from the pre-built did-resolver
Docker image on Github is as simple as the command below:
To configure the resolver, modify the values under the environment
section of the Docker Compose file. The values that can be edited are as follows:
MAINNET_ENDPOINT
: Mainnet Network endpoint as string with the following format" <networks>,<useTls>,<timeout>
. Example: grpc.cheqd.net:443,true,5s
networks
: A string specifying the Cosmos SDK gRPC endpoint from which the Resolver pulls data. Format: <resource_url>:<resource_port>
useTls
: Specify whether gRPC connection to ledger should use secure or insecure pulls. Default is true
since gRPC uses HTTP/2 with TLS as the transport mechanism.
timeout
: Timeout (in seconds) to wait for before any ledger requests are considered to have time out.
TESTNET_ENDPOINT
: Testnet Network endpoint as string with the following format" <networks>,<useTls>,<timeout>
. Example: grpc.cheqd.network:443,true,5s
RESOLVER_LISTENER
`: A string with address and port where the resolver listens for requests from clients.
LOG_LEVEL
: debug
/warn
/info
/error
- to define the application log level.
Our DID Resolver uses the Cosmos gRPC endpoint from cheqd-node
to fetch data. Typically, this would be running on port 9090
on a cheqd-node
instance.
You can either use public gRPC endpoints for the cheqd network (such as the default ones mentioned above), or point it to your own cheqd-node
instance by enabling gRPC in the app.toml
configuration file on a node:
Note: If you're pointing a DID Resolver to your own node instance, by default cheqd-node
instance gRPC endpoints are not served up with a TLS certificate. This means the useTls
property would need to be set to false
, unless you're otherwise using a load balancer that provides TLS connections to the gRPC port.
You can build your own image using docker build
Uncomment the build
section in the docker/docker-compose.yml
file. This relies on the Dockerfile
above but uses Docker Compose syntax to customise the build:
Make sure you comment out the pre-existing image
property that pulls in a container image from Github Container Registry, as shown above.
You can also do just a build with:
The instructions to configure and run the resolver are the same as when using the pre-built image.
did:cheqd
via Universal ResolverThe resolver.cheqd.net API endpoint is run by the cheqd team and only handles did:cheqd
credentials.
If you want to resolve DIDs from multiple DID methods, the Universal Resolver project provides a multi DID method resolver.
You can make resolution requests to a pre-existing Universal Resolver endpoint, such as dev.uniresolver.io, to their REST API endpoint:
You can also run your own instance of Universal Resolver, using the Docker Compose file of the project.
The Universal Resolver quick start guide provides instructions on how to do this:
Follow these instructions to create a new Resource linked to a DID using DID registrar. This tutorial will use the cheqd did regisrtar swagger API's and the Veramo CLI.
⚠️ Before you begin... Make sure you've completed creating a DID for this tutorial for Veramo CLI
Use the /{did}/create-resource
api to publish a new DID-Linked Resource
Paste the DID in the did path parameter
Generate request body by providing name, type and base64 encoded data
Click on execute to perform the request
This response requests an action
for you to sign the serialized payload again in a CLI. This is a security feature which means you are not passing your private key to the Registrar. Note down the serialized payload, jobId from the response.
Sign the serialized payload in your CLI with the below command
Fill in the prompts
keyRef: Enter the kid of the keyPair generated in the first step
algorithm: Ed25519
data to sign: Paste the serialized payload from the previous step
enconding: Select base64
NOTE: If there are n verification methods for the controller then n signatures are required to publish a resource.
Copy the Result value from the response.
Use the /create-resource
api again
Create the payload using the following values
jobId
secret
signingResponse
verificationMethodId
signature
Click on Execute
The state in didState should be finished
in the response, the DID is created successfully
You can check your DID on the Universal Resolver or by going to: https://resolver.cheqd.net/1.0/identifiers/{yourDID}/resources/{yourResourceId}
Service for resolving DIDs and dereferencing DID-Linked Resources
DID methods are expected to provide standards-compliant methods of DID and DID Document ("DIDDoc") production.
The cheqd DID Resolver is designed to implement the W3C DID Resolution specification for did:cheqd
method. It also supports full DID URL dereferencing, defined in our ADR here.
Our DID resolver is a package which can be implemented directly into clients' own infrastructure as a library written in Golang. This provides full support for cheqd's resolver, and can be run by anyone, creating a secure and client-controlled environment for resolving cheqd DIDs.
Our DID resolver is also available as a supported driver in Universal Resolver, a project maintained by DIF which hosts drivers of many different DID Resolvers in a compatible and easy-to-integrate format (Docker Containers).
Having multiple implementations of a DID Resolver accommodates for different clients, developers and customers - each with different needs. The flexibility and modular architecture exhibited here will allow cheqd DIDs to be resolved simply and securely within closed, controlled ecosystems with tight security protocols - as well as by community members who want to try our our identity functionality. Catering to both parties' needs makes the cheqd DID Resolver valuable in both everyday use, and for enterprise use.
You can see our resolver in action, resolving our first DID here:
cheqd AnonCreds Object Method Specification
cheqd intends to directly support AnonCreds using its DID-Linked Resource module in an AnonCreds Object Method. With its resource module, cheqd will identify each on-ledger resource with a DID Core compliant DID URL. This DID URL will be able to be dereferenced in order to fetch the resource and associated metadata.
While AnonCreds are only one flavour of Verifiable Credentials, they are currently in a functional state and are heavily used by cheqd's partners. Other Credential types, such as JSON-LD with BBS+ signatures, can provide a lot of equivalent functionality, but are currently not production ready.
Therefore, it is important for cheqd to provide support for AnonCreds in order to enable partners with existing clients using AnonCreds to use cheqd and existing Indy ledgers concurrently, within existing applications.
Our aim is to support the functionality enabled by identity-domain transactions in by Hyperledger Indy into cheqd-node
. This will reach the goal of allowing use cases of existing SSI networks on Hyperledger Indy to be supported by the cheqd network.
Importantly, we want to make sure that this work is done in a manner which brings AnonCreds closer to W3C compliance and wide-scale interoperability.
cheqd support for Ledger-Agnostic AnonCreds schemas
Schemas are used to list a set of attributes. Issuers of Verifiable Credentials may reference schemas within Credentials they issue in order to provide a layer of semantic interoperability with other issuers utilising the same schema.
If you are not familiar with the latest Ledger-Agnostic AnonCreds Schema structure, click the collapsible tile below to learn about the new format.
cheqd resources implementation uses the following path-based syntax:
did:cheqd:mainnet:<SchemaIssuerId>/resources/<SchemaId>
The cheqd AnonCreds object method uses a UUID to identify the Schema Object Content.
For example, the following DID URL is cheqd's representation of a schemaId
:
did:cheqd:mainnet:7BPMqYgYLQni258J8JPS8K/resources/6259d357-eeb1-4b98-8bee-12a8390d3497
The request format may be specific to each AnonCreds Object Method. However, the response format should be standardised to enable any AnonCreds supported application to understand the object, without needing custom or method-specific logic.
The cheqd schema request format comprises of:
A Resource file for the Schema object content (e.g. degreeSchema.json
); and
A Payload file (including the signing keys and additional inputs to create a DID-Linked Resource).
Both of these inputs are required to provide the ledger enough information to:
Before creating any on-ledger transaction, it is important to assemble the required Schema Object Content and save it as a file locally.
In the example below, the content should be saved as a JSON file, for example: degreeSchema.json
with the following content:
The Payload file utilises the inputs from the Resource file where possible, mapping common fields across. The Payload file may also require additional inputs to be provided by the creator to create a DID-Linked Resource for inputs not provided in the Resource file.
Below is an example of a Payload file:
For example, the full request format using a CLI should be structured as follows:
Once you have created your resource on cheqd, the following metadata will be generated in the DID Document Metadata associated with did:cheqd:mainnet:7BPMqYgYLQni258J8JPS8K
This can either be compiled by the associated SDK handling cheqd AnonCreds, or it can be assembled by the cheqd DID resolver.
The cheqd DID resolver will use the following logic to compile the standardised response format:
If "resourceType=anonCredsSchema" then append "issuerId" to the beginning of the Response Format for the resource presented
Existing DID Resolvers will be able to query for any AnonCreds Object Content using the following parameters:
Credo is an SDK which and regular Verifiable Credentials natively with cheqd support.
Walt.id SSI Kit is an SDK that supports the standards for identity, with full cheqd support.
In the , schemas are written directly to a , rather than using a centralized service such as . Schemas are also referenced within Credential Definitions, which are used to link the schema, issuer and holder together ().
This documentation will guide an implementor of AnonCreds on cheqd on how the cheqd AnonCreds Object Method defines the structure of , the and the .
Each specific AnonCreds identifier must be defined within an AnonCreds Object Method in the .
This means that an AnonCreds Schema Object ID does not need to be formatted in any particular syntax in the latest version of the .
In the , the Schema Object Content which is required to be written to the Verifiable Data Registry, contains the following information:
issuerId
- the of the schema. MUST adhere to rules.
cheqd uses to identify individual resources, associated with a DID, using fully resolvable DID URLs.
It is important to differentiate between the Request format for creating an AnonCreds object on cheqd, and the Response format, for how an AnonCreds objectshould be compiled by SDKs and the .
Populate a ; and
Compile a standardised AnonCreds schema object in the .
This Schema Resource file inputs should be replicated where possible within the Payload file, to populate a stored on cheqd, with the following mapping:
Resource file field | Payload file field |
---|
When passing the Payload file to the ledger, additional inputs may be required within the Payload file to populate the . In this instance, the only additional information required is:
Additional parameter | Expected input | Rationale |
---|
Using the and associated , the ledger has enough information to compile the following data structure as a response format.
To create a schema on cheqd, you should follow the , and pass the relevant JSON file for the object in the transaction.
Parameter | Type | Example |
---|
publisher DID
: is a . The DID of the Schema Publisher.
name
: is a , the name of the schema
version
: is a , the version of the schema in format. The three part, period (“.”) separated format MAY be enforced.
This legacy format is now attributed to the
Setup DID Resolver
Setup an instance of our DID Resolver to run it in your own environment.
DID Resolver ADR
Learn about the architecture for the cheqd DID Resolver and its different modes.
DID URL Dereferencing ADR
Understand how cheqd supports complex DID URL dereferencing for DIDs and DID-Linked Resources.
Schemas
Create Schemas using DID-Linked Resources to support AnonCreds on cheqd.
Credential Definitions
Create CredDefs using DID-Linked Resources to support AnonCreds on cheqd.
Revocation Registry Definitions
Create Revocation Registry Definitions using DID-Linked Resources to support AnonCreds on cheqd.
Revocation Status Lists
Create Revocation Status Lists using DID-Linked Resources to support AnonCreds on cheqd.
"name" | "name" |
"version" | "version" |
"resourceType" | "anonCredsSchema" | The Payload file drawing inputs from the Resource file does not provide the ledger the requisite amount of information to create a full DID-Linked Resource. resourceType must be provided as an additional input parameter |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceId=0f964a80-5d18-4867-83e3-b47f5a756f02 |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceName=degreeLaw |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceName=degreeLaw&resourceType=JSONSchema2020 |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceName=degreeLaw&resourceVersionId=1.3.1 |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceName=degreeLaw&resourceType=JSONSchema2020&versionTime=2015-03-11T05:30:02Z |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?versionId=0f964a80-5d18-4867-83e3-b47f5a756f02 |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceName=degreeLaw&resourceType=JSONSchema2020&versionTime=2018-07-19T08:40:00Z |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?linkedResource=true // note that this would only be a valid query if there is ONLY ONE resource associated with the DID and DID Document. |
| did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceName=degreeLaw&resourceType=JSONSchema2020&versionTime=2018-07-19T08:40:00Z&resourceMetadata=true or, did:cheqd:46e2af9a-2ea0-4815-999d-730a6778227c?resourceMetadata=true // note that this would only be a valid query if there is ONLY ONE resource associated with the DID and DID Document. |
" | did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceName=degreeLaw&resourceType=JSONSchema2020&latestResourceVersion=true |
" | did:cheqd:mainnet:46e2af9a-2ea0-4815-999d-730a6778227c?resourceName=degreeLaw&resourceType=JSONSchema2020&allResourceVersions=true |
cheqd support for Ledger-Agnostic AnonCreds Revocation Status List Objects
In the ledger-agnostic AnonCreds specification, Status List Objects contain the state of the cryptographic accumulator and revocation indices at a given point in time. This enables:
Holders of Verifiable Credentials to generate a proof of non-revocation (or not) about their specific credential; and
Verifiers to be able to verify that proof.
A Status List is generated and published immediately on creation of the Revocation Registry Definition Object so that it can be used immediately by holders. Over time, additional Status Lists may be generated and published as the revocation status of one or more credentials within the Revocation Registry change.
In each of these subsequent Revocation Status List Objects, there is an updated cryptographic accumulator value AND an updated list of revoked indices, pointing to the Revocation Registry Definition Object and a location within a Tails File, associated with an index value.
This documentation will guide an implementor of AnonCreds on cheqd on how the cheqd AnonCreds Object Method defines and structures Status List IDs, Request Formats and Response Formats.
If you are not familiar with the latest Ledger-Agnostic AnonCreds Revocation Registry Definition structure, click the collapsible tile below to learn about the new format.
cheqd uses DID-Linked Resources to identify individual resources, associated with a DID, using fully resolvable DID URLs.
cheqd resources module uses the following format:
did:cheqd:mainnet:<issuerDid>/resources/<statusListId>
Rather than using a composite string for the Status List ID. The cheqd AnonCreds object method uses a UUID to identify the Revocation Status List Object.
For example, the following DID URL is cheqd's representation of a statusListId
:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J/resources/9d26b902-555d-43bd-bac3-0bedeb462887
Another supported format for a statusListId
may be used in applications where it is important to derive the credDefId
, revocRegDefId
and statusListId
from the same root.
This format uses query-based syntax, for example:
did:cheqd:mainnet:<IssuerDid>?resourceName=<resourceName>&resourceType=<resourceType>
For example:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsStatusList
It is important to differentiate between the Request format for creating an AnonCreds object on cheqd, and the Response format, for how an AnonCreds objectshould be compiled by SDKs and the cheqd DID Resolver.
The request format may be specific to each AnonCreds Object Method. However, the response format should be standardised to enable any AnonCreds supported application to understand the object, without needing custom or method-specific logic.
The cheqd AnonCreds Status List request format comprises of:
A Resource file for the Status List object content (e.g. degreeStatusList.json
); and
A Payload file (including the signing keys and additional inputs to create a DID-Linked Resource).
Both of these inputs are required to provide the ledger enough information to:
Populate a cheqd DID-Linked Resource; and
Compile a standardised AnonCreds Revocation Registry Definition object in the Response format.
Before creating any on-ledger resource transaction, it is important to assemble the required Status List Content and save it as a file locally.
In the example below, the content should be saved as a file, for example: degreeStatusList.json
with the following content:
This Status List Resource file inputs should be replicated where possible within the Payload file, to populate a DID-Linked resource stored on cheqd, with the following mapping:
What this means is that if the Resource file has an object of "type" = "currentAccumulator" then this should be written as "resourceType" = "anonCredsStatusList" when creating the Payload file.
The Payload file utilises the inputs from the Resource file where possible, mapping common fields across. The Payload file may also require additional inputs to be provided by the creator to create a DID-Linked Resource for inputs not provided in the Resource file.
Below is an example of a Payload file:
When passing the Payload file to the ledger, additional inputs may be required within the Payload file to populate the DID-Linked Resource. In this instance, the only additional information required is:
For example, the full request format using a CLI should be structured as follows:
Once you have created your Status List Object as a resource on cheqd, the following metadata will be generated in the DID Document Metadata associated with did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J
Next and Previous Status Lists will appear in the resource Metadata when a new Status List is made with the same resourceName
and resourceType
Using the cheqd Status List Request format and associated resource metadata, the ledger has enough information to compile the following data structure as a response format.
This can either be compiled by the relevant SDK handling cheqd AnonCreds, or it can be assembled by the cheqd DID resolver.
The cheqd DID resolver will use the following logic to compile the standardised response format:
If "resourceType=anonCredsStatusList" then append "created" into a field called "timestamp" to the end of the Response Format for the resource presented
To Create a Status List as a new version of a previous Status List, you need to create a new resource.
You must:
Generate a new UUID for the resourceId
Specify the same collectionId
Specify the same resourceName
Specify the same resourceType
Attach to the transaction the new resourceFile
with the latest accum
value and index
values.
Once the transaction has been created, the resourceMetadata
will look like the following:
Note: The previousVersionId will now link to the previous Revocation Status List ID
Across the cheqd CredDef Object Method, the Revocation Registry Definition Object Method and the StatusList Object Method - each resource is associated with the same issuer DID and Collection ID.
Importantly, this allows each new resource to be indexed and versioned by their:
resourceName
resourceType
New resources can be created to update the existing CredDef or RevRegDef, whilst maintaining the historical state of the previous versions. See the documentation on Publishing a New Version of a Resource to understand this further.
Existing DID Resolvers will be able to query for the Status List Object Content using the same patterns and parameters as the Schema Object found here.
The cheqd AnonCreds method also enables applications to derive the CredDef, Revocation Registry Definition Object and Status Lists from the same root:
We propose that the resourceName
for CredDefs, Revocation Registry Definitions and Revocation Status Lists should remain the same when each of these resources is part of the same AnonCred. This will make it easier for resources to query by resourceName
and resourceType
to delineate between the three resources using a common root.
Using this logic, the following queries can be used to dereference to CredDefs, Revocation Registry Definitions and Status Lists, in a way which can derive all three resources from the same root:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsCredDef
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsRevocRegDef
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsStatusList
Note: across all three of these queries, the resolver would fetch the latest version of the resource by default
Using existing DID Resolvers, it is possible to traverse the history of Status List versions in order to produce proofs of non-revocation required in the AnonCreds Specification.
A DID URL such as the following will display all of the accumulators associated with a particular Status List:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsStatusList&allResourceVersions=true
Furthermore, it will be possible to query Status Lists at certain times. This may be very useful if you want to prove whether a Verifiable Credential was valid in the past:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?universityDegree&resourceType=anonCredsStatusList&versionTime=2022-08-21T08:40:00Z
It will be very common for a proof of non-revocation to require the latest Status List and work its way back from there.
The following DID URL will be able to call the latest Status List:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?universityDegree&resourceType=anonCredsStatusList
The AnonCreds construction below uses this logic to demonstrate how an application could derive the latest Status List using the "rev_reg_id
" since it shares the same root and would only require replacing "anonCredsRevocRegDef" with "anonCredsStatusList".
This is similar to how Hyperledger Indy uses composite strings to derive assoicated AnonCreds Objects from others. For example:
``
cheqd support for Ledger-Agnostic AnonCreds CredDefs
In the ledger-agnostic AnonCreds specification, Credential Definitions are used to specify the following information all in one place, to create an immutable record of:
The DID of the credential issuer
The schema the issued credentials will be based upon
The public/private key pairs that will be used to sign the claims within an issued credential
A cryptographic secret, embedded within the CredDef Object content, creating an uncorrelatable 'link secret' between the issuer and holder
Information necessary for the revocation of credentials, if revocation is to be enabled by the Issuer for this type of credential (Optional).
This documentation will guide an implementor of AnonCreds on cheqd on how the cheqd AnonCreds Object Method defines and structures cheqd CredDef IDs, CredDef Request formats and CredDef Response formats, with and without revocation enabled.
If you are not familiar with the latest Ledger-Agnostic AnonCreds CredDef structure, click the collapsible tile below to learn about the new format.
cheqd uses DID-Linked Resources to identify individual resources, associated with a DID, using fully resolvable DID URLs.
cheqd resources module uses the following path-based syntax:
did:cheqd:mainnet:<IssuerDid>/resources/<CredDefResourceId>
Rather than using a composite string for the CredDef Resource ID. The cheqd AnonCreds object method uses a UUID to identify the CredDef Object Content which includes additional CredDef Object Content Metadata, providing the required fields for equivalence with Hyperledger Indy implementations.
For example, the following DID URL is cheqd's representation of a credDefId
:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J/resources/77465164-5646-42d9-9a0a-f7b2dcb855c0
Another supported format for a credDefId
may be used in applications where it is important to derive the credDefId
, revocRegDefId
and statusListEntryId
from the same root.
This format uses query-based syntax, for example:
did:cheqd:mainnet:<IssuerDid>?resourceName=<resourceName>&resourceType=<resourceType>
For example:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsCredDef
It is important to differentiate between the Request format for creating an AnonCreds object on cheqd, and the Response format, for how an AnonCreds objectshould be compiled by SDKs and the cheqd DID Resolver.
The request format may be specific to each AnonCreds Object Method. However, the response format should be standardised to enable any AnonCreds supported application to understand the object, without needing custom or method-specific logic.
The cheqd CredDef request format comprises of:
A Resource file for the CredDef object content (e.g. degreeCredDef.json
); and
A Payload file (including the signing keys and additional inputs to create a DID-Linked Resource).
Both of these inputs are required to provide the ledger enough information to:
Populate a cheqd DID-Linked Resource; and
Compile a standardised AnonCreds CredDef object in the Response format.
Before creating any on-ledger resource transaction, it is important to assemble the required CredDef Resource file and save it as a file locally.
In the example below, the content should be saved as a file, for example: degreeCredDef.json
with the following content (without revocation):
Or with revocation:
This CredDef Resource file inputs should be replicated where possible within the Payload file, to populate a DID-Linked resource stored on cheqd, with the following mapping:
What this means is that if the Resource file has an object of "type" = "CL" then this should be represented as the "resourceType" = "anonCredsCredDef" within the Payload file.
The Payload file utilises the inputs from the Resource file where possible, mapping common fields across. The Payload file may also require additional inputs to be provided by the creator to create a DID-Linked Resource for inputs not provided in the Resource file.
Below is an example of a Payload file:
When passing the Payload file to the ledger, additional inputs may be required within the Payload file to populate the DID-Linked Resource. In this instance, the only additional information required is:
For example, the full request format using a CLI should be structured as follows:
Once you have created your resource on cheqd, the following metadata will be generated in the DID Document Metadata associated with did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J
Using the cheqd CredDef Request format and associated resource metadata, the ledger has enough information to compile the following data structure as a response format.
This can either be compiled by the relevant SDK handling cheqd AnonCreds, or it can be assembled by the cheqd DID resolver.
The cheqd DID resolver will use the following logic to compile the standardised response format:
If "resourceType=anonCredsCredDef" then append "issuerId" to the beginning of the Response Format for the resource presented
To create a CredDef on cheqd, you should follow the tutorials for creating a DID-Linked Resource here, and pass the relevant JSON file for the object in the transaction.
Across the cheqd CredDef Object Method, the Revocation Registry Definition Object Method and the StatusListEntry Object Method - each resource is associated with the same issuer DID and Collection ID.
Importantly, this allows each new resource to be indexed and versioned by their:
resourceName
resourceType
New resources can be created to update the existing CredDef or RevRegDef, whilst maintaining the historical state of the previous versions. See the documentation on Publishing a New Version of a Resource to understand this further.
Existing DID Resolvers will be able to query for the CredDef Object Content using the same patterns and parameters as the Schema Object found here.
The cheqd AnonCreds method also enables applications to derive the CredDef, Revocation Registry Definition Object and Status List from the same root:
We propose that the resourceName
for CredDefs, Revocation Registry Definitions and Status Lists should remain the same when each of these resources is part of the same AnonCred. This will make it easier for resources to query by resourceName
and resourceType
to delineate between the three resources using a common root.
Using this logic, the following queries can be used to dereference to CredDefs, Revocation Registry Definitions and Status List, in a way which can derive all three resources from the same root:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsCredDef
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsRevocRegDef
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsStatusList
Note: across all three of these queries, the resolver would fetch the latest version of the resource by default
The AnonCreds construction below uses this logic to demonstrate how an application could derive the latest Status List using the "rev_reg_id
" since it shares the same root and would only require replacing "anonCredsRevocRegDef" with "anonCredsStatusList".
This is similar to how Hyperledger Indy uses composite strings to derive assoicated AnonCreds Objects from others. For example:
Note that this work on Trust Infrastructure is in a draft stage, and will change as it is improved and iterated over the coming months.
Verifiable Credentials (VCs) are, in most cases, issued by legal entities. Verifiers need to know who issued the VCs, whether the issuer is recognised as trusted within the domain, and who made the recognition. By default, legal entities have no accreditations; thus, verifiers may not recognise the Verifiable Credentials they issued.
The Trust Model enables verifiers to trust roots of hierarchies without needing to know each issuer directly. All permissions and policies are verifiable by verifiers, which allows building greater trust towards issuers.
Depending on their accreditations and authorisations, legal entities can play the following roles:
Root Trusted Accreditation Organisation (Root TAO)
Trusted Accreditation Organisation (TAO)
Trusted Issuer (TI)
A trust chain creates a common and highly accessible point of trust for the given trust domain. Each Verifier can choose to trust the Root TAO and verify the accreditation chain that is referenced from the issued Verifiable Credential. All Verifiable Accreditations are public information and stored as DID-Linked Resources on the cheqd network.
Root TAO is the owner of the chain, responsible for the governance of the whole trust chain. Root TAOs may accredit TAOs to govern a segment of the chain. Root TAO and TAOs may also accredit Trusted Issuers to issue specific Verifiable Credentials. The Verifiable Accreditation defines permissions with policies that the accreditation holder must follow. Accreditation holders (legal entities) can have multiple accreditations from single or numerous trust chains, where each accreditation belongs to a one trust chain that gives them issuing or governance capabilities.
A Trust Chain should contain all three roles, even if one single DID would represent all three roles. The roles must be RTAO, TAO, and TI, where only TI may issue domain-specific Verifiable Credentials.
A Root TAO represents a Trust Model and has full control of the Trust Chain. It may:
accredit itself to govern or issue domain-specific Verifiable Credentials
accredit any legal entity to govern or issue domain-specific Verifiable Credentials
revoke an accreditation from a legal entity that is participating in the trust chain
The RTAO permission is defined by VerifiableAuthorisationForTrustChain
, and the policies are contained in termsOfUse
as TrustFrameworkPolicy
.
A TAO governs an accredited segment on behalf of the RTAO. It may:
accredit itself to issue domain-specific Verifiable Credentials
accredit any legal entity to govern or issue domain-specific Verifiable Credentials
revoke accreditation from a legal entity that was accredited by the TAO
The TAO permission is defined by VerifiableAccreditationToAccredit
, and the policies are contained in termsOfUse
as AccreditationPolicy
.
A Trusted Issuer represents the Issuer in a trust chain. It may issue domain-specific Verifiable Credential types defined by the received accreditation. Issuers may issue Verifiable Credentials outside the trust chain, but these are not associated with a Root TAO and contain no reference to an accreditation.
The TI permission is defined by VerifiableAccreditationToAttest
, and the policies are contained in termsOfUse
as AccreditationPolicy
. When the Trusted Issuer is using their accreditation to issue a domain-specific VC, the issued domain VC must contain a termsOfUse
property with AttestationPolicy
type, which links to the Trusted Issuer's accreditation and into Root TAO's accreditation, where both are located in TIR.
Accreditations are certifications of being qualified to accredit or attest. Accreditations are attribute-driven and are always restricted to domain-specific credential types. These restrictions cannot be extended. For example, if a legal entity is accredited to accredit Issuers of diploma VCs, they may only pass this or a subset downstream of the hierarchy. Depending on the accreditation, the accredited legal entity may govern (accredit) or issue (attest), but always within the Trust Model and the accredited boundaries.
All Verifiable Credentials are attestations of something. Any issuer may issue non-accredited attestation (default), while accredited Trusted Issuers may issue domain-specific VCs with the accreditation, by attaching the AttestationPolicy
into termsOfUse
.
End Users (legal entities or natural persons) can accumulate multiple Verifiable Credentials from one or many Trust Models.
The following diagram show how a Root TAO accredits two TAOs lower in the hierarchy
<todo>
The Trust Framework Policy is a document that links to a regulation, directive, national policy, or similar document that may define requirements that must be met. These requirements may include security, legal, operational, or functional requirements.
All Trust Model policies are located in the termsOfUse
property of the corresponding VerifiableTrustModel
credential that contains the permissions related to the policy.
There are two types of Verifiable Accreditation:
For a trusted ecosystem, these attestations are required to trace the legitimacy of a credential issuer to a root-of-trust.
In order to ensure consistency and interoperability within a trusted ecosystem, Trusted Accreditation Organisations (TAOs) should define schemas for the Verifiable Accreditations for their particular ecosystem. They may also reuse existing schemas that have been created for equivalent ecosystems.
Notably, Verifiable Accreditations are credentials that are issued to organisational DIDs on cheqd. In each Verifiable Accreditation, there is also a reservedAttributeId
that corresponds to the resourceId
of the Accreditation as a DID-Linked Resource.
Storing Verifiable Accreditations as DID-Linked Resources enables each accreditation to be individually resolvable using a DID URL. It also enables Accreditations to be "chained" to a DID, allowing the traversal of the Accreditation to the root of trust.
The diagram below shows how DID-Linked Resources can be applied to the trust hierarchy to enable DID resolvable Verifiable Accreditations:
Article 22 of the eIDAS Regulation obliges Member States to establish, maintain and publish trusted lists. These lists should include information related to the qualified trust service providers for which they are responsible, and information related to the qualified trust services provided by them. The lists are to be published in a secured manner, electronically signed or sealed in a format suitable for automated processing.
Standard information in an X509 certificate includes:
Version — The version of X.509 that applies to the certificate.
Serial number — Serial number assigned by certificate authority to distinguish one certificate from other certificates.
Algorithm information — The hashing algorithm used by the CA to sign the certificate (SHA-2 in almost all cases).
Issuer distinguished name — The name of the entity issuing the certificate (usually a certificate authority)
Validity period of the certificate — The period during which certificate is valid to use.
Subject distinguished name — The name of the identity the certificate is issued to (individual, organization, domain name, etc.)
Subject public key information — The public key of the certificate
As such, one method of establishing a root of trust is associating a DID on cheqd with an existing X.509 certificate. This concept has been written on recently, with there being various approaches to achieving this.
As a first iteration of trust infrastructure on cheqd, we suggest that:
did:cheqd
DIDs can be derived from the same public/private key pair as existing X.509 certificates
did:cheqd
DIDs can reference X.509 certificates using a serviceEndpoint
X.509 certificates can reference did:cheqd
DIDs using the "Subject Alternative Name" field within the X.509 certificate.
This will enable Root TAOs to create a reciprocal root of trust across European Trusted Lists for eIDAS compliance, and equally on cheqd.
For ecosystems that do not require a "traditional" root of trust, we can leverage the cheqd network itself to create reputable, "weighted" roots of trust.
Then, when traversing the trust chain and resolving to the Root of Trust, the validating application can apply logic to validate the "reputation" of the Root TAO, based on the voting power of the Validator within the active set.
Create did:cheqd
DID for Root TAO
Establish root of trust, by:
Associating Root TAO DID with X.509 certificate; or
Associating Root TAO DID with cheqd Validator
Create did:cheqd
DIDs for TAOs or TIs within the ecosystem
Create body of Verifiable Accreditation, specifying:
The did:cheqd
DID of the subject organisation that the Accreditation is being issued to
A UUID as a reservedAttributeId which aligns with the resourceId of the DID-Linked Resource
Encode Verifiable Accreditation as a hexidecimal and as a base64 encoded value
Compile payload file for writing Verifiable Accreditation as a DID-Linked Resource
Publish transaction as a DID-Linked Resource, using the same UUID for the resourceId
as the value specified in the reservedAttributeId
Resource file field | Resource file input | Payload file field | Payload file input |
---|---|---|---|
Additional parameter | Expected input | Rationale |
---|---|---|
CredDef Object field | CredDef Object expected input | Mapped Payload file field | Mapped Payload file input |
---|---|---|---|
Additional parameter | Expected input | Rationale |
---|---|---|
cheqd introduces a Verifiable Trust Model, that directly mirrors the model , that contains permissions and policies. Permissions allow governance or issuance in the Trust Model, while policies are used to define who made the accreditation, which Trust Framework is followed, and the legal basis of it. Trust Model participants make the whole Verifiable Trust Model publicly available by registering it as on cheqd.
Abbreviation | Term | Description |
---|
Unlike the which requires Root TAOs to obtain authorisation from the EBSI office to write to the Trust Registry, cheqd employs a permisionless model, allowing any organisation to set-up a Root TAO DID and accredit other organisations.
Verifiable Accreditations are credentials that are issued from one organisation to another organisation to "accredit" that organisation to perform a particular action. These types of credentials are stored directly on-ledger as , meaning that they are persistent, sequentially versioned and highly available.
Type | Description |
---|
For existing trust frameworks such as eIDAS, organisations need to establish a root of trust using in traditional "" infrastructure. These certificates establish that an organisation is authorised to provide a service under a particular jurisdiction.
For this model, we suggest that "Root TAOs" on the cheqd Network and include their DID in the "description" field of their Validator. This will tie the reputation and weight of the Validator with the DID itself.
Field | Description | Required |
---|
"type"
"currentAccumulator"
"resourceType"
"anonCredsStatusList"
"name"
"<insert same name as CredDef and RevocRegDef>"
The Payload file drawing inputs from the Resource file on its own does not provide the ledger the requisite amount of information to create a full DID-Linked Resource. resourceName must be provided as an additional input parameter
"type"
"CL"
"resourceType"
"anonCredsCredDef"
"tag"
""
"resourceVersion"
""
"name"
"universityDegree"
The Payload file drawing inputs from the Resource file on its own does not provide the ledger the requisite amount of information to create a full DID-Linked Resource. resourceName must be provided as an additional input parameter
- | Trust Chain | Implementation of a Trust Model |
DID | Decentralised Identifier | Legal entity identifier for Trust Model, cannot be natural person in context of Trust Model |
RTAO | Root Trusted Accreditation Organization | Legal entity governing the whole trust chain |
TAO | Trusted Accreditation Organization | Legal entity governing a trust chain segment |
TI | Trusted Issuer | Legal entity participating in a trust chain as an issuer |
VC | Verifiable Credential | Base type for Verifiable Attestation, Accreditation and Authorisation |
- | Verifiable Trust Model | Permissions with policies to either accredit, or to attest |
Verifiable Accreditation to Accredit | This Credential verifies that an organisation has the permissions needed to accredit other organisations for issuing a particular type of Verifiable Accredittion. |
Verifiable Accreditation to Attest | This Credential verifies that an organisation has the permissions needed to issue Verifiable Credentials, defined by a particular schema. |
did | DID of the DID Controller publishing the DID-Linked Resource | Yes |
hash | Hash of the Verifiable Accreditation as a Base64 encoded value | Yes |
body | Body of the Verifiable Accreditation as a hexidecimal string | Yes |
type | Type of Resource being created, defaults to | Yes |
issuerType | Type of Issuer that is issuing this Verifiable Accreditation, can be: "RootTAO", "TAO" or "SubTAO" | Yes |
tao | DID of the TAO that accredited the Issuer | Yes |
rootTao | DID of the root of trust that accredited the TAO and the issuer | Yes |
revoked | Boolean value indicating whether the Verifiable Accreditation is revoked or not | Yes |
Encrypted | Boolean value indicating whether the Verifiable Accreditation is encrypted or not | No |
The purpose of this document is to describe how an existing DID (and associated DIDDoc) can be updated using the cheqd-node
Cosmos CLI.
NOTE: The procedures below are only recommended for development purposes!
Using
cheqd-node
Cosmos CLI for real-world production usage is not recommended, since the identity keys are passed in raw form to the CLI. This is fine in development/testing usage, but is not recommend for mainnet.Developers are encouraged to use production-grade CLI tools such as Veramo SDK for cheqd or look at our developer guide on how to integrate custom applications.
Learn how to create a DID with cheqd Cosmos CLI
Query an existing DID/DIDDoc with cheqd Cosmos CLI
Given this procedure below is intended for development/training purposes, we assume that the user stores their public/private keys safely during the DID creation process and has access to it.
Updating a DIDDoc requires the full updated DIDDoc to be sent. Only the updated/changed parts cannot be sent. This accounts for scenarios where the DIDDoc may have been updated on ledger, but the local copy is not synced with the latest changes.
Use a text editor like nano
to edit the body of the DIDDoc (the example below assumes it's saved in a file called payload.json
).
For example, we can take the DIDDoc created previously and change the Service Endpoint from bar.example.com
to foo.example.com
:
As in flow with creating DID-Document we need to compile payload.json
file with private key inside and pass it to the CLI. The result JSON in our example will look liks:
Send the updated DIDDoc to the ledger. This must be signed with the correct identity keys:
Payload_in_JSON
- previously compiled JSON.
--from
: Cosmos account key which will pay fees for the transaction to be written to ledger.
--node
: IP address or URL of node to send request to
--chain-id
: E.g., cheqd-testnet-6
--fees
: Set to 25000000000ncheq, which is the fixed fee for updating a DID
Note that each of cheqd's on-ledger identity transactions has a fixed fee, the pricing for cheqd DIDs and DID-Linked Resources can be found here. If your account has insufficient balance the transaction will fail.
The purpose of this document is to describe how a DID (and associated DIDDoc) can be created using the cheqd-node
Cosmos CLI.
NOTE: The guidance below is only recommended to be used for testing purposes!
Using
cheqd-node
Cosmos CLI for real-world production environments is not recommended, since the identity keys are passed in raw form to the CLI. This is fine in development/testing usage, but is not recommend for mainnet.Developers are encouraged to use production-grade CLI tools such as Veramo SDK for cheqd or look at our developer guide on how to integrate custom applications.
Access to a cheqd-node
Cosmos CLI binary. You can either get this from our Github releases, or download the cheqd-cli
Docker container image.
Understand how to use cheqd accounts and Cosmos SDK keys.
Tokens to pay for identity transactions, since all ledger transactions are metered.
For testing purposes, CHEQ test tokens can be acquired from our testnet faucet.
Mainnet CHEQ tokens can be acquired from any marketplace where the $CHEQ token is traded.
For the remainder of this tutorial, it's assumed that the DID and associated DID Document is being created on testnet. These commands can easily be modified for mainnet.
First, we'll need to generate a verification key:
The result should look like the following:
Note: Keep this key safe! It is used to create the DIDDoc, and to update it in the future. Normally, you should be careful when cat
-ing such keys as it reveals the private key as well.
Encode the identity key's public key to one of the formats below according to the verificaiton method type you selected, as this will be later required in the verificationMethod
section:
A unique-id
should only be a 16-byte encoded base58 string (Indy-style) or a uuid.
For example, we can generate uuid using uuidgen
tool:
The result for our example will be b0ca0b75-ca6a-4674-a261-45f6dd0c9c77
, so let's use it as our unique-id
in our DIDDoc.
Copy-paste the template below into your terminal into a blank file (e.g., using nano
). We will add additional required information into the blank fields <xxxxx>
in the next steps.
You'll need to replace some values (as described in the cheqd DID method):
<namespace>
: Can be testnet
or mainnet
. For this CLI, we strongly suggest using testnet
.
<unique-id>
: Unique identifier, created in step #3
<key-alias>
: A key alias for the verification method identifier, e.g., #key1
<verification-method-type>
: Verification method type slected from step #2 above
<public-key-base58>, <public-key-multibase>, <public-key-jwk>
: Any one of the values from the result of step #2 above
<auth-key-alias>
: Alias of authentication key. Can be a reference to an existing verification method.
<service-key>
: Alias for service property. This is an optional section but useful to understand the power of DIDDocs.
<URI-to-object>
: A valid URI that can act as a service endpoint.
The examples below show the variation in syntax for different verification method key types in the DIDDoc contents. Note that each key type has a slightly different output.
We recommend you save this DIDDoc file (e.g., in a file called diddoc.json
) for the following steps.
After assembling the DID-Document JSON file we are ready to compile the final payload file with private key inside.
The example of payload.json
files with different verification methods:
Now that we have our DIDDoc prepared, we can send a create DID request to the ledger:
Where:
--from
: Should be an alias of a cheqd/Cosmos key, which will be used to pay for the ledger transaction.
--fees
: Should equal 50000000000ncheq, which is equivalent to 50 CHEQ, the current price for a create DID transaction on testnet and mainnet.
Note that each of cheqd's on-ledger identity transactions has a fixed fee, the pricing for cheqd DIDs and DID-Linked Resources can be found here. If your account has insufficient balance the transaction will fail.
After you execute the command, you will receive "code": 0"
if the DID was successfully written to the ledger.
Otherwise, the raw_logs
field in the response can help figure out why something went wrong. For example:
Finally, to check that the DID was successfully written to the ledger, we can use the following query:
where:
<identifier-of-your-DIDDoc>
: Fully-qualified DID with <unique-id>
For example:
Congratulations! You've created, hopefully, the first of many DIDs on cheqd!
Since upgrading to 1.x.y
version, we introduced versioning feature for DID Documents. This means that it is possible to get the previous version of a DID Document using the particular versionId of the document.
For querying particular version of the DID-Document the next command can be used:
Where:
id
- identifier of your DID-Document. Fully-qualified DID with <unique-id>
version-id
- particular id of version you want to get
Command:
Output:
Note that the output here is in snake_case because of how the cheqd ledger represents protobufs. This output would be in spec compliant JSON if queried using our DID resolver.
For querying all the versions there is a command:
Where:
id
- identifier of your DID-Document. Fully-qualified DID with <unique-id>
Output:
NOTE: The procedures below are only recommended for development purposes!
Using
cheqd-node
Cosmos CLI for real-world production usage is not recommended, since the identity keys are passed in raw form to the CLI. This is fine in development/testing usage, but is not recommend for mainnet.
Send the updated DIDDoc to the ledger. This must be signed with the correct identity keys:
Payload_in_JSON
- previously compiled JSON.
--from
: Cosmos account key which will pay fees for the transaction to be written to ledger.
--node
: IP address or URL of node to send request to
--chain-id
: E.g., cheqd-testnet-6
--fees
: Set to 10000000000ncheq, which is the fixed fee for deactivating a DID
Note: If you already have a DIDDoc and corresponding keys, you can skip this step.
Let's assume the DID for the DIDDoc is as follows:
did:cheqd:mainnet:6h7fjuw37gbf9ioty633bnd7thf65hs1
Resource content should be placed in a file and stored locally.
The fee for a resource transaction changes depending on the file type being passed to the ledger. Currently there are three different variations on the fee:
payload-file
- file with JSON formatted payload. The format and structure can be found in example
resource-data-file
- file which will be sent to the ledger as a data
. Can be a picture or an image or whatever you want.
flags
- additional parameters like, --gas
or --from
.
Example input:
where payload.json
is:
After you execute the command, you will receive "code": 0"
if the resource was successfully written to the ledger.
Otherwise, the raw_logs
field in the response can help figure out why something went wrong. For example:
Finally, to check that the resource was successfully written, we can use the following query:
<collection-id>
: The same unique identifier as that after the namespace of the corresponding DID created in step 1
<resource-id>
: Unique ID of the resource within the collection of resources associated with the DIDDoc
Example input:
Ouput:
Notice that both previous_version_id
and next_version_id
are empty now cause there is only one resource in such collection c82f2b02-bdab-4dd7-b833-3e143745d612
.
There are also 2 annother commands for getting resource from ledger depending what the actual info is needed.
Here is the command which allows to get only metadata information without getting the whole resource. The format of call is:
Parameters collection-id
and resource-id
have the same meaning as before.
Example input:
Output:
For querying all the resources but only metadata there is a special command:
As the main parameter it requires only collection-id
.
Example input:
Ouput:
Congratulations! You've successfully created a resource on cheqd ledger; hopefully, the first of many.
An existing did:cheqd
entry created using any SDK/CLI. For development purposes, this can be done using .
NOTE: Use the for production-grade usage
Querying using the Cosmos CLI is useful for development purposes, but the is designed for programmatic usage. Production-grade SDKs such as also rely on the DID Resolver package.
The purpose of this document is to describe how an existing DID (and associated DIDDoc) can be deactivated using .
Developers are encouraged to use or look at .
Learn how to
with cheqd Cosmos CLI
As in flow with we need to compile payload.json
file with private key inside and pass it to the CLI. The resulting JSON in our example will look liks:
Note that each of cheqd's on-ledger identity transactions has a fixed fee, . If your account has insufficient balance the transaction will fail.
The purpose of this document is to outline how someone can create a Resource on the cheqd network using . The process that's followed is similar to what's described in the .
Install the latest stable cheqd-node CLI, either as a or .
Acquire test CHEQ tokens through (if creating it on our testnet), or (if you plan on creating it on mainnet).
To create a DIDDoc, you can follow the instructions to .
. On Unix systems, the uuidgen
tool can be used to generate a new UUID:
fees
- the specific fee for the transaction, depending on the
cheqd Cosmos CLI
Use the Cosmos CLI to create DIDs and DID-Linked Resources for testing purposes.
Direct integration
Build a direct integration with the ledger code for the greatest flexibility.
VDR tools CLI
Build on Evernym's VDR tools (with cheqd support now outdated).
Demo wallet
Spin up a demo wallet for testing purposes, or fork our existing work.
The purpose of this document is to describe how someone can create a new Resource on under an existing Collection.
This tutorial uses the cheqd Cosmos CLI, similar to the creating a new Resource tutorial.
Install the latest stable cheqd-node CLI, either as a standalone binary or Docker container image.
Acquire test CHEQ tokens through our testnet faucet (if creating it on our testnet), or CHEQ tokens (if you plan on creating it on mainnet).
Having a Resource already created under this DIDDoc Collection
UUIDs are used to identify Resources. On Unix systems, the uuidgen
tool can be used to generate a new UUID:
Resource content should be placed in a file and stored locally.
Resources with the same Collection ID and name are grouped into version sets. Each resource in such a set has a link to the previous version (except the first version) and the next version (if it's not the most recent version).
To create a resource and mark it as a new version within a particular group, we need to use the same collection-id
and name
as in the previous version. Links between versions will be created automatically.
New versions have dedicated unique IDs and can be referenced and retrieved as any other resources.
payload-file
- file with JSON formatted payload. The format and structure can be found in example
resource-data-file
- file which will be sent to the ledger as a data
. Can be a picture or an image or whatever you want.
flags
- additional parameters like, --gas
or --from
. --fees
should match the price of the speicfic resource file type defined here.
where payload.json
is:
After you execute the command, you will receive "code": 0"
if the resource was successfully written to the ledger.
Otherwise, the raw_logs
field in the response can help figure out why something went wrong. For example:
Finally, to check that the resource was successfully written, we can use the following query:
<collection-id>
: The same unique identifier as that after the namespace of the corresponding DID created in step 1
<resource-id>
: Unique ID of the resource within the collection of resources associated with the DIDDoc
Notice that previous_version_id
is not empty and pointing to the previously created resource with id
: 3e6bd814-6851-4c8a-b114-c64f035ef590
.
Follow these instructions to query a DID from cheqd ledger.
⚠️ Before you begin...
Make sure you've correctly configured the cheqd plugin's agent settings for Veramo CLI
Use veramo did resolve <did>
to resolve a DID. For example:
TIp: If you have followed along the process of creating a did. You can put your did instead.
The output should look like the following:
DID queries are passed and handled using the cheqd DID Resolver. You can also check out the API endpoints exposed by the DID Resolver to understand how this can be fetched/consumed outside Veramo CLI.
Update or deactivate a DID
Users are able to update DID Documents for various reasons, such as to include a new section or to rotate the Verification Method keys within the DID Document.
With the /did/update
API, users are able to input either:
The section of the DID Document they would like to update; or
The full updated DID Document body.
Users are also able to deactivate DID Documents to prevent further updates and to provide client applications the relevant information that the DID Document is no longer actively used.
A /did/deactivate
request must be signed by all of the Verification Method keys listed in the DID Document.
NOTE: The tutorials below are only recommended to be used for testing purposes!
Using
cheqd-node
Cosmos CLI for real-world production environments is not recommended, since the identity keys are passed in raw form to the CLI. This is fine in development/testing usage, but is not recommend for mainnet.
Utilise our cheqd Cosmos CLI for identity for testing purposes, following the tutorials listed below:
There are plenty of other places you can go to get started creating cheqd DIDs. Simply pick the option which is best suited for your needs:
Create DIDs and DID Documents
Create W3C conformant DIDs and associated DID Documents.
Update and manage DIDs
Update and manage existing DIDs and DID Documents.
Query DIDs
Query and resolve existing DIDs to fetch DID Documents.
Deactivate DIDs
Deactivate existing DIDs and DID Documents.
Create DID-Linked Resources
Create digital resources associated and linked with DIDs.
Add new DID-Linked Resource to Collection
Create new versions of the same DID-Linked Resource within one Collection.
Credential Service
Credential Service is a SaaS product offering the easiest and quickest way to issue Credentials, using REST APIs and very little integration effort.
DID Registrar
Simple setup for building cheqd DIDs into existing applications using REST APIs, building into the Universal Registrar.
Veramo SDK Plugin
The Veramo SDK Plugin is an extension of the Veramo SDK, a JavaScript framework for Trusted Data, adding support for cheqd functionality.
Aries Framework JavaScript
Aries Framework JavaScript is an SDK which supports ZKCreds (AnonCreds) natively with cheqd support.
Walt.id SSI Kit
Walt.id SSI Kit is an SDK that supports the European Architecture and Reference Framework (ARF) standards for identity, with full cheqd support.
The Verifiable Credential Status List v2021 Specification is a working document from the W3C to support a privacy-preserving, space-efficient, and high-performance mechanism for publishing status information such as suspension or revocation of JSON and JSON-LD Verifiable Credentials.
Using DID-Linked Resources, we have been able to natively support Status List 2021 on cheqd directly.
The Status List 2021 Specification utilises bitstrings to represent whether a Verifiable Credential has been suspended/revoked or not. A bitstring can be thought of as a long list of 1s and 0s, where, if the binary value of the position in the list is 1 (one), the verifiable credential is revoked, if it is 0 (zero) it is not revoked.
Figure 1: Graphic showing the StatusList2021 bitstring
Each issued Credential correlates with a position and index on the bitstring, so that a verifier will be able to correlate the value within the Credential against the public bitstring to ascertain whether the Credential has been revoked or not, using a validate algorithm as well as a bitstring expansion algorithm.
The issuer keeps a bitstring list of all Verifiable Credentials it has issued. The StatusList is usually published by the issuer in the format of its own Verifiable Credential. This Verifiable Credential is generally hosted publicly on a centralised server or domain to enable third-party read-access.
cheqd stores each Status List and subsequent entries on-ledger as DID-Linked Resource versions. This has notable benefits, including the provenance, legitimacy and security of the Status List. For a full list of benefits, see the context for creating DID-Linked Resources.
Below are a list of alternatives for creating cheqd Status Lists.
Create Status List
Create a Status List on-ledger as a DID-Linked Resource using Veramo
Status List within a Verifiable Credential
Issue a Verifiable Credential with a cheqd Status List within the body.
Credential Service
Credential Service is a SaaS product offering the easiest and quickest way to issue Credentials, using REST APIs and very little integration effort.
DID Registrar
Simple setup for building cheqd DIDs into existing applications using REST APIs, building into the Universal Registrar.
cheqd support for Ledger-Agnostic AnonCreds Revocation Registry Definitions
In the ledger-agnostic AnonCreds specification, a Revocation Registry Definition Object acts as an on-ledger hub for revocation, providing a central point information about the:
type
of Revocation Registry (In Indy this is always "CL_ACCUM
").
cred_def_id
: Each Revocation Registry must be linked to one specific Credential Definition.
tag
: An issuer-specified name for the Revocation Registry, to ensure consistency when referencing the registry.
maxCredNum
: The maximum amount of Credentials that can be revoked in the Revocation Registry before a new one needs to be started.
tailsLocation
: A URL resolving to the location of the Tails File.
A Tails File is a large file containing a cryptographic accumulator value of prime numbers multiplied together. When a Credential is revoked, the value of the accumulator changes, removing the cryptographic value of the Credential as a factor of the accumulator value.
Each credential issued using the Revocation Registry Definition is given its own index (1 to the maxCredNum
).
While not required, the Indy community has created a component, the “Indy Tails Server,” which is basically a web server for storing Tails Files.
This documentation will guide an implementor of AnonCreds on cheqd on how the cheqd AnonCreds Object Method defines and structures Revocation Registry Definition IDs and associated content.
If you are not familiar with the latest Ledger-Agnostic AnonCreds Revocation Registry Definition structure, click the collapsible tile below to learn about the new format.
cheqd uses DID-Linked Resources to identify individual resources, associated with a DID, using fully resolvable DID URLs.
cheqd resources module uses the following format:
did:cheqd:mainnet:<issuerDid>/resources/<revRegDefResourceId>
Rather than using a composite string for the Revocation Registry Definition Resource ID. The cheqd AnonCreds object method uses a UUID to identify the Revocation Registry Definition Object Content.
For example, the following DID URL is cheqd's representation of a revocRegDefId
:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J/resources/af20b1f0-5c4d-4037-9669-eaedddb9c2df
Another supported format for a revocRegDefId
may be used in applications where it is important to derive the credDefId
, revocRegDefId
and statusListId
from the same root.
This format uses query-based syntax, for example:
did:cheqd:mainnet:<IssuerDid>?resourceName=<resourceName>&resourceType=<resourceType>
For example:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsRevocRegDef
It is important to differentiate between the Request format for creating an AnonCreds object on cheqd, and the Response format, for how an AnonCreds objectshould be compiled by SDKs and the cheqd DID Resolver.
The request format may be specific to each AnonCreds Object Method. However, the response format should be standardised to enable any AnonCreds supported application to understand the object, without needing custom or method-specific logic.
The cheqd revocation registry definition request format comprises of:
A Resource file for the Revocation Registry Definition object content (e.g. degreeRevocRegDef.json
); and
A Payload file (including the signing keys and additional inputs to create a DID-Linked Resource).
Both of these inputs are required to provide the ledger enough information to:
Populate a cheqd DID-Linked Resource; and
Compile a standardised AnonCreds revocation registry definition object in the Response format.
Before creating any on-ledger resource transaction, it is important to assemble the required Revocation Registry Definition Object Content and save it as a file locally.
In the example below, the content should be saved as a file, for example: degreeRevocRegDef.json
with the following content:
Note: The associated Credential Definition specified must have enabled revocation support for the Revocation Registry Definition to be able to be used properly in an SDK.
This Revocation Registry Definition Resource file fields should be replicated where possible within the Payload file, to populate a DID-Linked resource stored on cheqd, with the following mapping:
What this means is that if the Resource file has an object of "type" = "CL_ACCUM" then this should be written as "resourceType" = "anonCredsRevocRegDef" when creating the Payload file.
The Payload file utilises the inputs from the Resource file where possible, mapping common fields across. The Payload file may also require additional inputs to be provided by the creator to create a DID-Linked Resource for inputs not provided in the Resource file.
Below is an example of a Payload file:
When passing the Payload file to the ledger, additional inputs may be required within the Payload file to populate the DID-Linked Resource. In this instance, the only additional information required is:
For example, the full request format using a CLI should be structured as follows:
Once you have created your Revocation Registry as a resource on cheqd, the following metadata will be generated in the DID Document Metadata associated with did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J
Using the cheqd Revocation Registry Definition Request format and associated resource metadata, the ledger has enough information to compile the following data structure as a response format.
This can either be compiled by the associated SDK handling cheqd AnonCreds, or it can be assembled by the cheqd DID resolver.
The cheqd DID resolver will use the following logic to compile the standardised response format:
If "resourceType=anonCredsRevocRegDef" then append "issuerId" to the beginning of the Response Format for the resource presented
To create a Revocation Registry Definition on cheqd, you should follow the tutorials for creating a DID-Linked Resource here, and pass the relevant JSON file for the object in the transaction.
Across the cheqd CredDef Object Method, the Revocation Registry Definition Object Method and the StatusList Object Method - each resource is associated with the same issuer DID and Collection ID.
Importantly, this allows each new resource to be indexed and versioned by their:
resourceName
resourceType
New resources can be created to update the existing CredDef or RevRegDef, whilst maintaining the historical state of the previous versions. See the documentation on Publishing a New Version of a Resource to understand this further.
Existing DID Resolvers will be able to query for the Revocation Registry Definition Object Content using the same patterns and parameters as the Schema Object found here.
The cheqd AnonCreds method also enables applications to derive the CredDef, Revocation Registry Definition Object and Status Lists from the same root:
We propose that the resourceName
for CredDefs, Revocation Registry Definitions and Status Lists should remain the same when each of these resources is part of the same AnonCred. This will make it easier for resources to query by resourceName
and resourceType
to delineate between the three resources using a common root.
Using this logic, the following queries can be used to dereference to CredDefs, Revocation Registry Definitions and Status Lists, in a way which can derive all three resources from the same root:
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsCredDef
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsRevocRegDef
did:cheqd:mainnet:zF7rhDBfUt9d1gJPjx7s1J?resourceName=universityDegree&resourceType=anonCredsStatusList
Note: across all three of these queries, the resolver would fetch the latest version of the resource by default
The AnonCreds construction below uses this logic to demonstrate how an application could derive the latest Revocation Status List using the "rev_reg_id
" since it shares the same root and would only require replacing "anonCredsRevocRegDef" with "anonCredsStatusList".
This is similar to how Hyperledger Indy uses composite strings to derive assoicated AnonCreds Objects from others. For example:
Resource file field | Resource file input | Payload file field | Payload file input |
---|---|---|---|
Additional parameter | Expected input | Rationale |
---|---|---|
"type"
"CL_ACCUM"
"resourceType"
"anonCredsRevocRegDef"
"tag"
""
"resourceVersion"
""
"name"
"<insert same name as CredDef>"
The Payload file drawing inputs from the Resource file on its own does not provide the ledger the requisite amount of information to create a full DID-Linked Resource. resourceName must be provided as an additional input parameter
Verida wallet
Download the Verida wallet to receive credentials issued by cheqd's Credential Service to a did:vda
address.