Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 121 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

SSI Kit

General

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...

Getting started

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Ecosystems

Loading...

Loading...

Loading...

Loading...

DID Registration

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Tutorials

Loading...

Loading...

Concepts

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Introduction

Discontinuation Notice

This documentation will help you understand how the SSI Kit works and how you can use it. However, it presumes a certain level of knowledge about Self-Sovereign Identity (SSI) so

Important: Please be informed that, beginning from December 2023, the SSI Kit will no longer receive new features. Furthermore, the SSI Kit is planned for discontinuation by the end of Q3 2024. However, all functionalities offered by the SSI Kit will be integrated into our new libraries, APIs, and apps in the walt.id . Giving you more modularity, flexibility and ease-of-use to build end-to-end digital identity and wallet solutions. Read the transition guide . For any clarification or queries, feel free to as we aim to make this transition as smooth as possible.

if you are already familiar with SSI, you can jump to the .

if you are new to SSI, please continue with our .

identity repo
here
contact us
introduction of the SSI Kit
introduction to Self-Sovereign Identity

Transition To The Community Stack

The Community Stack

Transition

Starting from December 2023, the SSI-Kit will halt feature enhancements, leading to a complete discontinuation planned for end-Q3 2024. It's essential to plan your transition to the new stack effectively. The table below indicates which components of the SSI-Kit are already supported in the new stack.

  • For Kotlin/Java projects where SSI-Kit was used as a native dependency, utilize the provided Library for equivalent features in the new stack. •

  • If you employed the REST APIs, simply switch to the supplied API in the new stack.

SSI-Kit Feature
The Community Stack

Keys Operations: Create, Update, Delete

All types of operations are supported

ed25519

secp256k1

secp256r1

rsa

DIDs Operations: Create, Register, Resolve, Delete

All types of operations are supported

did:key

did:jwk

did:web

did:cheqd

did:iota

did:ebsi

Not yet supported

W3C Credentials

Issuance

W3C Credential Issuance as JWTs

W3C Credential Issuance as SD-JWTs

W3C Credential Issuance as JSON-LD

Not yet supported

Verification

W3C Credential Verification (JWTs)

W3C Credential Verification (SD-JWTs)

W3C Credential Verification (JSON-LD)

Not yet supported

Other Credential Features

Credential Templates

Credential Revocation

Not yet supported

Policies

Open-Policy Agent Policies

Issuance & Verification via OpenID4VC

It has always been our goal to provide developers and organizations with great tools, so they can focus on delivering holistic identity solutions. Taking the lessons learned from previous products, we decided to redesign our current offering, resulting in what we now call The Community Stack. A collection of open-source products providing everything to launch any identity solution with ease. You can learn more about it .

If you have any question, please .

All relevant new libaries and APIs have found it's place in the repo.

Available via: •  • 

Available via: •  • 

Available via: •  • 

Available via: •  • 

Available via: •  • 

Available via: •  • 

Available via: •  • 

Available via: •  • 

Available via: •  • 

Available via: •  •

Available via: •  •

Available via: •  • Please note, the issuer API only supports did:key at this point.

Available via: •  •

In The Community Stack, we no longer have the notion of a credential template. The issuance will simply happen by providing the full W3C data schema, which will then be signed. A list of credentials schemas can be found

Similar. A list of all policies can be found .

Not yet supported. However, the new also give you great flexibility until we will reintroduce Open-Policy Agent policies.

Available via: • •  • 

here
reach out
waltid-identity
Crypto Lib
Wallet-API
Crypto Lib
Wallet-API
Crypto Lib
Wallet-API
Crypto Lib
Wallet-API
DID Lib
Wallet API
DID Lib
Wallet API
DID Lib
Wallet API
DID Lib
Wallet API
DID Lib
Wallet API
Verifiable Credential Lib
Issuer API
Verifiable Credential Lib
Issuer API
Verifiable Credential Lib
Verifier API
Verifiable Credential Lib
Verifier API
here
here
webhook policies
OpenID4VC Lib
Issuer API
Verifier API
Intro SSI-Kit

SSI Kit | Basics

Learn what the SSI Kit is.

The SSI Kit offers everything you need to use Self-Sovereign Identity (SSI) with ease.

The following sections elaborate the SSI Kit's unique properties, enabled functionality and components.

Overview

Here are the most important things you need to know about the SSI Kit:

  • It is written in Kotlin/Java. It can be directly integrated (Maven/Gradle dependency) or run as RESTful web-service. A CLI tool allows you to run all functions manually.

  • It is open source (Apache 2). You can use the code for free and without strings attached.

  • It is a holistic solution that allows you to build use cases “end-to-end”. There is no need to research, combine or tweak different libraries to build pilots or production systems.

  • It abstracts complexity and low-level functionality via different interfaces (CLI, APIs). Additional services facilitate development and integration (e.g. Issuer and Verifier Portals).

  • It is modular, composable and built on open standards allowing you to customize and extend functionality with your own or third party implementations and to preventing lock-in.

  • It is flexible in a sense that you can deploy and run it on-premise, in your (multi) cloud environment or as a library in your application.

It enables you to use different identity ecosystems like Europe’s emerging identity ecosystem () in anticipation of a multi-ecosystem future.

EBSI, ESSIF

Trust Registries

Our products are agnostic towards the underlying technologies used to implement Trust Registries, which means that the SSI Kit is potentially compatible with any type of Trust Registry.

The SSI Kit supports:

  • Permissionless Blockchains (e.g. Ethereum),

  • Permissioned Blockchains (e.g. Ethereum Enterprise/Hyperledger Besu),

  • Domain Name Service (DNS),

  • Pure peer-to-peer approaches that do not require Registries.

Note that we are continuously adding support for new Registries and underlying technologies.

You can learn more about Trust Registries .

here

SSI Flavors & Ecosystems

The SSI Kit abstracts complexity for developers by following a "multi-stack approach" that enables you to use different implementations or "flavours" of SSI.

As a result, you can participate in different identity ecosystems (e.g. EBSI/ESSIF, Gaia-X, Velocity Network, cheqd and IOTA) and avoid technology-related lock-in effects.

Read on to learn which concrete technologies and implementations we support on the level of

  • Trust Registries

  • Keys

  • Decentralized Identifiers (DIDs)

  • Verifiable Credentials (VCs)

  • Data Exchange Protocols

Based on our , we distinguish the following concepts or building blocks:

Introduction to Self-Sovereign Identity (SSI)

Functionality

The SSI Kit establishes an identity infrastructure layer for any use case in any industry. Its core services are in the scope of:

  • Registry Interactions (e.g. read, write; agnostic towards the underlying tech e.g. DLT, DNS)

  • Key Management (e.g. generate, sign, import, export, manage lifecycle)

  • Decentralized Identifier (DID) operations (e.g. register, resolve, manage lifecycle)

  • Verifiable Credential/Presentations (VC, VP) operations (e.g. create, issue, present, verify)

  • Ecosystem specific use cases (e.g. onboarding, data exchange and monetization)

Illustration:

Components

Signatory | For Issuers

Signatory allows you to digitize paper credentials and automate data provision to your stakeholders.

It provides all functionality required by “Issuers”. For example:

  • Process and authenticate data requests by people or organisations,

  • Import data (from local storage or third parties),

  • Create re-usable VC templates,

  • Create VCs in different formats (e.g. JSON/JWT, JSON-LD),

  • Sign VCs using different key types (e.g. ed25519, secp256K1, RSA),

  • Manage the lifecycle of VCs (e.g. revocation).

  • Issue VCs (e.g. via OIDC/SIOP)

Custodian | For Holders

Custodian is a secure data hub for people and organizations. It provides all functionality required by “Holders”. For example:

  • Interact with Registries (read, write)

  • Create, store, manage keys, data (DIDs, VCs) and other secrets,

  • Request and import data (VCs) from third parties,

  • Selectively disclose data (VCs/VPs) for authentication and identification,

  • Manage consent and data access in a user-centric fashion.

Auditor | For Verifiers

Auditor allows you to verify your stakeholders’ identity data and offer frictionless access to services or products. It provides all functionality required by “Verifiers”. For example:

  • request data (VCs/VPs) from stakeholders,

  • verify data (VCs/VPs; incl. integrity, validity, provenance, authenticity),

  • trigger pre-defined actions following the verification.

Verification Policies

The verification steps can be dynamically configured by passing "verification policies" to each verification attempt.

The SSI Kit comes with the following set of built-in verification polices:

  • SignaturePolicy: Loads or resolves DID, loads public key and verifies the credentials signature.

  • JsonSchemaPolicy: Validates the credential against the JSON schema.

  • TrustedSchemaRegistryPolicy: Checks if the JSON schema is anchored in the EBSI Trusted Schema Registry.

  • TrustedIssuerDidPolicy: Checks if the issuer DID is anchored on the EBSI DID registry.

  • TrustedIssuerRegistryPolicy: Checks if the issuer got inserted in the EBSI TIR (Trusted Issuer Registry).

  • TrustedSubjectDidPolicy: Checks if the issuer DID is anchored on the EBSI DID registry.

  • IssuedDateBeforePolicy: Checks if issued date is in the past.

  • ValidFromBeforePolicy: Checks if valid-from date is in the past.

  • ExpirationDateAfterPolicy: Checks if expiration-date is in the futrue.

  • CredentialStatusPolicy: Checks if credential is revoked based on the credential-status list.

Keys

Cryptographic keys convey control over digital identities and enable core functionality such as encryption and authentication.

The SSI Kit supports:

  • EdDSA / ed25519

  • ECDSA / secp256k1

  • ECDSA / secp256r1

  • RSA

Note that we are continuously adding support for new key types.

You can learn more about keys .

here

Decentralized Identifiers (DIDs)

Our open source solutions enable you to use different types of DIDs and different identity ecosystems. Every relevant functionality is supported from the generation of DIDs and DID Documents to anchoring or resolving them on/from Registries.

We currently support the following DID methods:

  • did:ebsi

  • did:web

  • did:key

  • did:jwk

  • did:iota

  • did:cheqd

Note that we are continuously adding support for new DID methods.

You can learn more about DIDs .

here

Data Exchange Protocols

Authentication and data exchange protocols (e.g. OIDC/SIOP) enable the exchange of data (VCs) between different parties.

The SSI Kit supports latest OpenID Connect extension for SSI:

The implementation of the protocols is conformant with the latest specs from EBSI

You can learn more about protocols .

OpenID Connect for Credential Issuance (OpenID4CI)
OpenID for Verifiable Presentations (OpenID4VP)
https://api-conformance.ebsi.eu/docs/wallet-conformance
here

Architecture

The architecture of the SSI Kit consists of three layers:

  1. Low-Level Services Abstraction: Abstracts complex, low-level operations (e.g. cryptography, key management, digital signatures, data storage).

  2. Ecosystem Abstraction: Abstracts ecosystem-specific requirements based on the relevant technical and governance frameworks (e.g. SSI flavors, business logic, policies).

  3. High-Level Interfaces / APIs: Provides high-level interfaces that hide complexity and facilitate usage for developers.

Also, the architecture allows for the integration of third party solutions throughout the stack. For example:

  • Key storage (e.g. HSM, WebKMS)

  • Data storage (e.g. identity hubs, confidential storage)

  • Registries (e.g. blockchains, DNS)

This architectural openness prevents vendor lock-in and allows you to build SSI-based solutions that meet your unique requirements.

Illustration:

Read on to explore all three abstraction layers in more detail.

Verifiable Credentials (VCs)

Verifiable Credentials (VCs) are digital identity documents that can easily and securely be shared with and verified (incl. validity, integrity, authenticity, provenance) by anyone in a privacy preserving way. Importantly, they are never (!) stored on a blockchain due to privacy and compliance reasons.

The SSI Kit supports W3C Verifiable Credentials in different formats:

  • JSON / JWT

  • JSON-LD

Note that we are continuously adding support for new VC types and formats.

You can learn more about VCs .

here

SSI Kit

This section elaborates the theory behind the SSI Kit:

- Learn what the SSI Kit is and what it does.

- Learn which SSI flavors and identity ecosystems we support.

- Explore the SSI Kit's multi-layered architecture and components.

- Explore use cases you can implement with the SSI Kit.

- Explore all features in an overview list.

SSI Kit | Basics
SSI Flavors & Ecosystems
Architecture
Use Cases
SSI-Kit feature list

Ecosystem Abstraction

We believe in a multi-ecosystem future.

This is why we built an abstraction layer for ecosystem-specific operations and business logic. The idea is to support any ecosystem with a single solution that does not put any additional burden on developers. As a result, you can use our solutions to participate in different ecosystems without having to switch between different technical implementations.

We currently support:

  • EBSI/ESSIF (EU's new decentralized identity ecosystem)

  • Gaia-X (EU's new cloud infrastructure)

  • Velocity Network

  • cheqd Network

  • IOTA

Note that we are continuously adding new ecosystems.

Low-Level Service Abstraction

This software-layer holds a set of generic core services for common SSI and cryptographic functions. The services are in the scope of key management, decentralized identifiers, verifiable credentials and data storage.

The following is a short summary of the interfaces available. The detailed functions are described in the documentation further on.

Key Interfaces

Handles keys and cryptographic operations like the generation of signatures (e.g. linked data, JWT) with signature types such as ES256K or EdDSA.

Keys can be stored in a file and database keystore, which is extendable to HSMs and WebKMS.

DID Interfaces

Abstracts common functionality related to Decentralised Identifiers (DIDs, DID Documents) for methods like “did:web”, “did:key”, “did:ebsi”.

Credential Interfaces

Abstracts common functionality related to Verifiable Credentials (VCs) and Verifiable Presentations (VPs) in different formats like JSON and JSON-LD.

The low-level services expose comon interfaces that can conviniently unitized directly via Kotlin/Java or via the REST API ().

Swagger doc of the core API

Use Cases

Use cases you can build with the SSI Kit.

You can use Self-Sovereign Identity (SSI) - and by extension the SSI Kit - to solve any identity-related problem.

Identity and Access Management (IAM, CIAM)

You can use the SSI Kit to enable your users, customers, employees or partners to access information, services or products. By this, you can replace today's cumbersome sign-up and login processes (usernames, passwords) with more seamless experiences.

In other words, you can SSI to authenticate stakeholders you already know.

Identity Proofing / Verification

You can use the SSI Kit to identify people, organizations or even things to provide them with information, services or products.

Identity proofing is particularly important in the AML (anti-money launder) regulated industries, but is seeing growing adoption by non-regulated industries and platforms to prevent fraud, SPAM and other malicious behaviour.

Simply put, you can use SSI to identify stakeholders you do not yet know.

Risk and Compliance Checks

You can use the SSI Kit to verify any identity-related information beyond a person’s or company’s core identity (see Identity Proofing / Verification), which can be important when evaluating risks or performing compliance assessments.

For example, you can use SSI for

  • employment background checks (education, work, criminal history)

  • financial due diligence (bank account information, liquidity events, credit ratings)

  • any other type of data verification required for transactions from insurance or health data to social proofs like ratings or recommendations.

Digital Credentials

SSI can be used to digitize any type of identity-related information in order to replace paper-based identity documents or cards with digital ones that are easier to manage, share and verify as well as harder to forge.

For example, think about official public sector documents such as identity certificates or about licenses or certificates that convey allowance to perform regulated activities.

You can find more examples in our White Papers:

Identity Wallets

Any Questions

(co-authored by the Boston Consulting Group)

You can launch identity wallets or extend your existing applications with the SSI capabilities. Check out our if you are interested to learn more.

If you have any questions, feel free to .

Introduction to Self-Sovereign Identity
Me, Myself & (SS)I
get in touch

Self-Sovereign Identity (SSI)

Learn about Self-Sovereign Identity (SSI).

Welcome to our Introduction to Self-Sovereign Identity (SSI) for developers and technical readers.

Before you get started, feel free to explore other (less technical) resources that will help you and your team to get a more holistic understanding of SSI and digital identity in general:

.

Introduction to Digital Identity
Introduction to Self-Sovereign Identity
Introduction to NFTs for Identity
Case studies from our users

High-Level Interfaces / APIs

The SSI Kit exposes high-level interfaces / APIs to hide the complex introduced by

  • low-level services (e.g. key management, signing, data storage)

  • different ecosystems (i.e. different SSI flavors, business logic and governance frameworks).

  • issuing Verifiable Credentials by the Signatory,

  • holding (storing, presenting) Verifiable Credentials by the Custodian

  • and verifying Verifiable Credentials by the Auditor.

The interfaces can be used in JVM-based applications directly, or via the REST API.

The functionality of the high-level interfaces correlate with the . The functions are grouped around:

The Swagger documentation can be found under section .

SSI Kit Components
REST API

SSI | Basics

Learn what SSI is.

What is SSI?

Self-Sovereign Identity (SSI) is a user-centric approach to digital identity that gives people and organizations full control over their data. As a result, SSI enables anyone to easily share their data and reliably prove their identity (i.e. who they are and anything about them) without sacrificing security or privacy.

In other words, SSI enables you to “bring your own identity” and this is true for potentially any type of information - from your core identity (e.g. name, age, address) to your education and work records, your health and insurance data, bank account and financial information, etc.

Moreover, SSI can be used to model the digital identities of people, organizations and things.

At the end of the day, SSI promises a digital world in which interactions are effortless and worry-free. It is simply the next evolutionary step in identity management, a new paradigm in which our digital identities are no longer fragmented and locked into silos that are under someone else’s control, but only at our own disposal to be shared securely and privately.

How does SSI work?

SSI allows us to model digital identity just like we are used to the way identity works in the non-digital world based on paper documents and cards. There are just some minor twists.

For example, instead of our identity documents being made of paper or plastic, they are digital credentials made of bits and bytes and instead of storing them in wallets made of leather, they are stored in digital wallets on our phones. Importantly, these digital credentials can be reliably verified by anyone they are shared with online or offline.

In doing so, SSI enables decentralized ecosystems in which different parties can exchange and verify identity-related information. These ecosystems look like three-sided marketplaces, so that every party can take on three roles:

  • Issuers - Parties who “issue” identity-related data to people or organizations (“Holders”) in the form of digital credentials. They are the original data sources of an SSI ecosystem. For example, a government issues digital passports to citizens or a university issues digital diplomas to graduates.

  • Holders - Individuals or organizations who receive digital credentials that contain data about themselves from various sources (“Issuers”). By aggregating and storing such credentials in digital wallets, Holders can build holistic digital identities that are under their control and can easily be shared with third parties ("Verifiers").

  • Verifiers - Parties who rely on data to provide products and services can reliably verify and process data that has been provided by others (“Holders”). Verifiers, also called “Relying Parties”, are usually organizations or individuals in their professional capacity.

Usually, a single party plays only one of these roles per interaction. However, it is perfectly normal for a party to take on different roles in different interactions.

For example:

  • A university (Holder) is being accredited to issue certain types of educational credentials by a national authority (Issuer).

  • A university (Issuer) issues a digital diploma to a graduate (Holder), who can share this information with a recruiter (Verifier) in the course of a job application.

  • After the recruiting process, a recruiter (Issuer) issues the results of an applicant’s assessment (e.g. skills, referral) to the applicant (Holder), who can share this information with a new manager or another recruiter (Verifier).

  • A manager (Issuer) issues the results of a performance review to his employee (Holder) who can share this information with HR (e.g. to improve talent development programs).

Technologies & Concepts

Learn about the technologies and concepts on which SSI is based.

Understanding SSI requires the understanding of a few core concepts:

  • Cryptographic keys, which convey control over digital identities and enable core functionality such as encryption and authentication.

  • Wallets, which store our keys (control) and VCs (identity data) and enable the management and sharing of our digital identities and data via easy-to-use applications.

The SSI tech stack:

How the SSI works:

The following graphic shows how SSI works and highlights the core concepts (in blue)

Building Blocks:

Think of these core concepts as different building blocks that are available in different variations and can be put together in different ways:

As a result, there are different “flavours” of SSI depending on which variations of which building blocks have been used and how they have been put together.

Importantly, the differences in terms of technologies that are being used illustrate why interoperability has always been one of the most important topics within the industry and why the development and use of open standards (e.g. by the W3C, Decentralized Identity Foundation, OpenID Foundation and others) are vital for technology and vendor selection.

, which hold a shared and trusted record of information. In other words, they represent a “layer of trust” and can be referred to as the “single source of truth”.

, which give us the power of verifying information, for example credentials, anywhere, anytime, through the establishment of a public key infrastructure. They link keys to unique identifiers that allow different parties to find and interact with each other.

which are digital identity documents that can easily and securely be shared with and verified (incl. validity, integrity, authenticity, provenance) by anyone in a privacy preserving way. Importantly, they are never (!) stored on a blockchain due to privacy and compliance reasons.

, contain identity data for verification from one or multiple VCs and are mainly created by the holder of the VCs.

enable the exchange of data (VCs) between different parties.

Different technologies can be used to establish Trust Registries like blockchains (EBSI, Ethereum) or the domain name service (DNS). SSI even works (for certain use cases) without any Trust Registries but purely on a peer-to-peer basis. Similarly different types of DIDs, keys, proofs, credential formats, authentication and data exchange protocols can be used.
Registries
Decentralized Identifiers (DIDs)
Verifiable Credentials (VCs)
Verifiable Presentations (VPs)
Protocols

Registries

A shared and trusted record of information.

Registries serve as a single source of truth which all participants of an SSI ecosystem can trust. Depending on the ecosystem, registries make information accessible to anyone or just a limited group. Registries are important because they enable:

  • (Distributed) Public Key Infrastructures (DPKIs) which establishes an open distribution system for public keys which can be used for encryption and authentication among others.

  • Trust Registries hold reliable information about people, organizations, things and even credentials (e.g. data models, status and validity information) to ensure that different parties can trust each other and the identity-related data they exchange.

Different technologies can be used to implement Registries. For example:

  • Blockchains or L1: Typically blockchains are used because it is unfeasible (or even impossible) to tamper with them. The fact that no single organization can change the contents of a blockchain or manipulate the terms by which it is governed are very aligned with the requirements for identity ecosystems. Today, we see a growing number of developers and organizations focusing on so-called permissioned blockchains (i.e. only a selected group can “write”) like Ethereum Quorum/Enterprise. Permissionless blockchains, like Ethereum, are still used, but less than the permissioned alternatives for a variety of reasons like scalability, costs, lack of customisable governance frameworks.

  • L2: Layer two networks sit on top of blockchains and aggregate data before anchoring it. The main idea behind them is to circumvent common challenges of public, permissionless blockchains like scalability and cost issues. The most popular implementations in the context of identity are “ION” (for Bitcoin) and “Element” (for Ethereum).

  • Other Distributed Ledger Technologies (DLTs): Sometimes other DLTs are utilised like the Interplanetary File System (IPFS) though its use for digital identity remains limited.

  • Domain Name Service (DNS): Considering certain drawbacks of DLTs and their relatively slow adoption by the mass market, DNS can also be used to serve as a registry. Though it is not fully decentralised (considering its underlying governance framework), DNS has many advantages like its maturity and global adoption.

Importantly, SSI can be implemented without registries, particularly without blockchains, because identity data (or at least personal data of individuals) is never anchored due to privacy and compliance reasons. However, by combining SSI with blockchains (or other technologies), robust and trustworthy identity ecosystems that utilise transparent DPKIs and reliable Trust Registries can emerge.

Decentralised Identifiers (DIDs)

DIDs give us the power of verifying information, for example credentials, anywhere, anytime, through the establishment of a public key infrastructure.

The shortcomings of current IDs

In the digital economy, data exchange happens a lot, which makes it increasingly important to be able to identify persons, concepts or anything else for that matter in a secure and verifiable way.

A person today can have multiple different identifiers, like:

  • name@surname.com

  • https://www.surname.com

  • 0000-0000-0000-0000 (ORCID based identifier, used to identify authors of scholarly communication)

All of these identifiers work, but none fulfills to be decentralized, persistent, resolvable and cryptographically verifiable when put into the following questions.

Is the identifier decentralized?

  • https://www.surname.comdepends on a single point of failure. What happens if the hosting side disappears?

  • 0000-0000-0000-0000 (ORCID) depends on the ORCID database. What happens if it is discontinued, hacked, etc?

Is the identifier persistent?

  • https://www.surname.com If I do no longer pay for that domain, the identifier will be gone or even bought by somebody else.

Is the identifier resolvable?

  • How can I get additional information about 0000-0000-0000-0000 (ORCID) identifiers?

Is the identifier verifiable?

  • How can I prove that I own the domain, https://www.surname.com?

  • If I stopped paying for my domain, https://www.surname.com and somebody else would buy it. How would somebody know that the information provided on the side was actually mine?

All those problems make it hard to be 100% sure when exchanging information, that the party we are exchanging information with, is actually the party and not some malicious actor pretending to be the party.

DID to the rescue

The design of DIDs, which is a new form of unique identifier that has been standardized by the W3C, can now help us address these problems of current identifiers, by being:

Decentralized

  • The DIDs no longer depend on centralized registries, identity providers, authorities, etc.

Persistent

  • Once created, the did is permanently assigned to the subject.

Resolvable

  • It is possible to find a basic set of information when resolving the did. Typically, this will lead to a DID Document.

Cryptographically verifiable

  • There is a mechanism to cryptographically prove identity and ownership via information provided by the DID Document.

DID format:

The DID is a simple text string built up of three parts:

Schema

The did URI scheme identifier

DID Method

The identifier for the did method

DID Method-Specific Identifier

An identifier based on the requirements of the did method

A variety of “DID methods'', which are different implementations of the DID specification, exist. Considering that DID methods differ in terms of how they are created, registered and resolved, different methods come with different advantages and disadvantages.

For example, while DIDs are often anchored on Registries, such as EBSI (did:ebsi) or the Domain Name Service (did:web), new methods emerged that do not require Registries because their distribution is based on peer-to-peer interactions (e.g. did:key).

Now we can take any did, look at the method and resolve it based on the framework around the method. The resolved content will most of the time be JSON or JSON-LD, although other data formats might also be added in the future. The resolved content is called DID Document.

DID Document

A container of information holding:

The Subject

  • The owner of the DID Document

The Controllers

  • The entities allowed to introduce changes to the DID Document. The controller may or may not be identical to the "subject". For example, if the DID Document belonged to a DID of a book. The controller would be the author or another related person, rather than the book itself.

Cryptographic data

  • The DID document contains the public keys of the corresponding entity. The keys might be of any algorithm (typically elliptical curve keys or RSA keys are used), and are mostly encoded in the JWK format. However, other encoding formats such as PEM or Multibase are also supported. The keys can be classified to be used in certain use cases such as: authentication, verification, etc.

Service endpoints

  • Services that the subject wants to mention

DID general flow

Example (did:ebsi)

The identifier did:ebsi:2A9RkiYZJsBHT1nSB3HZAwYMNfgM7Psveyodxrr8KgFvGD5y of the method ebsi would resolve to the following DID document:

{
    "@context": [
        "https://w3id.org/did/v1"
    ],
    // keys used for the authentication of the contoller
    "authentication": [
        "did:ebsi:2A9RkiYZJsBHT1nSB3HZAwYMNfgM7Psveyodxrr8KgFvGD5y#1a7514b2d58141c3982021a6323b99bf"
    ],
    // the subject
    "id": "did:ebsi:2A9RkiYZJsBHT1nSB3HZAwYMNfgM7Psveyodxrr8KgFvGD5y",
    // the cryptographic data used for authentication, verification or other use cases
    // utilizing public keys
    "verificationMethod": [{
        "controller": "did:ebsi:2A9RkiYZJsBHT1nSB3HZAwYMNfgM7Psveyodxrr8KgFvGD5y",
        "id": "did:ebsi:2A9RkiYZJsBHT1nSB3HZAwYMNfgM7Psveyodxrr8KgFvGD5y#1a7514b2d58141c3982021a6323b99bf",
        "publicKeyJwk": {
            "alg": "EdDSA",
            "crv": "Ed25519",
            "kid": "1a7514b2d58141c3982021a6323b99bf",
            "kty": "OKP",
            "use": "sig",
            "x": "tqJADByHRU3YxswewQD4wQYXU9tB43j3PfjofsYEvqs"
        },
        "type": "Ed25519VerificationKey2018"
    }]
}

Our open source products enable you to use different DID methods for different identity ecosystems. Every relevant functionality (e.g. generation, anchoring, resolution) is supported .

DIDs are unique identifiers (URIs) which are standardised by the . They can refer to any subject - from a person, to an organization, to a thing or basically anything else for that matter. Before we have a look at how a DID is structured and the benefit it provides, let's understand the shortcomings of current identifiers first and then see how the DID solves those.

W3C

Data Exchange (Protocols)

Data Exchange (Protocols) enable the exchange of data (VCs) between different parties.

Different authentication and data exchange protocols are used to securely transfer identity data (e.g. VCs, VPs) between parties (e.g. from an Issuer to a Holder). They typically establish a mutually authenticated and encrypted data channel between the communicating parties.

The most common data exchange protocols used for SSI are:

  • OIDC4SSI / SIOP (Self-Issued OpenID Connect Provider): An extension of a mature authentication and authorization protocol called "OpenID Connect" (OIDC).

  • DIDComm: A novel protocol specifically designed for SSI and maintained by the Decentralized Identity Foundation (DIF).

  • Credential Handler API: A proposed browser-extension that may be used to connect the user's identity wallet to a web-application.

Our solutions enable you to use different data exchange protocols like OIDC/SIOP as required by different ecosystems.

Verifiable Credentials (VCs)

Before we dive deeper into Verifiable Credentials and learn about their structure and how they work, we will have a look at the problems of today's credentials.

Credentials today

Today's credentials are easy to fake, hard to verify, and not privacy preserving by design. Making it hard for business and people offline but especially online to trust each other, when exchanging information and data. This brings about many problems, thereunder:

  • To verify that a document or claim presented is actually valid, can take up many resources and time. Just think about, what you had to do last time you opened up a bank account. The presenting of your ID card via a video call, taking selfies etc.

  • Often the credentials provided by you to get access to a service, are then stored on centralized servers. This makes them not only vulnerable to data breaches, but you also need to trust the organization that they only use the data in ways you would agree with.

  • You might be forced to disclose more information than needed. The police officer checking your driver license, in most cases, only needs to know that you are allowed to drive, but not where you live or your name.

  • Organizations employing people who claim to have a skill by presenting a fake certificate, can get jobs, which, when performed poorly, could have catastrophic consequences.

This is why we need a better way to verify the claims presented, and that is where Verifiable Credentials come in.

Verifiable Credentials to the Rescue

  • Easy to verify: There is a clearly defined and reliable way of verifying a Verifiable Credential.

  • Temper-proof: No one expect the issuer (entity creating the VC) can change the claims stated in the VC.

  • Independent: No need to contact the issuer of the presented certificate to be certain about its validity. The check can happen in an independent, asynchronous way.

  • Data is owned: The holder of a certificate now owns the data and decides what to share and when, only providing proof but never actually giving it (a copy) to the service provider.

  • Portable: The user is free to choose where to take their VC and in which wallet it is saved.

The lifecycle of a Verifiable Credential

Setup

  • Holder setup: The holder generates the DID via the wallet and saves the private and public key as part of the DID Document, to be able to request, receive and present Verifiable Credentials from thereon. The DID and the DID Document will never be put into any registry, it will only exist locally in the wallet.

  • Verifier setup: The verifier only needs to have the technology to communicate with the registries when presented with a VC, to validate its authenticity using the DID and the DID Document from the issuer.

After the registration of the issuer and the setup of the wallet for the holder, the holder can now receive a VC from the issuer.

Issuance & Content

When the holder receives their Verifiable Credential it will be saved on their wallet, and it will contain the following:

  • Metadata:

    • The DID of the issuer

    • The status of the credential (expiration and issuing date, revoke state)

  • Claims:

    • The DID of the holder of the credential

    • The claims about the subject (what the issuer asserts about the subject). This could be, if they can drive a car and what type of car (driver license) or the subject of their study and knowledge areas skilled in (university certificate).

  • Proof:

    • This will contain the signatures of the issuer, which can be used to see if the content of the VC has been tempered with and for an authenticity check.

Using the Certificate

  1. Validate that the DID of the holder, stated in the certificate, is the person presenting the VC.

  2. Checking if all the state values are valid (expiration date and if the certificate is revoked or not).

  3. Checking the claims about the subject and if they match the requirements to give the person access to the service they are requesting to get access to.

  4. Checking the signatures of the issuer and the holder, by getting the DID of the issuer from the registry and the DID from the holder in their wallet and validating it using the public keys presented in the related DID documents.

When all the checks pass, the verifier can now grant the holder access to the service requested.

Example of a Verifiable Credential

{
 // Sets the context of the credential. Establishes the idea and meaning behind the 
 // special terms used in the credential, so that the parties interacting with the
 // credential are on the same side.
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://essif.europa.eu/schemas/v-a/2020/v1",
    "https://essif.europa.eu/schemas/eidas/2020/v1"
  ],
  // The identifier of the Verifiable Credential
  "id": "education#higherEducation#3fea53a4-0432-4910-ac9c-69ah8da3c37f",
  // Types of the credential, giving you an overview of the data to expect
  "type": [
    "VerifiableCredential",
    "VerifiableAttestation"
  ],
  // Issuer of the credential
  "issuer": "did:ebsi:2757945549477fc571663bee12042873fe555b674bd294a3",
  // When the credential was issued
  "issuanceDate": "2019-06-22T14:11:44Z",
  // When the credential will be valid
  "validFrom": "2019-06-22T14:11:44Z",
  // Claims about the subject
  "credentialSubject": {
  // Identifier of the only subject of the credential
    "id": "id111"
  },
  // Current status of the credential, such as if it is suspended or revoked
  "credentialStatus": {
    "id": "https://essif.europa.eu/status/identity#verifiableID#1dee355d-0432-4910-ac9c-70d89e8d674e",
    "type": "CredentialStatusList2020"
  },
  // Used data schema by the credential. It gives the verifiers an idea, 
  // if the presented data in the credential conforms.
  "credentialSchema": {
    "id": "https://essif.europa.eu/tsr-vid/verifiableid1.json",
    "type": "JsonSchemaValidator2018"
  },
  // It can give the verifier an extra level of security, that the issued credential
  // can be trused, as it lays out requirements the issuer needs to check the 
  // subject against, before issuance of the credential can take place.
  "evidence": [
    {
      "id": "https://essif.europa.eu/tsr-va/evidence/f2aeec97-fc0d-42bf-8ca7-0548192d5678",
      "type": [
        "DocumentVerification"
      ],
      "verifier": "did:ebsi:2962fb784df61baa267c8132497539f8c674b37c1244a7a",
      "evidenceDocument": "Passport",
      "subjectPresence": "Physical",
      "documentPresence": "Physical"
    }
  ],
  // Digital proof that makes the credential temper-evident
  "proof": {
    // The cryptographic signature suite that was used to generate the signature
    "type": "EidasSeal2021",
    // The date when the signature was created
    "created": "2019-06-22T14:11:44Z",
    // Purpose of this prove
    "proofPurpose": "assertionMethod",
    // The identifier of the public key that can be used to verify the signature
    "verificationMethod": "did:ebsi:2757945549477fc571663bee12042873fe555b674bd294a3#2368332668",
    // The digital signature value
    "jws": "HG21J4fdlnBvBA+y6D...amP7O="
  }
}

Our open source products enable you to act as an "Issuer" (create and issue VCs), as a Holder (manage and share VCs/VPs) and as a Verifier (request and verify VCs/VPs).

Verifiable Presentations (VPs)

Why do we need Verifiable Presentations?

How Verifiable Presentations are composed?

Verifiable Presentations represent a composition of claims, which can come from one or multiple Verifiable Credentials, of which the authorship is verified. This gives the holder of credentials the chance of composing context specify presentations, which only contain the data which is relevant in that context. When presenting the composition to a verifier, it can easily be validated.

Taking a closer look at how they are built up. We will see four different layers:

  1. Presentation Layer - Being the Verifiable Presentation itself with the required metadata

  2. Credential Layer - Referenced by Layer 1 and pointing to one or more credentials

  3. Credential Proof Layer - Holding the proofs of the credentials and the signatures from Layer

  4. Presentation Proof Layer - Holding the proof of the Verifiable Presentation and its signatures

Example of a Verifiable Presentation in code

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1"
  ],
  "type": [
    "VerifiableCredential",
    "VerifiablePresentation"
  ],
  "verifiableCredential": [
    {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://essif.europa.eu/schemas/vc/2020/v1"
      ],
      "credentialSubject": {
        "id": "did:ebsi:00000004321",
        "naturalPerson": {
          "did": "did:example:00001111"
        }
      },
      "id": "did:ebsi-eth:00000001/credentials/1872",
      "issuanceDate": "2020-08-24T14:13:44Z",
      "issuer": "did:ebsi:000001234",
      "proof": {
        "created": "2020-08-24T14:13:44Z",
        "jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19.",
        "proofPurpose": "assertionMethod",
        "type": "EcdsaSecp256k1Signature2019",
        "verificationMethod": "did:ebsi-eth:000001234#key-1"
      },
      "type": [
        "VerifiableCredential",
        "VerifiableAuthorization"
      ]
    },
    {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://w3id.org/citizenship/v1"
      ],
      "credentialSubject": {
        "birthDate": "1958-08-17",
        "givenName": "JOHN",
        "id": "did:example:123",
        "type": [
          "PermanentResident",
          "Person"
        ]
      },
      "issuer": "did:example:456",
      "proof": {
        "created": "2020-04-22T10:37:22Z",
        "jws": "eyJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlLCJhbGciOiJFZERTQSJ9..BhWew0x-txcroGjgdtK-yBCqoetg9DD9SgV4245TmXJi-PmqFzux6Cwaph0r-mbqzlE17yLebjfqbRT275U1AA",
        "proofPurpose": "assertionMethod",
        "type": "Ed25519Signature2018",
        "verificationMethod": "did:example:456#key-1"
      },
      "type": [
        "VerifiableCredential",
        "PermanentResidentCard"
      ]
    }
  ]
}

Our open source products enable you to act as a Holder (share VPs) and as a Verifier (request verify VPs).

Quick Start

Getting started with the SSI Kit.

Discontinuation Notice

The SSI-Kit's functionality can be used in a variety of ways. Select your preference to get started

Tutorials

Verifiable Credentials (VCs) are digital credentials that contain actual identity data of people or organizations and are standardized by the . They are digital equivalents of paper-based identity documents like passports or diplomas.

With VCs and the standard introduced by , we now have a way of creating a digital piece of information that identifies a particular entity or verifies a specific attribute, qualification or claim about them, in a way, that is almost impossible to forger, easy to verify, and privacy preserving by design. Leaving us with the following benefits:

For us to understand the typical lifecycle of a Verifiable Credential, we need to make sure, we understand the idea behind an and what are. With that out of the way, let's start with cycle.

Registration of the Issuer: Depending on the governance framework, the issuer will be accredited by a trusted entity, before their DID as well as DID Document will be put into the . The Registry is the Single Source of truth and trust entity which verifiers will use as a reference point to make sure a presented VC is valid.

The holder can now use the VC in their wallet to access services, and get access to products by presenting it to the service/product provider (The Verifier) and thereby making it a . The verifier will go through the following steps to make sure the certificate is valid:

Before the validation of the content of the certificate can take place, the VC needs to be parsed from the support JSON-LD or the JWT format. Depending on the ecosystem used, there will also happen a of the credential.

A Verifiable Presentation (VP) is a collection from one or more Verifiable Credentials, whereas the authorship of the whole collection can be cryptographically verified. VPs are standardized as part of the .

Verifiable Presentations, make it possible to combine and tamper-evident share data of one or more Verifiable Credentials. The shared presentation of the data will be encoded in such a way that authorship of the data can be trusted after a process of cryptographic verification. In situations where only a subset of the original Verifiable Credential data is reveled, for example, to enhance user privacy, can help us keep that data verifiable.

If you want to get a better understanding of the different attributes present, please visit our section about .

Important: Please be informed that, beginning from December 2023, the SSI Kit will no longer receive new features. Furthermore, the SSI Kit is planned for discontinuation by the end of Q3 2024. However, all functionalities currently offered by the SSI Kit will be integrated into our new libraries, APIs, and apps under . This is aimed at providing a more modular, flexible, and efficient solution for your needs. For any clarification or queries, feel free to as we aim to make this transition as smooth as possible.

- Issue and verify your first VC using the SSI-Kit Api

- Leverage custom credential templates, the credential status property, prebuild and custom verification policies.

W3C
W3C
Issuer, Holder and Verifier
DID and DID Documents
Registry
Verifiable Presentation
validation of the schema
W3C Verifiable Credentials Data Model
Zero-Knowledge Proofs
VCs

REST API

Learn how to issue, verify and manage Verifiable Credentials, Keys and DIDs via API.

Java | Kotlin

Learn how to issue, verify and manage Verifiable Credentials, Keys and DIDs directly in a Java or Kotlin Application. Adding the SSI-Kit as a direct dependency.

CLI - Command Line Tool

Learn how to issue, verify and manage Verifiable Credentials, Keys and DIDs via the CLI.

Intro to Decentralised Identifiers (DIDs)
The Community Stack
contact us
My First Verifiable Credential (VC)
Advanced Verifiable Credentials (VC)
Verifiable Credentials Explained

Key management

Key management functions include:

List keys

The /keys endpoint lists the key available to the Custodian

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/keys' \
  -H 'accept: application/json'
No parameters
{
    "list":
    [
        {
            "algorithm": "string",
            "cryptoProvider": "string",
            "keyId":
            {
                "id": "string"
            },
            "keyPair": {},
            "keysetHandle": null
        }
    ]
}

E.g. List the available keys

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/keys' \
  -H 'accept: application/json'
{
    "list":
    [
        {
            "algorithm": "EdDSA_Ed25519",
            "cryptoProvider": "SUN",
            "keyId":
            {
                "id": "e548f032cadf4145ab6886a57c2e87e6"
            },
            "keyPair": {},
            "keysetHandle": null
        },
        {
            "algorithm": "EdDSA_Ed25519",
            "cryptoProvider": "SUN",
            "keyId":
            {
                "id": "e70e8fd8932043caa7c857c3b944d0e0"
            },
            "keyPair": {},
            "keysetHandle": null
        },
        {
            "algorithm": "EdDSA_Ed25519",
            "cryptoProvider": "SUN",
            "keyId":
            {
                "id": "b50db0c1f73242b8bb0f2f6324e15ec3"
            },
            "keyPair": {},
            "keysetHandle": null
        },
        {
            "algorithm": "EdDSA_Ed25519",
            "cryptoProvider": "SUN",
            "keyId":
            {
                "id": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
            },
            "keyPair": {},
            "keysetHandle": null
        },
        {
            "algorithm": "EdDSA_Ed25519",
            "cryptoProvider": "SUN",
            "keyId":
            {
                "id": "8cc0b1707ea345ed83e479469d42aac2"
            },
            "keyPair": {},
            "keysetHandle": null
        },
        {
            "algorithm": "EdDSA_Ed25519",
            "cryptoProvider": "SUN",
            "keyId":
            {
                "id": "did:key:z6Mkv58vGsBMwbiyQ3P93MRnYfRgGvn4STEEsj5hFHYe51wu#z6Mkv58vGsBMwbiyQ3P93MRnYfRgGvn4STEEsj5hFHYe51wu"
            },
            "keyPair": {},
            "keysetHandle": null
        },
        {
            "algorithm": "EdDSA_Ed25519",
            "cryptoProvider": "SUN",
            "keyId":
            {
                "id": "186a1e0a6d42459ba902724fe7643ed4"
            },
            "keyPair": {},
            "keysetHandle": null
        },
        {
            "algorithm": "EdDSA_Ed25519",
            "cryptoProvider": "SUN",
            "keyId":
            {
                "id": "c5b11445be0e4d37863170df3328630b"
            },
            "keyPair": {},
            "keysetHandle": null
        }
    ]
}

Load key

The /keys/{alias} endpoint loads a key specified by its alias.

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/keys/{alias}' \
  -H 'accept: application/json'
No parameters
{
    "algorithm": "string",
    "cryptoProvider": "string",
    "keyId":
    {
        "id": "string"
    },
    "keyPair": {},
    "keysetHandle": null
}

E.g. Load a key with id e548f032cadf4145ab6886a57c2e87e6

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/keys/e548f032cadf4145ab6886a57c2e87e6' \
  -H 'accept: application/json'
{
    "algorithm": "EdDSA_Ed25519",
    "cryptoProvider": "SUN",
    "keyId":
    {
        "id": "e548f032cadf4145ab6886a57c2e87e6"
    },
    "keyPair": {},
    "keysetHandle": null
}

Generate key

The /keys/generate endpoint generates a key using the specified algorithm.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/keys/generate' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "keyAlgorithm": "EdDSA_Ed25519"
}
{
    "algorithm": "string",
    "cryptoProvider": "string",
    "keyId":
    {
        "id": "string"
    },
    "keyPair": {},
    "keysetHandle": null
}

E.g. Generate a key using the EdDSA_Ed25519 algorithm.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/keys/generate' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{ "keyAlgorithm": "EdDSA_Ed25519" }'
{
    "keyAlgorithm": "EdDSA_Ed25519"
}
{
    "algorithm": "EdDSA_Ed25519",
    "cryptoProvider": "SUN",
    "keyId":
    {
        "id": "8394ea7883bc4328a3f18b146b7e16bd"
    },
    "keyPair": {},
    "keysetHandle": null
}

Import key

The /keys/import endpoint imports a key (JWK or PEM format) to the underlying keystore.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/keys/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '<request-body>'

The key string in JWK or PEM format

{
    "id": "string"
}

E.g. Import a public key specified in JWK format.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/keys/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '{"kty":"OKP","use":"sig","crv":"Ed25519","kid":"bc6fa6b0593648238c4616800bed7746","x":"YyswAyRO2Aur8Jmzc8aOvI3AWFka3ZynJwB84a0FJVU","alg":"EdDSA"}'
{
    "kty": "OKP",
    "use": "sig",
    "crv": "Ed25519",
    "kid": "bc6fa6b0593648238c4616800bed7746",
    "x": "YyswAyRO2Aur8Jmzc8aOvI3AWFka3ZynJwB84a0FJVU",
    "alg": "EdDSA"
}
{
    "id": "bc6fa6b0593648238c4616800bed7746"
}

Delete key

The /keys/{id} deletes the specified as parameter:

  • id path parameter (required) - the key alias

curl -X 'DELETE' \
  'https://custodian.ssikit.walt.id/keys/{id}' \
  -H 'accept: application/json'
No parameters
Code 200

E.g. Delete the key with id bc6fa6b0593648238c4616800bed7746

curl -X 'DELETE' \
  'https://custodian.ssikit.walt.id/keys/bc6fa6b0593648238c4616800bed7746' \
  -H 'accept: application/json'

Export key

The /keys/export endpoint exports a key.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/keys/export' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "keyAlias": "string",
    "format": "JWK",
    "exportPrivate": true
}
The key in the specified format, JWK or PEM

E.g. Export the public key with id = e548f032cadf4145ab6886a57c2e87e6 as JWK.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/keys/export' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "keyAlias": "e548f032cadf4145ab6886a57c2e87e6",
  "format": "JWK",
  "exportPrivate": false
}'
{
    "keyAlias": "e548f032cadf4145ab6886a57c2e87e6",
    "format": "JWK",
    "exportPrivate": false
}
{
    "kty": "OKP",
    "use": "sig",
    "crv": "Ed25519",
    "kid": "e548f032cadf4145ab6886a57c2e87e6",
    "x": "jT8YleOQnaABpZTnvId3WoID4Pia9Lex9OndqQ22Xxs",
    "alg": "EdDSA"
}

REST API

Manage keys, DIDs, issue Verifiable Credentials, and verify them using the SSI-Kit's REST API.

Installation & Running the Project

Make sure you have Docker or a JDK 16 build environment including Gradle installed on your machine

Pull the docker container directly from docker hub and run the project

docker run -p 7000-7004:7000-7004 -itv $(pwd)/data:/app/data waltid/ssikit serve -b 0.0.0.0

This will create a folder called data in your current directory as storage for the VC, DIDs, Keys and other things which need to be stored in order to provide all the functionality.

  1. Clone the project

git clone https://github.com/walt-id/waltid-ssikit.git

2. Change the folder

cd waltid-ssikit/

3. Run the project

The first time you run the command you will be asked to built the project. You can confirm the prompt.

./ssikit.sh serve

After successfully running the project, you will have the endpoints, described below, available for use.

Exposed endpoints:

Type
Locally
General Available

Signatory API - For Issuers

http://127.0.0.1:7001

Custodian API - For Holders

http://127.0.0.1:7002

Auditor API - For Verifiers

http://127.0.0.1:7003

Core API

http://127.0.0.1:7000

ESSIF API

http://127.0.0.1:7004

The Core API exposes most of the functionalities provided by the SSI Kit, however newer features will only be released in the other API endpoints. Therefore, it is recommended to use the Signatory API, Custodian API and Auditor API for most use cases.

Next Steps

Tutorials

Custodian API - For Holders

Custodian REST API functions.

The Custodian API provides management functions for maintaining secrets and sensitive data (e.g. keys, Verifiable Credentials) in a secure way:

Signatory API - For Issuers

Signatory REST API functions.

The Signatory API exposes the "issuance" endpoint, which provides flexible integration possibilities for anyone intending to act as an "Issuer" (i.e. create, sign and issue Verifiable Credentials), as follows:

Credentials

The /v1/credentials/issue endpoint issues a specified credential.

Templates

The currently available template functions are:

List templates

The /v1/templates endpoint returns the list of the available template ids

No parameter

E.g. List the templates

Import template

The /v1/templates/{id} endpoint to import your custom credential template

  • id path parameter (required) - id of the template, e.g. MyCustomCredential

Load template

The /v1/templates/{id} endpoint displays the content of the template having the parameters:

  • id path parameter (required) - id of the template

No parameter

E.g. Load the template for the id set to UniversityDegree.

Revocations

Cryptographic keys

The following key management functions are available:

List key ids

The /v1/key endpoint lists the available key ids.

E.g. List the available key ids.

Load key

The /v1/key/{id} endpoint loads the public component of the provided key id in JWK format:

  • id - path parameter (required) - the key id

E.g. Load the key having id = e548f032cadf4145ab6886a57c2e87e6.

Delete key

The /v1/key/{id} endpoint deletes the specified key.

E.g. Delete the key having id = e548f032cadf4145ab6886a57c2e87e6.

Generate key

The /v1/key/gen generates a new key using the specified algorithm.

E.g. Generate a new key using the EdDSA_Ed25519 algorithm.

Import key

The /v1/key/import endpoint imports a key (JWK or PEM format) to the underlying keystore.

E.g. Import a public key specified in JWK format.

Export key

The /v1/key/export endpoint exports public and private key part (if supported by underlying keystore).

E.g. Export the public key with id = bc6fa6b0593648238c4616800bed7746 as JWK.

- lists the available keys

- loads a key specified by its alias

- generate a key using the specified algorithm

- imports a key

- deletes a specific key

- exports public and private key parts (if supported by the underlying keystore)

If you want to get a more detailed overview of the options provided for building the project on your machine, please refer to .

- Learn how to issue credentials

- Learn how to maintain secrets and sensitive data (e.g. keys, Verifiable Credentials)

- Learn how to verify credentials

- Play through a whole use case from Issuance to Verification

|

|

- issue credentials

- create and mange credential templates

- revocation related functions

If you're new to VCs, check out the for an overview.

E.g. Issue a UniversityDegree credential in the default JSON-LD format. In case you don't have the DID for the Issuer and or the Holder, you can create one .

Check out the section to learn about how to issue a verifiable credential with a credentialStatus property.

- display the list of Templates

- import a custom template

- display the content of the template having the specified id

Refer to section for more details on verifiable credential revocations.

- list of key ids

- load the public key in JWK format

- delete key

- generate key

- import key

- export key

building the project
Issuance
Holders
Verifiers
My First VC
List
Load
Generate
Import
Delete
Export
curl -X 'POST' \
  'https://signatory.ssikit.walt.id/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "templateId": "string",
    "config":
    {
        "issuerDid": "string",
        "subjectDid": "string",
        "verifierDid": "string",
        "issuerVerificationMethod": "string",
        "proofType": "JWT",
        "domain": "string",
        "nonce": "string",
        "proofPurpose": "string",
        "credentialId": "string",
        "issueDate": "2022-10-06T18:09:14.570Z",
        "validDate": "2022-10-06T18:09:14.570Z",
        "expirationDate": "2022-10-06T18:09:14.570Z",
        "dataProviderIdentifier": "string",
        "ldSignatureType": "string",
        "creator": "string",
        "ecosystem": "string",
        "statusType": "string"
    },
    "credentialData":
    {
        "additionalProp1":
        {},
        "additionalProp2":
        {},
        "additionalProp3":
        {}
    }
}
The issued credential displayed either in JSON-LD or JWT format
curl -X 'POST' \
  'https://signatory.ssikit.walt.id/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "templateId": "UniversityDegree",
    "config":
    {
        "issuerDid": "did:web:walt.id",
        "subjectDid": "did:web:my.domain"
    },
    "credentialData":
    {
        "credentialSubject":
        {
            "degree":
            {
                "name": "Bachelor of Science and Arts",
                "type": "BachelorDegree"
            }
        }
    }
}'
{
    "templateId": "UniversityDegree",
    "config":
    {
        "issuerDid": "did:web:walt.id",
        "subjectDid": "did:web:my.domain"
    },
    "credentialData":
    {
        "credentialSubject":
        {
            "degree":
            {
                "name": "Bachelor of Science and Arts",
                "type": "BachelorDegree"
            }
        }
    }
}
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
    ],
    "credentialSubject":
    {
        "degree":
        {
            "name": "Bachelor of Science and Arts",
            "type": "BachelorDegree"
        },
        "id": "did:web:my.domain"
    },
    "id": "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270",
    "issued": "2022-10-07T09:53:41.369913097Z",
    "issuer":
    {
        "id": "did:web:walt.id"
    },
    "validFrom": "2022-10-07T09:53:41.369917079Z",
    "issuanceDate": "2022-10-07T09:53:41.369917079Z",
    "type":
    [
        "VerifiableCredential",
        "UniversityDegreeCredential"
    ],
    "proof":
    {
        "type": "Ed25519Signature2018",
        "creator": "did:web:walt.id",
        "created": "2022-10-07T09:53:41Z",
        "domain": "https://api.preprod.ebsi.eu",
        "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ"
    }
}
curl -X 'GET' \
  'https://signatory.ssikit.walt.id/v1/templates' \
  -H 'accept: application/json'
[
    "string"
]
curl -X 'GET' \
  'https://signatory.ssikit.walt.id/v1/templates' \
  -H 'accept: application/json'
[
    "DataSelfDescription",
    "VerifiableDiploma",
    "VerifiableVaccinationCertificate",
    "LegalPerson",
    "VerifiableAuthorization",
    "Europass",
    "KybMonoCredential",
    "KycCredential",
    "VerifiableMandate",
    "VerifiablePresentation",
    "EuropeanBankIdentity",
    "KybCredential",
    "VerifiableAttestation",
    "OpenBadgeCredential",
    "PeerReview",
    "DataConsortium",
    "ProofOfResidence",
    "AmletCredential",
    "ParticipantCredential",
    "PermanentResidentCard",
    "UniversityDegree",
    "VerifiableId",
    "DataServiceOffering",
    "GaiaxCredential",
    "Iso27001Certificate"
]
curl -X 'POST' \
  'https://signatory.ssikit.walt.id/v1/templates/{id}' \
  -H 'accept: application/json'
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
  "type": [
    "VerifiableCredential",
    "MyCustomCredential"
  ],
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "id": "string",
  "issuer": {
    "id": "string"
  },
  "issued": "2020-03-10T04:24:12.164Z",
  ... // custom data in json
}
{
  "type": [
    "VerifiableCredential",
    "MyCustomCredential"
  ],
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "id": "http://example.gov/credentials/3732",
  "issuer": {
    "id": "did:example:456"
  },
  "issued": "2020-03-10T04:24:12.164Z",
  "credentialSubject": {
    "id": "did:example:123",
    "firstName": "",
    "lastName": "",
    "country": "Austria"
  }
}
null
curl -X 'GET' \
  'https://signatory.ssikit.walt.id/v1/templates/{id}' \
  -H 'accept: application/json'
The template content as JSON
curl -X 'GET' \
  'https://signatory.ssikit.walt.id/v1/templates/UniversityDegree' \
  -H 'accept: application/json'
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
    ],
    "credentialSubject":
    {
        "degree":
        {
            "name": "Bachelor of Science and Arts",
            "type": "BachelorDegree"
        },
        "id": "did:example:123"
    },
    "id": "http://example.gov/credentials/3732",
    "issued": "2020-03-10T04:24:12.164Z",
    "issuer":
    {
        "id": "did:example:456"
    },
    "type":
    [
        "VerifiableCredential",
        "UniversityDegreeCredential"
    ]
}
curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/key' \
  -H 'accept: application/json'
No parameters
The list of key ids
curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/key' \
  -H 'accept: application/json'
[
    "e548f032cadf4145ab6886a57c2e87e6",
    "e70e8fd8932043caa7c857c3b944d0e0",
    "b50db0c1f73242b8bb0f2f6324e15ec3",
    "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
    "8cc0b1707ea345ed83e479469d42aac2",
    "c5b11445be0e4d37863170df3328630b",
    "8394ea7883bc4328a3f18b146b7e16bd",
    "fd36a0159592413da1d89f192dd77dcd",
    "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z#z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z",
    "fa9296808e64440d89e6d245a1709141",
    "8dd54d6ae25a4818b1497530a8659dc1"
]
curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/key/{id}' \
  -H 'accept: application/json'
No parameters
The string for the public component of the key
curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/key/e548f032cadf4145ab6886a57c2e87e6' \
  -H 'accept: application/json'
"{\"kty\":\"OKP\",\"use\":\"sig\",\"crv\":\"Ed25519\",\"kid\":\"e548f032cadf4145ab6886a57c2e87e6\",\"x\":\"jT8YleOQnaABpZTnvId3WoID4Pia9Lex9OndqQ22Xxs\",\"alg\":\"EdDSA\"}"
curl -X 'DELETE' \
  'https://core.ssikit.walt.id/v1/key/' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '<request-body>'
The key id string
Code 200
curl -X 'DELETE' \
  'https://core.ssikit.walt.id/v1/key/' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d 'e548f032cadf4145ab6886a57c2e87e6'
e548f032cadf4145ab6886a57c2e87e6
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/key/gen' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "keyAlgorithm": "EdDSA_Ed25519"
}
{
    "id": "string"
}
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/key/gen' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "keyAlgorithm": "EdDSA_Ed25519"
}'
{
    "keyAlgorithm": "EdDSA_Ed25519"
}
{
    "id": "2251db0d15eb4e96b80c471edbaed185"
}
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/key/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '<request-body>'
The key string in JWK or PEM format
{
    "id": "string"
}
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/key/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '{"kty":"OKP","use":"sig","crv":"Ed25519","kid":"bc6fa6b0593648238c4616800bed7746","x":"YyswAyRO2Aur8Jmzc8aOvI3AWFka3ZynJwB84a0FJVU","alg":"EdDSA"}'
{
    "kty": "OKP",
    "use": "sig",
    "crv": "Ed25519",
    "kid": "bc6fa6b0593648238c4616800bed7746",
    "x": "YyswAyRO2Aur8Jmzc8aOvI3AWFka3ZynJwB84a0FJVU",
    "alg": "EdDSA"
}
{
    "id": "bc6fa6b0593648238c4616800bed7746"
}
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/key/export' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "keyAlias": "string",
    "format": "JWK",
    "exportPrivate": true
}
The key in the specified format, JWK or PEM
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/key/export' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "keyAlias": "bc6fa6b0593648238c4616800bed7746",
  "format": "JWK",
  "exportPrivate": false
}'
{
    "keyAlias": "bc6fa6b0593648238c4616800bed7746",
    "format": "JWK",
    "exportPrivate": false
}
{
    "kty": "OKP",
    "use": "sig",
    "crv": "Ed25519",
    "kid": "bc6fa6b0593648238c4616800bed7746",
    "x": "YyswAyRO2Aur8Jmzc8aOvI3AWFka3ZynJwB84a0FJVU",
    "alg": "EdDSA"
}
https://signatory.ssikit.walt.id/
https://custodian.ssikit.walt.id/
https://auditor.ssikit.walt.id/
https://core.ssikit.walt.id/
https://essif.ssikit.walt.id/
Swagger
Redoc
Key
DID
Credentials
Swagger
Redoc
intro section
Issue with status
Credential Statuses
Credentials
Templates
Revocations
list
import
load
here
list
load
delete
generate
import
export

Did management

DID management functions enable the following:

List DID

The /did endpoint lists the available DIDs.

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/did' \
  -H 'accept: application/json'
No parameters
The list of DID strings

E.g. List the available DIDs

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/did' \
  -H 'accept: application/json'
[
    "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
    "did:web:my.domain",
    "did:web:walt.id",
    "did:key:z6Mkv58vGsBMwbiyQ3P93MRnYfRgGvn4STEEsj5hFHYe51wu"
]

Load DID

The /did/{id} endpoint loads a DID specified by:

  • id path parameter (required) - the DID url string

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/{id}' \
  -H 'accept: application/json'
No parameters
{
    "assertionMethod":
    [
        "string"
    ],
    "authentication":
    [
        "string"
    ],
    "@context":
    [
        "string"
    ],
    "id": "string",
    "verificationMethod":
    [
        {
            "controller": "string",
            "id": "string",
            "publicKeyJwk":
            {
                "alg": "string",
                "crv": "string",
                "kid": "string",
                "kty": "string",
                "use": "string",
                "x": "string"
            },
            "type": "string"
        }
    ]
}

E.g Load the DID having the id = did:web:walt.id.

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/did/did%3Aweb%3Awalt.id' \
  -H 'accept: application/json'
{
    "assertionMethod":
    [
        "did:web:walt.id#186a1e0a6d42459ba902724fe7643ed4"
    ],
    "authentication":
    [
        "did:web:walt.id#186a1e0a6d42459ba902724fe7643ed4"
    ],
    "@context":
    [
        "https://www.w3.org/ns/did/v1"
    ],
    "id": "did:web:walt.id",
    "verificationMethod":
    [
        {
            "controller": "did:web:walt.id",
            "id": "did:web:walt.id#186a1e0a6d42459ba902724fe7643ed4",
            "publicKeyJwk":
            {
                "alg": "EdDSA",
                "crv": "Ed25519",
                "kid": "186a1e0a6d42459ba902724fe7643ed4",
                "kty": "OKP",
                "use": "sig",
                "x": "7-ofBq4vt0ePzC5IjiWkqTedfSv7WJJr6-HsQNXsr2M"
            },
            "type": "Ed25519VerificationKey2019"
        }
    ]
}

Delete DID

The /did/{id} deletes the DID specified by:

  • url - path parameter (required) - the DID url string

curl -X 'DELETE' \
  'https://custodian.ssikit.walt.id/did/{id}' \
  -H 'accept: application/json'
No parameters
Code 200

E.g. Delete the DID having id = did:web:walt.id.

curl -X 'DELETE' \
  'https://custodian.ssikit.walt.id/did/did%3Aweb%3Awalt.id' \
  -H 'accept: application/json'

Create DID

The /did/create endpoint creates a DID.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "method": "string",
    "keyAlias": "string",
    "method-dependent-options": "..."
}
The DID url string

The method and keyAlias properties are common for all did-method requests, method being required, while keyAlias - optional (if not specified, a new key will be automatically created using the default algorithm according to the did-method). The method-dependent options have default values, if not specified otherwise. Below are the available properties by did-method.

{
    "method": "key",
    "keyAlias": "string",
    "useJwkJcsPub": "boolean"
}
{
  "method": "web",
  "keyAlias": "string",
  "didWebDomain": "string",
  "didWebPath": "string"
}
  • didWebDomain (default) - "walt.id"

  • didWebPath (default) - empty-string

{
    "method": "ebsi",
    "keyAlias": "string",
    "version": "int"
}
  • version (default) - 1

{
    "method": "cheqd",
    "keyAlias": "string",
    "network": "string"
}
  • network (default) - "testnet"

{
    "method": "iota",
    "keyAlias": "string"
}
{
    "method": "jwk",
    "keyAlias": "string"
}

E.g. Create a DID using the web method having the domain set to walt.id.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "web",
  "didWebDomain": "walt.id"
}'
{
    "method": "web",
    "didWebDomain": "walt.id"
}
did:web:walt.id

Resolve DID

The /did/resolve endpoint resolves a DID.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/did/resolve' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "did": "string"
}
{
    "assertionMethod":
    [
        "string"
    ],
    "authentication":
    [
        "string"
    ],
    "@context":
    [
        "string"
    ],
    "id": "string",
    "verificationMethod":
    [
        {
            "controller": "string",
            "id": "string",
            "publicKeyJwk":
            {
                "alg": "string",
                "crv": "string",
                "kid": "string",
                "kty": "string",
                "use": "string",
                "x": "string"
            },
            "type": "string"
        }
    ]
}

E.g. Reslove the DID having id = did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/did/resolve' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "did": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
}'
{
    "did": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
}
{
    "assertionMethod":
    [
        "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
    ],
    "authentication":
    [
        "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
    ],
    "capabilityDelegation":
    [
        "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
    ],
    "capabilityInvocation":
    [
        "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
    ],
    "@context":
    [
        "https://www.w3.org/ns/did/v1"
    ],
    "id": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
    "keyAgreement":
    [
        "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6LShXhgLqK3vQX3eg18gwZUYNtt6M6FjPqpV1eQD86m8Hwh"
    ],
    "verificationMethod":
    [
        {
            "controller": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
            "id": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
            "publicKeyBase58": "6tW7uQ6c3YgZDoCFbHMB6QFjPENyHRouTUwGnLv36wS9",
            "type": "Ed25519VerificationKey2019"
        },
        {
            "controller": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
            "id": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6LShXhgLqK3vQX3eg18gwZUYNtt6M6FjPqpV1eQD86m8Hwh",
            "publicKeyBase58": "6rXWpXWBpwoJZHdNAJ3XDngQFCZ92nffc2viifTEQvAw",
            "type": "X25519KeyAgreementKey2019"
        }
    ]
}

Import DID

The /did/import endpoint resolves and imports the DID to the underlying data store.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/did/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '<request-body>'

The DID url string.

Code 201

E.g. Import DID having id = did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/did/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d 'did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z'
did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z

Core API

Core REST API functions.

The Core API exposes wallet core functionality in the scope of storing and managing:

The Core API exposes most of the functionalities provided by the SSI Kit, however newer features will only be released in the other API endpoints. Therefore, it is recommended to use the Signatory API, Custodian API and Auditor API for most use cases.

Auditor API - For Verifiers

Auditor REST API functions.

The Auditor API enables anybody to act as a "Verifier" (i.e. verify Verifiable Credentials or Verifiable Presentations). The validation steps can be easily configured by existing or custom policies.

The following functionality is available:

Verification

The /v1/verify endpoint verifies a list of credentials / presentations specified in the JSON-LD format against a set of policies. Each of the policy should be registered with the Auditor before being used in the verification. If at least one of the listed policies fails the verification, then the entire credential is considered to be invalid.

curl -X 'POST' \
  'https://auditor.ssikit.walt.id/v1/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "policies":
    [
        {
            "policy": "string",
            "argument":
            {
                "additionalProp1":
                {},
                "additionalProp2":
                {},
                "additionalProp3":
                {}
            }
        }
    ],
    "credentials":
    [
        {
            "json": "string",
            "issuanceDate": "string",
            "dateFormat":
            {
                "locale":
                {
                    "language": "string",
                    "script": "string",
                    "variant": "string",
                    "displayName": "string",
                    "country": "string",
                    "unicodeLocaleAttributes":
                    [
                        "string"
                    ],
                    "unicodeLocaleKeys":
                    [
                        "string"
                    ],
                    "displayLanguage": "string",
                    "displayScript": "string",
                    "displayCountry": "string",
                    "displayVariant": "string",
                    "extensionKeys":
                    [
                        "string"
                    ],
                    "iso3Language": "string",
                    "iso3Country": "string"
                },
                "decimalStyle":
                {
                    "zeroDigit": "string",
                    "positiveSign": "string",
                    "negativeSign": "string",
                    "decimalSeparator": "string"
                },
                "resolverStyle": "STRICT",
                "resolverFields":
                [
                    {
                        "baseUnit":
                        {
                            "dateBased": true,
                            "timeBased": true,
                            "duration":
                            {
                                "seconds": 0,
                                "nano": 0,
                                "negative": true,
                                "zero": true,
                                "units":
                                [
                                    {
                                        "dateBased": true,
                                        "timeBased": true,
                                        "durationEstimated": true
                                    }
                                ]
                            },
                            "durationEstimated": true
                        },
                        "rangeUnit":
                        {
                            "dateBased": true,
                            "timeBased": true,
                            "duration":
                            {
                                "seconds": 0,
                                "nano": 0,
                                "negative": true,
                                "zero": true,
                                "units":
                                [
                                    {
                                        "dateBased": true,
                                        "timeBased": true,
                                        "durationEstimated": true
                                    }
                                ]
                            },
                            "durationEstimated": true
                        },
                        "dateBased": true,
                        "timeBased": true
                    }
                ],
                "zone":
                {
                    "id": "string",
                    "rules":
                    {
                        "fixedOffset": true,
                        "transitions":
                        [
                            {
                                "offsetBefore":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetAfter":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "duration":
                                {
                                    "seconds": 0,
                                    "nano": 0,
                                    "negative": true,
                                    "zero": true,
                                    "units":
                                    [
                                        {
                                            "dateBased": true,
                                            "timeBased": true,
                                            "durationEstimated": true
                                        }
                                    ]
                                },
                                "gap": true,
                                "dateTimeBefore": "2022-10-06T14:45:20.119Z",
                                "dateTimeAfter": "2022-10-06T14:45:20.119Z",
                                "overlap": true,
                                "instant": "2022-10-06T14:45:20.119Z"
                            }
                        ],
                        "transitionRules":
                        [
                            {
                                "month": "JANUARY",
                                "timeDefinition": "UTC",
                                "standardOffset":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetBefore":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetAfter":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "dayOfWeek": "MONDAY",
                                "dayOfMonthIndicator": 0,
                                "localTime":
                                {
                                    "hour": 0,
                                    "minute": 0,
                                    "second": 0,
                                    "nano": 0
                                },
                                "midnightEndOfDay": true
                            }
                        ]
                    }
                },
                "chronology":
                {
                    "id": "string",
                    "calendarType": "string"
                }
            },
            "jwt": "string",
            "id": "string",
            "type":
            [
                "string"
            ],
            "subject": "string",
            "expirationDate": "string",
            "credentialSchema":
            {
                "id": "string",
                "type": "string"
            },
            "proof":
            {
                "type": "string",
                "creator": "string",
                "created": "string",
                "domain": "string",
                "proofPurpose": "string",
                "verificationMethod": "string",
                "jws": "string",
                "nonce": "string"
            },
            "challenge": "string",
            "validFrom": "string",
            "issued": "string",
            "issuer": "string"
        }
    ]
}
[
    {
        "valid": true,
        "results":
        [
            {
                "valid": true,
                "policyResults":
                {
                    "additionalProp1": true,
                    "additionalProp2": true,
                    "additionalProp3": true
                }
            }
        ]
    }
]

E.g Verification of a UniversityDegree credential against Signature and JsonSchema policies, where SignaturePolicy is failing.

curl -X 'POST' \
  'https://auditor.ssikit.walt.id/v1/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "policies":
    [
        {
            "policy": "SignaturePolicy"
        }
    ],
    "credentials":
    [
        {
            "@context":
            [
                "https://www.w3.org/2018/credentials/v1",
                "https://www.w3.org/2018/credentials/examples/v1"
            ],
            "credentialSubject":
            {
                "degree":
                {
                    "name": "Bachelor of Science and Arts",
                    "type": "BachelorDegree"
                },
                "id": "did:key:z6Mkv58vGsBMwbiyQ3P93MRnYfRgGvn4STEEsj5hFHYe51wu"
            },
            "id": "urn:uuid:7c9d7748-1b66-4361-98eb-c8aab625d9d6",
            "issued": "2022-10-06T15:49:20Z",
            "issuer":
            {
                "id": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
            },
            "validFrom": "2022-10-06T15:49:20Z",
            "issuanceDate": "2022-10-06T15:49:20Z",
            "type":
            [
                "VerifiableCredential",
                "UniversityDegreeCredential"
            ],
            "proof":
            {
                "type": "JsonWebSignature2020",
                "creator": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
                "created": "2022-10-06T15:49:20Z",
                "proofPurpose": "assertionMethod",
                "verificationMethod": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
                "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..iOAli2QhHpp0jZeF2tUj5H4gi_rwaWeypKE4gVdSePp-747gwDCm-bLFjE1MBOFSILZYBWtVWCitrTUmUDfUBw"
            }
        }
    ]
}'
{
    "policies":
    [
        {
            "policy": "SignaturePolicy"
        },
    ],
    "credentials":
    [
        {
            "@context":
            [
                "https://www.w3.org/2018/credentials/v1",
                "https://www.w3.org/2018/credentials/examples/v1"
            ],
            "credentialSubject":
            {
                "degree":
                {
                    "name": "Bachelor of Science and Arts",
                    "type": "BachelorDegree"
                },
                "id": "did:key:z6Mkv58vGsBMwbiyQ3P93MRnYfRgGvn4STEEsj5hFHYe51wu"
            },
            "id": "urn:uuid:7c9d7748-1b66-4361-98eb-c8aab625d9d6",
            "issued": "2022-10-06T15:49:20Z",
            "issuer":
            {
                "id": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX"
            },
            "validFrom": "2022-10-06T15:49:20Z",
            "issuanceDate": "2022-10-06T15:49:20Z",
            "type":
            [
                "VerifiableCredential",
                "UniversityDegreeCredential"
            ],
            "proof":
            {
                "type": "JsonWebSignature2020",
                "creator": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
                "created": "2022-10-06T15:49:20Z",
                "proofPurpose": "assertionMethod",
                "verificationMethod": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX#z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
                "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..iOAli2QhHpp0jZeF2tUj5H4gi_rwaWeypKE4gVdSePp-747gwDCm-bLFjE1MBOFSILZYBWtVWCitrTUmUDfUBw"
            }
        }
    ]
}
{
    "valid": false,
    "results":
    [
        {
            "valid": false,
            "policyResults":
            {
                "SignaturePolicy": true
            }
        }
    ]
}

Policies

The Auditor Rest API also enables policy management with the following methods:

List policies

The /v1/policies endpoint lists the available verification policies. The policy id field is used to reference the policy during verification.

curl -X 'GET' \
  'https://auditor.ssikit.walt.id/v1/policies' \
  -H 'accept: application/json'
No parameters
[
    {
        "applyToVC": true,
        "applyToVP": true,
        "id": "string",
        "description": "string"
    }
]

E.g. Listing of the verification policies

curl -X 'GET' \
  'https://auditor.ssikit.walt.id/v1/policies' \
  -H 'accept: application/json'
[
    {
        "id": "SignaturePolicy",
        "description": "Verify by signature",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "JsonSchemaPolicy",
        "description": "Verify by JSON schema",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "TrustedSchemaRegistryPolicy",
        "description": "Verify by EBSI Trusted Schema Registry",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "TrustedIssuerDidPolicy",
        "description": "Verify by trusted issuer did",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "TrustedIssuerRegistryPolicy",
        "description": "Verify by trusted EBSI Trusted Issuer Registry record",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "TrustedSubjectDidPolicy",
        "description": "Verify by trusted subject did",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "IssuedDateBeforePolicy",
        "description": "Verify by issuance date",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "ValidFromBeforePolicy",
        "description": "Verify by valid from",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "ExpirationDateAfterPolicy",
        "description": "Verify by expiration date",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "GaiaxTrustedPolicy",
        "description": "Verify Gaiax trusted fields",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "GaiaxSDPolicy",
        "description": "Verify Gaiax SD fields",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "ChallengePolicy",
        "description": "Verify challenge",
        "argumentType": "ChallengePolicyArg",
        "isMutable": false
    },
    {
        "id": "VpTokenClaimPolicy",
        "description": "Verify verifiable presentation by OIDC/SIOPv2 VP token claim",
        "argumentType": "VpTokenClaim",
        "isMutable": false
    },
    {
        "id": "CredentialStatusPolicy",
        "description": "Verify by credential status",
        "argumentType": "None",
        "isMutable": false
    },
    {
        "id": "DynamicPolicy",
        "description": "Verify credential by rego policy",
        "argumentType": "DynamicPolicyArg",
        "isMutable": false
    },
    {
        "id": "VerifiableMandatePolicy",
        "description": "Predefined policy for verifiable mandates",
        "argumentType": "JsonObject",
        "isMutable": false
    }
]

Create policy

The /v1/create/{name} creates a dynamic policy. The following parameters can be specified:

  • name path parameter (required) - specifies the value to be used as the policy id

  • update query parameter (optional, defualts to false) - accepts boolean values and specifies whether it should override an existing policy with the same name (only if the policy is mutable)

  • downloadPolicy query parameter (optional, defaults to false) - accepts boolean values and identifies the scope of the policy field:

    • specifies a remote source that should be resolved to a policy

    • specifies the actual policy content

{
    "name": "string",
    "description": "string",
    "input":
    {
        "additionalProp1":
        {},
        "additionalProp2":
        {},
        "additionalProp3":
        {}
    },
    "policy": "string",
    "dataPath": "string",
    "policyQuery": "string",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}

E.g. Creating a Rego policy that checks if a credential subject id is not null or empty

curl -X 'POST' \
  'https://auditor.ssikit.walt.id/v1/create/MyPolicy?update=false&downloadPolicy=true' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "MyPolicy",
    "description": "my policy",
    "input": {},
    "policy": "package system\r\nimport future.keywords.if\r\ndefault allow := false\r\nallow if regex.match(\".+\", data.credentialSubject.id)",
    "dataPath": "$",
    "policyQuery": "data.system.main",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}'
{
    "name": "MyPolicy",
    "description": "my policy",
    "policy": "package system\r\nimport future.keywords.if\r\ndefault allow := false\r\nallow if regex.match(\".+\", data.credentialSubject.id)",
    "dataPath": "$",
    "policyQuery": "data.system.main",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}

Code 200

Delete policy

The /v1/delete/{name} endpoint deletes a dynamic policy. The following parameters can be specified:

  • name path parameter (required) - specifies the id value of the policy

curl -X 'DELETE' \
  'https://auditor.ssikit.walt.id/v1/delete/{name}' \
  -H 'accept: */*'

Policy removed / Policy not found

E.g. Removing the policy having 'MyPolicy' name

curl -X 'DELETE' \
  'https://auditor.ssikit.walt.id/v1/delete/MyPolicy' \
  -H 'accept: */*'

Policy removed / Policy not found

Credentials management

The following functions are available for credentials management:

List credentials

The /credentials endpoint lists the available credentials:

  • id - query parameter (optional) - the list of credentials ids

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/credentials' \
  -H 'accept: application/json'
No parameters
The list of credentials

E.g. List the the credentials having ids urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270 and urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84271

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/credentials?id=urn%3Auuid%3Ad36986f1-3cc0-4156-b5a4-6d3deab84270&id=urn%3Auuid%3Ad36986f1-3cc0-4156-b5a4-6d3deab84271' \
  -H 'accept: application/json'
{
    "list":
    [
        {
            "@context":
            [
                "https://www.w3.org/2018/credentials/v1",
                "https://www.w3.org/2018/credentials/examples/v1"
            ],
            "credentialSubject":
            {
                "degree":
                {
                    "name": "Bachelor of Science and Arts",
                    "type": "BachelorDegree"
                },
                "id": "did:web:my.domain"
            },
            "id": "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270",
            "issued": "2022-10-07T09:53:41.369913097Z",
            "issuer":
            {
                "id": "did:web:walt.id"
            },
            "proof":
            {
                "created": "2022-10-07T09:53:41Z",
                "creator": "did:web:walt.id",
                "domain": "https://api.preprod.ebsi.eu",
                "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ",
                "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
                "type": "Ed25519Signature2018"
            },
            "validFrom": "2022-10-07T09:53:41.369917079Z",
            "issuanceDate": "2022-10-07T09:53:41.369917079Z",
            "type":
            [
                "VerifiableCredential",
                "UniversityDegreeCredential"
            ]
        }
    ]
}

List credentials compact

The /credentials/list/credentialIds lists the available credentials ids.

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/credentials/list/credentialIds' \
  -H 'accept: application/json'
No parameters
The list of credentials ids

E.g. List the available credentials ids.

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/credentials/list/credentialIds' \
  -H 'accept: application/json'
{
    "list":
    [
        "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270"
    ]
}

Load credential

The /credentials/{id} loads a credential specified by:

  • id - path parameter (required) - the credential id

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/credentials/{id}' \
  -H 'accept: application/json'
No parameters
The credential string

E.g. Load the credential having id = urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270.

curl -X 'GET' \
  'https://custodian.ssikit.walt.id/credentials/urn%3Auuid%3Ad36986f1-3cc0-4156-b5a4-6d3deab84270' \
  -H 'accept: application/json'
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
    ],
    "credentialSubject":
    {
        "degree":
        {
            "name": "Bachelor of Science and Arts",
            "type": "BachelorDegree"
        },
        "id": "did:web:my.domain"
    },
    "id": "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270",
    "issued": "2022-10-07T09:53:41.369913097Z",
    "issuer":
    {
        "id": "did:web:walt.id"
    },
    "proof":
    {
        "created": "2022-10-07T09:53:41Z",
        "creator": "did:web:walt.id",
        "domain": "https://api.preprod.ebsi.eu",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ",
        "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
        "type": "Ed25519Signature2018"
    },
    "validFrom": "2022-10-07T09:53:41.369917079Z",
    "issuanceDate": "2022-10-07T09:53:41.369917079Z",
    "type":
    [
        "VerifiableCredential",
        "UniversityDegreeCredential"
    ]
}

Store credential

The /credentials/{alias} endpoint stores a verifiable credential by:

  • alias - path parameter (required) - the credential's id

curl -X 'PUT' \
  'https://custodian.ssikit.walt.id/credentials/urn%3Auuid%3Ad36986f1-3cc0-4156-b5a4-6d3deab84270' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'

The body should contain, the VC to be store. If no adjustments are required to VC, then the body can be the VC itself (e.g. the one received from the create VC endpoint).

{
    "json": "string",
    "issuanceDate": "string",
    "dateFormat":
    {
        "locale":
        {
            "language": "string",
            "script": "string",
            "variant": "string",
            "displayName": "string",
            "country": "string",
            "unicodeLocaleAttributes":
            [
                "string"
            ],
            "unicodeLocaleKeys":
            [
                "string"
            ],
            "displayLanguage": "string",
            "displayScript": "string",
            "displayCountry": "string",
            "displayVariant": "string",
            "extensionKeys":
            [
                "string"
            ],
            "iso3Language": "string",
            "iso3Country": "string"
        },
        "decimalStyle":
        {
            "zeroDigit": "string",
            "positiveSign": "string",
            "negativeSign": "string",
            "decimalSeparator": "string"
        },
        "resolverStyle": "STRICT",
        "resolverFields":
        [
            {
                "baseUnit":
                {
                    "dateBased": true,
                    "timeBased": true,
                    "duration":
                    {
                        "seconds": 0,
                        "nano": 0,
                        "negative": true,
                        "zero": true,
                        "units":
                        [
                            {
                                "dateBased": true,
                                "timeBased": true,
                                "durationEstimated": true
                            }
                        ]
                    },
                    "durationEstimated": true
                },
                "rangeUnit":
                {
                    "dateBased": true,
                    "timeBased": true,
                    "duration":
                    {
                        "seconds": 0,
                        "nano": 0,
                        "negative": true,
                        "zero": true,
                        "units":
                        [
                            {
                                "dateBased": true,
                                "timeBased": true,
                                "durationEstimated": true
                            }
                        ]
                    },
                    "durationEstimated": true
                },
                "dateBased": true,
                "timeBased": true
            }
        ],
        "zone":
        {
            "id": "string",
            "rules":
            {
                "fixedOffset": true,
                "transitions":
                [
                    {
                        "offsetBefore":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetAfter":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "duration":
                        {
                            "seconds": 0,
                            "nano": 0,
                            "negative": true,
                            "zero": true,
                            "units":
                            [
                                {
                                    "dateBased": true,
                                    "timeBased": true,
                                    "durationEstimated": true
                                }
                            ]
                        },
                        "gap": true,
                        "dateTimeBefore": "2022-10-09T09:09:41.896Z",
                        "dateTimeAfter": "2022-10-09T09:09:41.896Z",
                        "overlap": true,
                        "instant": "2022-10-09T09:09:41.896Z"
                    }
                ],
                "transitionRules":
                [
                    {
                        "month": "JANUARY",
                        "timeDefinition": "UTC",
                        "standardOffset":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetBefore":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetAfter":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "dayOfWeek": "MONDAY",
                        "dayOfMonthIndicator": 0,
                        "localTime":
                        {
                            "hour": 0,
                            "minute": 0,
                            "second": 0,
                            "nano": 0
                        },
                        "midnightEndOfDay": true
                    }
                ]
            }
        },
        "chronology":
        {
            "id": "string",
            "calendarType": "string"
        }
    },
    "jwt": "string",
    "id": "string",
    "type":
    [
        "string"
    ],
    "subject": "string",
    "expirationDate": "string",
    "credentialSchema":
    {
        "id": "string",
        "type": "string"
    },
    "proof":
    {
        "type": "string",
        "creator": "string",
        "created": "string",
        "domain": "string",
        "proofPurpose": "string",
        "verificationMethod": "string",
        "jws": "string",
        "nonce": "string"
    },
    "challenge": "string",
    "validFrom": "string",
    "issued": "string",
    "issuer": "string"
}
Code 201

E.g. Store the UniversityDegree verifiable credential.

curl -X 'PUT' \
  'https://custodian.ssikit.walt.id/credentials/urn%3Auuid%3Ad36986f1-3cc0-4156-b5a4-6d3deab84270' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "@context" : [ "https://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/examples/v1" ],
  "credentialSubject" : {
    "degree" : {
      "name" : "Bachelor of Science and Arts",
      "type" : "BachelorDegree"
    },
    "id" : "did:web:my.domain"
  },
  "id" : "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270",
  "issued" : "2022-10-07T09:53:41.369913097Z",
  "issuer" : {
    "id" : "did:web:walt.id"
  },
  "validFrom" : "2022-10-07T09:53:41.369917079Z",
  "issuanceDate" : "2022-10-07T09:53:41.369917079Z",
  "type" : [ "VerifiableCredential", "UniversityDegreeCredential" ],
  "proof" : {
    "type" : "Ed25519Signature2018",
    "creator" : "did:web:walt.id",
    "created" : "2022-10-07T09:53:41Z",
    "domain" : "https://api.preprod.ebsi.eu",
    "nonce" : "dc2be572-cca4-43dc-9903-0fec1dcf786f",
    "jws" : "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ"
  }
}'
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
    ],
    "credentialSubject":
    {
        "degree":
        {
            "name": "Bachelor of Science and Arts",
            "type": "BachelorDegree"
        },
        "id": "did:web:my.domain"
    },
    "id": "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270",
    "issued": "2022-10-07T09:53:41.369913097Z",
    "issuer":
    {
        "id": "did:web:walt.id"
    },
    "validFrom": "2022-10-07T09:53:41.369917079Z",
    "issuanceDate": "2022-10-07T09:53:41.369917079Z",
    "type":
    [
        "VerifiableCredential",
        "UniversityDegreeCredential"
    ],
    "proof":
    {
        "type": "Ed25519Signature2018",
        "creator": "did:web:walt.id",
        "created": "2022-10-07T09:53:41Z",
        "domain": "https://api.preprod.ebsi.eu",
        "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ"
    }
}

Delete credential

The /credentials/{alias} deletes a credential by:

  • alias - path parameter (required) - the credential's id

curl -X 'DELETE' \
  'https://custodian.ssikit.walt.id/credentials/{alias}' \
  -H 'accept: application/json'
No parameters
Code 200

E.g. Delete the credential with id = urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270

curl -X 'DELETE' \
  'https://custodian.ssikit.walt.id/credentials/urn%3Auuid%3Ad36986f1-3cc0-4156-b5a4-6d3deab84270' \
  -H 'accept: application/json'

Present credential

The /credentials/present endpoint creates a verifiable presentation from the specified credentials.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/credentials/present' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "vcs":
    [
        "string"
    ],
    "holderDid": "string",
    "verifierDid": "string",
    "domain": "string",
    "challenge": "string"
}
{
    "context":
    [
        "string"
    ],
    "id": "string",
    "holder": "string",
    "verifiableCredential":
    [
        {
            "json": "string",
            "issuanceDate": "string",
            "dateFormat":
            {
                "locale":
                {
                    "language": "string",
                    "script": "string",
                    "variant": "string",
                    "displayName": "string",
                    "country": "string",
                    "unicodeLocaleAttributes":
                    [
                        "string"
                    ],
                    "unicodeLocaleKeys":
                    [
                        "string"
                    ],
                    "displayLanguage": "string",
                    "displayScript": "string",
                    "displayCountry": "string",
                    "displayVariant": "string",
                    "extensionKeys":
                    [
                        "string"
                    ],
                    "iso3Language": "string",
                    "iso3Country": "string"
                },
                "decimalStyle":
                {
                    "zeroDigit": "string",
                    "positiveSign": "string",
                    "negativeSign": "string",
                    "decimalSeparator": "string"
                },
                "resolverStyle": "STRICT",
                "resolverFields":
                [
                    {
                        "baseUnit":
                        {
                            "dateBased": true,
                            "timeBased": true,
                            "duration":
                            {
                                "seconds": 0,
                                "nano": 0,
                                "negative": true,
                                "zero": true,
                                "units":
                                [
                                    {
                                        "dateBased": true,
                                        "timeBased": true,
                                        "durationEstimated": true
                                    }
                                ]
                            },
                            "durationEstimated": true
                        },
                        "rangeUnit":
                        {
                            "dateBased": true,
                            "timeBased": true,
                            "duration":
                            {
                                "seconds": 0,
                                "nano": 0,
                                "negative": true,
                                "zero": true,
                                "units":
                                [
                                    {
                                        "dateBased": true,
                                        "timeBased": true,
                                        "durationEstimated": true
                                    }
                                ]
                            },
                            "durationEstimated": true
                        },
                        "dateBased": true,
                        "timeBased": true
                    }
                ],
                "zone":
                {
                    "id": "string",
                    "rules":
                    {
                        "fixedOffset": true,
                        "transitions":
                        [
                            {
                                "offsetBefore":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetAfter":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "duration":
                                {
                                    "seconds": 0,
                                    "nano": 0,
                                    "negative": true,
                                    "zero": true,
                                    "units":
                                    [
                                        {
                                            "dateBased": true,
                                            "timeBased": true,
                                            "durationEstimated": true
                                        }
                                    ]
                                },
                                "gap": true,
                                "dateTimeBefore": "2022-10-09T11:30:48.206Z",
                                "dateTimeAfter": "2022-10-09T11:30:48.206Z",
                                "overlap": true,
                                "instant": "2022-10-09T11:30:48.206Z"
                            }
                        ],
                        "transitionRules":
                        [
                            {
                                "month": "JANUARY",
                                "timeDefinition": "UTC",
                                "standardOffset":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetBefore":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetAfter":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "dayOfWeek": "MONDAY",
                                "dayOfMonthIndicator": 0,
                                "localTime":
                                {
                                    "hour": 0,
                                    "minute": 0,
                                    "second": 0,
                                    "nano": 0
                                },
                                "midnightEndOfDay": true
                            }
                        ]
                    }
                },
                "chronology":
                {
                    "id": "string",
                    "calendarType": "string"
                }
            },
            "jwt": "string",
            "id": "string",
            "type":
            [
                "string"
            ],
            "subject": "string",
            "expirationDate": "string",
            "credentialSchema":
            {
                "id": "string",
                "type": "string"
            },
            "proof":
            {
                "type": "string",
                "creator": "string",
                "created": "string",
                "domain": "string",
                "proofPurpose": "string",
                "verificationMethod": "string",
                "jws": "string",
                "nonce": "string"
            },
            "challenge": "string",
            "validFrom": "string",
            "issued": "string",
            "issuer": "string"
        }
    ],
    "proof":
    {
        "type": "string",
        "creator": "string",
        "created": "string",
        "domain": "string",
        "proofPurpose": "string",
        "verificationMethod": "string",
        "jws": "string",
        "nonce": "string"
    },
    "issued": "string",
    "validFrom": "string",
    "expirationDate": "string",
    "json": "string",
    "issuanceDate": "string",
    "dateFormat":
    {
        "locale":
        {
            "language": "string",
            "script": "string",
            "variant": "string",
            "displayName": "string",
            "country": "string",
            "unicodeLocaleAttributes":
            [
                "string"
            ],
            "unicodeLocaleKeys":
            [
                "string"
            ],
            "displayLanguage": "string",
            "displayScript": "string",
            "displayCountry": "string",
            "displayVariant": "string",
            "extensionKeys":
            [
                "string"
            ],
            "iso3Language": "string",
            "iso3Country": "string"
        },
        "decimalStyle":
        {
            "zeroDigit": "string",
            "positiveSign": "string",
            "negativeSign": "string",
            "decimalSeparator": "string"
        },
        "resolverStyle": "STRICT",
        "resolverFields":
        [
            {
                "baseUnit":
                {
                    "dateBased": true,
                    "timeBased": true,
                    "duration":
                    {
                        "seconds": 0,
                        "nano": 0,
                        "negative": true,
                        "zero": true,
                        "units":
                        [
                            {
                                "dateBased": true,
                                "timeBased": true,
                                "durationEstimated": true
                            }
                        ]
                    },
                    "durationEstimated": true
                },
                "rangeUnit":
                {
                    "dateBased": true,
                    "timeBased": true,
                    "duration":
                    {
                        "seconds": 0,
                        "nano": 0,
                        "negative": true,
                        "zero": true,
                        "units":
                        [
                            {
                                "dateBased": true,
                                "timeBased": true,
                                "durationEstimated": true
                            }
                        ]
                    },
                    "durationEstimated": true
                },
                "dateBased": true,
                "timeBased": true
            }
        ],
        "zone":
        {
            "id": "string",
            "rules":
            {
                "fixedOffset": true,
                "transitions":
                [
                    {
                        "offsetBefore":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetAfter":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "duration":
                        {
                            "seconds": 0,
                            "nano": 0,
                            "negative": true,
                            "zero": true,
                            "units":
                            [
                                {
                                    "dateBased": true,
                                    "timeBased": true,
                                    "durationEstimated": true
                                }
                            ]
                        },
                        "gap": true,
                        "dateTimeBefore": "2022-10-09T11:30:48.207Z",
                        "dateTimeAfter": "2022-10-09T11:30:48.207Z",
                        "overlap": true,
                        "instant": "2022-10-09T11:30:48.207Z"
                    }
                ],
                "transitionRules":
                [
                    {
                        "month": "JANUARY",
                        "timeDefinition": "UTC",
                        "standardOffset":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetBefore":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetAfter":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "dayOfWeek": "MONDAY",
                        "dayOfMonthIndicator": 0,
                        "localTime":
                        {
                            "hour": 0,
                            "minute": 0,
                            "second": 0,
                            "nano": 0
                        },
                        "midnightEndOfDay": true
                    }
                ]
            }
        },
        "chronology":
        {
            "id": "string",
            "calendarType": "string"
        }
    },
    "jwt": "string",
    "type":
    [
        "string"
    ],
    "subject": "string",
    "credentialSchema":
    {
        "id": "string",
        "type": "string"
    },
    "issuer": "string",
    "challenge": "string"
}

E.g. Create a verifiable presentation from the provided VeriafiableID and OpenBadgeCredential credentials for a holder with did = did:web:my.domain.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/credentials/present' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "vcs": [
"{\r\n    \"@context\":\r\n    [\r\n        \"https:\/\/www.w3.org\/2018\/credentials\/v1\"\r\n    ],\r\n    \"credentialSchema\":\r\n    {\r\n        \"id\": \"https:\/\/api.preprod.ebsi.eu\/trusted-schemas-registry\/v1\/schemas\/0xb77f8516a965631b4f197ad54c65a9e2f9936ebfb76bae4906d33744dbcc60ba\",\r\n        \"type\": \"FullJsonSchemaValidator2021\"\r\n    },\r\n    \"credentialSubject\":\r\n    {\r\n        \"currentAddress\":\r\n        [\r\n            \"1 Boulevard de la Libert\u00E9, 59800 Lille\"\r\n        ],\r\n        \"dateOfBirth\": \"1993-04-08\",\r\n        \"familyName\": \"DOE\",\r\n        \"firstName\": \"Jane\",\r\n        \"gender\": \"FEMALE\",\r\n        \"id\": \"did:web:my.domain\",\r\n        \"nameAndFamilyNameAtBirth\": \"Jane DOE\",\r\n        \"personalIdentifier\": \"0904008084H\",\r\n        \"placeOfBirth\": \"LILLE, FRANCE\"\r\n    },\r\n    \"evidence\":\r\n    [\r\n        {\r\n            \"documentPresence\":\r\n            [\r\n                \"Physical\"\r\n            ],\r\n            \"evidenceDocument\":\r\n            [\r\n                \"Passport\"\r\n            ],\r\n            \"subjectPresence\": \"Physical\",\r\n            \"type\":\r\n            [\r\n                \"DocumentVerification\"\r\n            ],\r\n            \"verifier\": \"did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN\"\r\n        }\r\n    ],\r\n    \"id\": \"urn:uuid:4d88d22e-214b-4aa3-a4e9-906da9daf36a\",\r\n    \"issued\": \"2022-10-09T10:11:51Z\",\r\n    \"issuer\": \"did:web:walt.id\",\r\n    \"validFrom\": \"2022-10-09T10:11:51Z\",\r\n    \"issuanceDate\": \"2022-10-09T10:11:51Z\",\r\n    \"type\":\r\n    [\r\n        \"VerifiableCredential\",\r\n        \"VerifiableAttestation\",\r\n        \"VerifiableId\"\r\n    ],\r\n    \"proof\":\r\n    {\r\n        \"type\": \"JsonWebSignature2020\",\r\n        \"creator\": \"did:web:walt.id\",\r\n        \"created\": \"2022-10-09T10:11:52Z\",\r\n        \"proofPurpose\": \"assertionMethod\",\r\n        \"verificationMethod\": \"did:web:walt.id#c1672b42f846471eb2c22fd601169566\",\r\n        \"jws\": \"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..H4mLlx3Ot3rWV_EzthoiAjZs6J4UkJywuGENmSsqNHEnMGlwFHRKSNGWHwWnz2a7R38ktyo8r0_3sc2IkxGvCA\"\r\n    }\r\n}",
"{\r\n  \"@context\" : [ \"https:\/\/www.w3.org\/2018\/credentials\/v1\", \"https:\/\/w3c-ccg.github.io\/vc-ed\/plugfest-1-2022\/jff-vc-edu-plugfest-1-context.json\" ],\r\n  \"credentialSubject\" : {\r\n    \"achievement\" : {\r\n      \"criteria\" : {\r\n        \"narrative\" : \"The first cohort of the JFF Plugfest 1 in May\/June of 2021 collaborated to push interoperability of VCs in education forward.\",\r\n        \"type\" : \"Criteria\"\r\n      },\r\n      \"description\" : \"This wallet can display this Open Badge 3.0\",\r\n      \"image\" : \"https:\/\/w3c-ccg.github.io\/vc-ed\/plugfest-1-2022\/images\/plugfest-1-badge-image.png\",\r\n      \"name\" : \"Our Wallet Passed JFF Plugfest #1 2022\",\r\n      \"type\" : \"Achievement\"\r\n    },\r\n    \"id\" : \"did:web:my.domain\",\r\n    \"type\" : \"AchievementSubject\"\r\n  },\r\n  \"id\" : \"urn:uuid:1745f6ff-3e12-4678-b714-e779e989ae25\",\r\n  \"issuanceDate\" : \"2020-03-10T04:24:12.164Z\",\r\n  \"issued\" : \"2022-10-09T10:12:50Z\",\r\n  \"issuer\" : {\r\n    \"id\" : \"did:web:walt.id\",\r\n    \"image\" : \"https:\/\/kayaelle.github.io\/vc-ed\/plugfest-1-2022\/images\/JFF_LogoLockup.png\",\r\n    \"name\" : \"Jobs for the Future (JFF)\",\r\n    \"type\" : \"Profile\",\r\n    \"url\" : \"https:\/\/kayaelle.github.io\/vc-ed\/plugfest-1-2022\/images\/JFF_LogoLockup.png\"\r\n  },\r\n  \"validFrom\" : \"2022-10-09T10:12:50Z\",\r\n  \"type\" : [ \"VerifiableCredential\", \"OpenBadgeCredential\" ],\r\n  \"proof\" : {\r\n    \"type\" : \"JsonWebSignature2020\",\r\n    \"creator\" : \"did:web:walt.id\",\r\n    \"created\" : \"2022-10-09T10:12:50Z\",\r\n    \"proofPurpose\" : \"assertionMethod\",\r\n    \"verificationMethod\" : \"did:web:walt.id#c1672b42f846471eb2c22fd601169566\",\r\n    \"jws\" : \"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..8EIBOS-UKOUXboKElqWxRuux851NTbbll_sd16-67vv8Gh8vicJDNu7DjU-QgpsnJO_4mG8swxrOJeIFuU58Bg\"\r\n  }\r\n}"
  ],
  "holderDid": "did:web:my.domain"
}'
{
    "vcs":
    [
        "{\r\n    \"@context\":\r\n    [\r\n        \"https://www.w3.org/2018/credentials/v1\"\r\n    ],\r\n    \"credentialSchema\":\r\n    {\r\n        \"id\": \"https://api.preprod.ebsi.eu/trusted-schemas-registry/v1/schemas/0xb77f8516a965631b4f197ad54c65a9e2f9936ebfb76bae4906d33744dbcc60ba\",\r\n        \"type\": \"FullJsonSchemaValidator2021\"\r\n    },\r\n    \"credentialSubject\":\r\n    {\r\n        \"currentAddress\":\r\n        [\r\n            \"1 Boulevard de la Liberté, 59800 Lille\"\r\n        ],\r\n        \"dateOfBirth\": \"1993-04-08\",\r\n        \"familyName\": \"DOE\",\r\n        \"firstName\": \"Jane\",\r\n        \"gender\": \"FEMALE\",\r\n        \"id\": \"did:web:my.domain\",\r\n        \"nameAndFamilyNameAtBirth\": \"Jane DOE\",\r\n        \"personalIdentifier\": \"0904008084H\",\r\n        \"placeOfBirth\": \"LILLE, FRANCE\"\r\n    },\r\n    \"evidence\":\r\n    [\r\n        {\r\n            \"documentPresence\":\r\n            [\r\n                \"Physical\"\r\n            ],\r\n            \"evidenceDocument\":\r\n            [\r\n                \"Passport\"\r\n            ],\r\n            \"subjectPresence\": \"Physical\",\r\n            \"type\":\r\n            [\r\n                \"DocumentVerification\"\r\n            ],\r\n            \"verifier\": \"did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN\"\r\n        }\r\n    ],\r\n    \"id\": \"urn:uuid:4d88d22e-214b-4aa3-a4e9-906da9daf36a\",\r\n    \"issued\": \"2022-10-09T10:11:51Z\",\r\n    \"issuer\": \"did:web:walt.id\",\r\n    \"validFrom\": \"2022-10-09T10:11:51Z\",\r\n    \"issuanceDate\": \"2022-10-09T10:11:51Z\",\r\n    \"type\":\r\n    [\r\n        \"VerifiableCredential\",\r\n        \"VerifiableAttestation\",\r\n        \"VerifiableId\"\r\n    ],\r\n    \"proof\":\r\n    {\r\n        \"type\": \"JsonWebSignature2020\",\r\n        \"creator\": \"did:web:walt.id\",\r\n        \"created\": \"2022-10-09T10:11:52Z\",\r\n        \"proofPurpose\": \"assertionMethod\",\r\n        \"verificationMethod\": \"did:web:walt.id#c1672b42f846471eb2c22fd601169566\",\r\n        \"jws\": \"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..H4mLlx3Ot3rWV_EzthoiAjZs6J4UkJywuGENmSsqNHEnMGlwFHRKSNGWHwWnz2a7R38ktyo8r0_3sc2IkxGvCA\"\r\n    }\r\n}",
        "{\r\n  \"@context\" : [ \"https://www.w3.org/2018/credentials/v1\", \"https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/jff-vc-edu-plugfest-1-context.json\" ],\r\n  \"credentialSubject\" : {\r\n    \"achievement\" : {\r\n      \"criteria\" : {\r\n        \"narrative\" : \"The first cohort of the JFF Plugfest 1 in May/June of 2021 collaborated to push interoperability of VCs in education forward.\",\r\n        \"type\" : \"Criteria\"\r\n      },\r\n      \"description\" : \"This wallet can display this Open Badge 3.0\",\r\n      \"image\" : \"https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/images/plugfest-1-badge-image.png\",\r\n      \"name\" : \"Our Wallet Passed JFF Plugfest #1 2022\",\r\n      \"type\" : \"Achievement\"\r\n    },\r\n    \"id\" : \"did:web:my.domain\",\r\n    \"type\" : \"AchievementSubject\"\r\n  },\r\n  \"id\" : \"urn:uuid:1745f6ff-3e12-4678-b714-e779e989ae25\",\r\n  \"issuanceDate\" : \"2020-03-10T04:24:12.164Z\",\r\n  \"issued\" : \"2022-10-09T10:12:50Z\",\r\n  \"issuer\" : {\r\n    \"id\" : \"did:web:walt.id\",\r\n    \"image\" : \"https://kayaelle.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png\",\r\n    \"name\" : \"Jobs for the Future (JFF)\",\r\n    \"type\" : \"Profile\",\r\n    \"url\" : \"https://kayaelle.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png\"\r\n  },\r\n  \"validFrom\" : \"2022-10-09T10:12:50Z\",\r\n  \"type\" : [ \"VerifiableCredential\", \"OpenBadgeCredential\" ],\r\n  \"proof\" : {\r\n    \"type\" : \"JsonWebSignature2020\",\r\n    \"creator\" : \"did:web:walt.id\",\r\n    \"created\" : \"2022-10-09T10:12:50Z\",\r\n    \"proofPurpose\" : \"assertionMethod\",\r\n    \"verificationMethod\" : \"did:web:walt.id#c1672b42f846471eb2c22fd601169566\",\r\n    \"jws\" : \"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..8EIBOS-UKOUXboKElqWxRuux851NTbbll_sd16-67vv8Gh8vicJDNu7DjU-QgpsnJO_4mG8swxrOJeIFuU58Bg\"\r\n  }\r\n}"
    ],
    "holderDid": "did:web:my.domain"
}
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1"
    ],
    "holder": "did:web:my.domain",
    "id": "urn:uuid:0f9a8692-badf-4f0c-aa07-a4c3279e3470",
    "type":
    [
        "VerifiablePresentation"
    ],
    "verifiableCredential":
    [
        {
            "@context":
            [
                "https://www.w3.org/2018/credentials/v1"
            ],
            "credentialSchema":
            {
                "id": "https://api.preprod.ebsi.eu/trusted-schemas-registry/v1/schemas/0xb77f8516a965631b4f197ad54c65a9e2f9936ebfb76bae4906d33744dbcc60ba",
                "type": "FullJsonSchemaValidator2021"
            },
            "credentialSubject":
            {
                "currentAddress":
                [
                    "1 Boulevard de la Liberté, 59800 Lille"
                ],
                "dateOfBirth": "1993-04-08",
                "familyName": "DOE",
                "firstName": "Jane",
                "gender": "FEMALE",
                "id": "did:web:my.domain",
                "nameAndFamilyNameAtBirth": "Jane DOE",
                "personalIdentifier": "0904008084H",
                "placeOfBirth": "LILLE, FRANCE"
            },
            "evidence":
            [
                {
                    "documentPresence":
                    [
                        "Physical"
                    ],
                    "evidenceDocument":
                    [
                        "Passport"
                    ],
                    "subjectPresence": "Physical",
                    "type":
                    [
                        "DocumentVerification"
                    ],
                    "verifier": "did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN"
                }
            ],
            "id": "urn:uuid:4d88d22e-214b-4aa3-a4e9-906da9daf36a",
            "issued": "2022-10-09T10:11:51Z",
            "issuer": "did:web:walt.id",
            "proof":
            {
                "created": "2022-10-09T10:11:52Z",
                "creator": "did:web:walt.id",
                "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..H4mLlx3Ot3rWV_EzthoiAjZs6J4UkJywuGENmSsqNHEnMGlwFHRKSNGWHwWnz2a7R38ktyo8r0_3sc2IkxGvCA",
                "proofPurpose": "assertionMethod",
                "type": "JsonWebSignature2020",
                "verificationMethod": "did:web:walt.id#c1672b42f846471eb2c22fd601169566"
            },
            "validFrom": "2022-10-09T10:11:51Z",
            "issuanceDate": "2022-10-09T10:11:51Z",
            "type":
            [
                "VerifiableCredential",
                "VerifiableAttestation",
                "VerifiableId"
            ]
        },
        {
            "@context":
            [
                "https://www.w3.org/2018/credentials/v1",
                "https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/jff-vc-edu-plugfest-1-context.json"
            ],
            "credentialSubject":
            {
                "achievement":
                {
                    "criteria":
                    {
                        "narrative": "The first cohort of the JFF Plugfest 1 in May/June of 2021 collaborated to push interoperability of VCs in education forward.",
                        "type": "Criteria"
                    },
                    "description": "This wallet can display this Open Badge 3.0",
                    "image": "https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/images/plugfest-1-badge-image.png",
                    "name": "Our Wallet Passed JFF Plugfest #1 2022",
                    "type": "Achievement"
                },
                "id": "did:web:my.domain",
                "type": "AchievementSubject"
            },
            "id": "urn:uuid:1745f6ff-3e12-4678-b714-e779e989ae25",
            "issuanceDate": "2020-03-10T04:24:12.164Z",
            "issued": "2022-10-09T10:12:50Z",
            "issuer":
            {
                "id": "did:web:walt.id",
                "image": "https://kayaelle.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png",
                "name": "Jobs for the Future (JFF)",
                "type": "Profile",
                "url": "https://kayaelle.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png"
            },
            "proof":
            {
                "created": "2022-10-09T10:12:50Z",
                "creator": "did:web:walt.id",
                "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..8EIBOS-UKOUXboKElqWxRuux851NTbbll_sd16-67vv8Gh8vicJDNu7DjU-QgpsnJO_4mG8swxrOJeIFuU58Bg",
                "proofPurpose": "assertionMethod",
                "type": "JsonWebSignature2020",
                "verificationMethod": "did:web:walt.id#c1672b42f846471eb2c22fd601169566"
            },
            "validFrom": "2022-10-09T10:12:50Z",
            "type":
            [
                "VerifiableCredential",
                "OpenBadgeCredential"
            ]
        }
    ],
    "proof":
    {
        "type": "Ed25519Signature2018",
        "creator": "did:web:my.domain",
        "created": "2022-10-09T10:21:11Z",
        "domain": "https://api.preprod.ebsi.eu",
        "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
        "proofPurpose": "authentication",
        "verificationMethod": "did:web:my.domain#c5b11445be0e4d37863170df3328630b",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..2S3aHQISbL81Dbe1yOakXBFGvUJjxEZ7zGZZZ3XOJibtAON5v9lr5Q9NGt1c8h0zSrTLQDl2-fQ7A6HA9KL9Cw"
    }
}

Present stored credential

The /credentials/presentIds endpoint creates a verifiable presentation from the specified credential ids.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/credentials/presentIds' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "vcIds":
    [
        "string"
    ],
    "holderDid": "string",
    "verifierDid": "string",
    "domain": "string",
    "challenge": "string"
}
{
    "context":
    [
        "string"
    ],
    "id": "string",
    "holder": "string",
    "verifiableCredential":
    [
        {
            "json": "string",
            "issuanceDate": "string",
            "dateFormat":
            {
                "locale":
                {
                    "language": "string",
                    "script": "string",
                    "variant": "string",
                    "displayName": "string",
                    "country": "string",
                    "unicodeLocaleAttributes":
                    [
                        "string"
                    ],
                    "unicodeLocaleKeys":
                    [
                        "string"
                    ],
                    "displayLanguage": "string",
                    "displayScript": "string",
                    "displayCountry": "string",
                    "displayVariant": "string",
                    "extensionKeys":
                    [
                        "string"
                    ],
                    "iso3Language": "string",
                    "iso3Country": "string"
                },
                "decimalStyle":
                {
                    "zeroDigit": "string",
                    "positiveSign": "string",
                    "negativeSign": "string",
                    "decimalSeparator": "string"
                },
                "resolverStyle": "STRICT",
                "resolverFields":
                [
                    {
                        "baseUnit":
                        {
                            "dateBased": true,
                            "timeBased": true,
                            "duration":
                            {
                                "seconds": 0,
                                "nano": 0,
                                "negative": true,
                                "zero": true,
                                "units":
                                [
                                    {
                                        "dateBased": true,
                                        "timeBased": true,
                                        "durationEstimated": true
                                    }
                                ]
                            },
                            "durationEstimated": true
                        },
                        "rangeUnit":
                        {
                            "dateBased": true,
                            "timeBased": true,
                            "duration":
                            {
                                "seconds": 0,
                                "nano": 0,
                                "negative": true,
                                "zero": true,
                                "units":
                                [
                                    {
                                        "dateBased": true,
                                        "timeBased": true,
                                        "durationEstimated": true
                                    }
                                ]
                            },
                            "durationEstimated": true
                        },
                        "dateBased": true,
                        "timeBased": true
                    }
                ],
                "zone":
                {
                    "id": "string",
                    "rules":
                    {
                        "fixedOffset": true,
                        "transitions":
                        [
                            {
                                "offsetBefore":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetAfter":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "duration":
                                {
                                    "seconds": 0,
                                    "nano": 0,
                                    "negative": true,
                                    "zero": true,
                                    "units":
                                    [
                                        {
                                            "dateBased": true,
                                            "timeBased": true,
                                            "durationEstimated": true
                                        }
                                    ]
                                },
                                "gap": true,
                                "dateTimeBefore": "2022-10-09T09:52:44.738Z",
                                "dateTimeAfter": "2022-10-09T09:52:44.738Z",
                                "overlap": true,
                                "instant": "2022-10-09T09:52:44.738Z"
                            }
                        ],
                        "transitionRules":
                        [
                            {
                                "month": "JANUARY",
                                "timeDefinition": "UTC",
                                "standardOffset":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetBefore":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetAfter":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "dayOfWeek": "MONDAY",
                                "dayOfMonthIndicator": 0,
                                "localTime":
                                {
                                    "hour": 0,
                                    "minute": 0,
                                    "second": 0,
                                    "nano": 0
                                },
                                "midnightEndOfDay": true
                            }
                        ]
                    }
                },
                "chronology":
                {
                    "id": "string",
                    "calendarType": "string"
                }
            },
            "jwt": "string",
            "id": "string",
            "type":
            [
                "string"
            ],
            "subject": "string",
            "expirationDate": "string",
            "credentialSchema":
            {
                "id": "string",
                "type": "string"
            },
            "proof":
            {
                "type": "string",
                "creator": "string",
                "created": "string",
                "domain": "string",
                "proofPurpose": "string",
                "verificationMethod": "string",
                "jws": "string",
                "nonce": "string"
            },
            "challenge": "string",
            "validFrom": "string",
            "issued": "string",
            "issuer": "string"
        }
    ],
    "proof":
    {
        "type": "string",
        "creator": "string",
        "created": "string",
        "domain": "string",
        "proofPurpose": "string",
        "verificationMethod": "string",
        "jws": "string",
        "nonce": "string"
    },
    "issued": "string",
    "validFrom": "string",
    "expirationDate": "string",
    "json": "string",
    "issuanceDate": "string",
    "dateFormat":
    {
        "locale":
        {
            "language": "string",
            "script": "string",
            "variant": "string",
            "displayName": "string",
            "country": "string",
            "unicodeLocaleAttributes":
            [
                "string"
            ],
            "unicodeLocaleKeys":
            [
                "string"
            ],
            "displayLanguage": "string",
            "displayScript": "string",
            "displayCountry": "string",
            "displayVariant": "string",
            "extensionKeys":
            [
                "string"
            ],
            "iso3Language": "string",
            "iso3Country": "string"
        },
        "decimalStyle":
        {
            "zeroDigit": "string",
            "positiveSign": "string",
            "negativeSign": "string",
            "decimalSeparator": "string"
        },
        "resolverStyle": "STRICT",
        "resolverFields":
        [
            {
                "baseUnit":
                {
                    "dateBased": true,
                    "timeBased": true,
                    "duration":
                    {
                        "seconds": 0,
                        "nano": 0,
                        "negative": true,
                        "zero": true,
                        "units":
                        [
                            {
                                "dateBased": true,
                                "timeBased": true,
                                "durationEstimated": true
                            }
                        ]
                    },
                    "durationEstimated": true
                },
                "rangeUnit":
                {
                    "dateBased": true,
                    "timeBased": true,
                    "duration":
                    {
                        "seconds": 0,
                        "nano": 0,
                        "negative": true,
                        "zero": true,
                        "units":
                        [
                            {
                                "dateBased": true,
                                "timeBased": true,
                                "durationEstimated": true
                            }
                        ]
                    },
                    "durationEstimated": true
                },
                "dateBased": true,
                "timeBased": true
            }
        ],
        "zone":
        {
            "id": "string",
            "rules":
            {
                "fixedOffset": true,
                "transitions":
                [
                    {
                        "offsetBefore":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetAfter":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "duration":
                        {
                            "seconds": 0,
                            "nano": 0,
                            "negative": true,
                            "zero": true,
                            "units":
                            [
                                {
                                    "dateBased": true,
                                    "timeBased": true,
                                    "durationEstimated": true
                                }
                            ]
                        },
                        "gap": true,
                        "dateTimeBefore": "2022-10-09T09:52:44.739Z",
                        "dateTimeAfter": "2022-10-09T09:52:44.739Z",
                        "overlap": true,
                        "instant": "2022-10-09T09:52:44.739Z"
                    }
                ],
                "transitionRules":
                [
                    {
                        "month": "JANUARY",
                        "timeDefinition": "UTC",
                        "standardOffset":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetBefore":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetAfter":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "dayOfWeek": "MONDAY",
                        "dayOfMonthIndicator": 0,
                        "localTime":
                        {
                            "hour": 0,
                            "minute": 0,
                            "second": 0,
                            "nano": 0
                        },
                        "midnightEndOfDay": true
                    }
                ]
            }
        },
        "chronology":
        {
            "id": "string",
            "calendarType": "string"
        }
    },
    "jwt": "string",
    "type":
    [
        "string"
    ],
    "subject": "string",
    "credentialSchema":
    {
        "id": "string",
        "type": "string"
    },
    "issuer": "string",
    "challenge": "string"
}

E.g. Create a verifiable presentation from the stored credential having id = urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270 for the holder with did = did:web:my.domain.

curl -X 'POST' \
  'https://custodian.ssikit.walt.id/credentials/presentIds' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "vcIds": [
    "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270"
  ],
  "holderDid": "did:web:my.domain"
}'
{
    "vcIds":
    [
        "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270"
    ],
    "holderDid": "did:web:my.domain"
}
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1"
    ],
    "holder": "did:web:my.domain",
    "id": "urn:uuid:35e627b2-297c-4d33-85cd-a4dfc40bab32",
    "type":
    [
        "VerifiablePresentation"
    ],
    "verifiableCredential":
    [
        {
            "@context":
            [
                "https://www.w3.org/2018/credentials/v1",
                "https://www.w3.org/2018/credentials/examples/v1"
            ],
            "credentialSubject":
            {
                "degree":
                {
                    "name": "Bachelor of Science and Arts",
                    "type": "BachelorDegree"
                },
                "id": "did:web:my.domain"
            },
            "id": "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270",
            "issued": "2022-10-07T09:53:41.369913097Z",
            "issuer":
            {
                "id": "did:web:walt.id"
            },
            "proof":
            {
                "created": "2022-10-07T09:53:41Z",
                "creator": "did:web:walt.id",
                "domain": "https://api.preprod.ebsi.eu",
                "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ",
                "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
                "type": "Ed25519Signature2018"
            },
            "validFrom": "2022-10-07T09:53:41.369917079Z",
            "issuanceDate": "2022-10-07T09:53:41.369917079Z",
            "type":
            [
                "VerifiableCredential",
                "UniversityDegreeCredential"
            ]
        }
    ],
    "proof":
    {
        "type": "Ed25519Signature2018",
        "creator": "did:web:my.domain",
        "created": "2022-10-09T09:52:44Z",
        "domain": "https://api.preprod.ebsi.eu",
        "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
        "proofPurpose": "authentication",
        "verificationMethod": "did:web:my.domain#c5b11445be0e4d37863170df3328630b",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..KCfytKgejnjdW_D632lugaj08E9yO8DcDmNcAoGHywld7twcUf1QqKoidfGNW3j2un4ywqRnjSIiYzK8ZxoXDg"
    }
}

API Serving Configs

To expose the API service using the CLI tool or the docker container, use one of the following commands:

Show all options for specifying bind address and ports:

On localhost only using the default ports 7000-7003

Binding on all network interfaces, using the default ports 7000-7003

Binding on a specific network interface (e.g.: 192.168.0.1)

Using docker one needs to bind to 0.0.0.0 in the container and limit the binding from outside using the docker run -p syntax like so:

Use custom ports by using the -p (Core API), -e (ESSIF API), -s (Signatory API) command options

CLI | Command Line Interface

Manage keys, DIDs, issue Verifiable Credentials, and verify them using the SSI-Kit command line tool.

Installation & Running the Project

Choose between a Docker or a JVM-based runtime.

Response configuration

For debug infos add "-v" e.g.:

Getting Started

Explore the components of the SSI Kit and their functionality:

Dependency (JVM)

The SSI Kit can also be used as direct dependency for JVM-based applications. In this case an existing application can easily be enhanced with SSI functionality.

Dependency

Gradle

Maven

Required Maven repos:

Examples

Decentralised-Identifiers

The following DID management functions are available:

List DIDs

The /v1/did endpoint lists the available DIDs.

E.g. List the available DIDs.

Load DID

The /v1/did/{id} endpoint loads a DID specified by:

  • id - path parameter (required) - the DID url string

E.g. Load the DID = did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z.

Delete DID

The /v1/did/{id} endpoint deletes the DID by:

  • id - path parameter (required) - the DID url string

E.g. Delete the DID = did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z.

Create DID

The /v1/did/create creates a DID.

The method and keyAlias properties are common for all did-method requests, method being required, while keyAlias - optional (if not specified, a new key will be automatically created using the default algorithm according to the did-method). The method-dependent options have default values, if not specified otherwise. Below are the available properties by did-method.

  • didWebDomain (default) - "walt.id"

  • didWebPath (default) - empty-string

  • version (default) - 1

  • network (default) - "testnet"

E.g. Create a DID using the key method and automatically generate a new key.

Resolve DID

The /v1/did/resolve resolves a DID url string to a DID document.

E.g. Resolve the DID = did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa.

Import DID

The /v1/did/import endpoint resolves and imports the specified DID url to the underlying data store.

E.g. Import the DID = did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa.

- lists the available DIDs

- loads a DID by the specified id

- deletes a DID by the specified url

- creates a new DID

- resolves a DID to a document

- import a DID

For more info on DIDs, go .

useJwkJcsPub (default) - false - specifies whether to create a did:key using the jwk_jcs-pub multicodec (code: )

|

|

- credential / presentation verification

- policy related functions

- display the available verification policies

- create a dynamic verification policy

- remove a dynamic verification policy

More details on creating verification policies and fields definitions can be found at .

- lists the available credentials

- lists credential ids

- loads a credential by id

- store a credential

- delete a credential by id

- create a verifiable presentation from specific credentials

- create a verifiable presentation from specific stored credential ids

Make sure you have Docker build environment installed on your machine.

  1. Pulling the project directly from DockerHub

2. Setting and alias for convenience

3. Getting an overview of the commands and options available

Make sure you have a JDK 16+ build environment including Gradle installed on your machine.

  1. Clone the project

2. Change the folder

3. Run the project

The first time you run the command you will be asked to built the project. You can confirm the prompt.

You will now see an overview of all the different commands and options available.

4. Set an alias

To make it more convient to use, you can also set an alias as follows for the wrapper script:

5. Get the overview again

If you want to get a more detailed overview of the options provided for building the project on your machine, please refer to .

The following illustrates how the SSI Kit can be used via Gradle or Maven (look for the current version on GitHub )

You can find the latest version . Make sure when adding the version you add it without the 'v' in front.

- list DIDs

- load DID

- delete by DID url

- create DID

- resolve DID

- import DID

useJwkJcsPub (default) - false - specifies whether to create a did:key using the jwk_jcs-pub multicodec (code: )

here
0xeb51
Swagger
Redoc
Cryptographic keys
Decentralised Identifiers (DIDs)
Verifiable Credentials (VCs)
Swagger
ReDoc
Verification Policies
List
Load
Delete
Create
Resolve
Import
Verification
Policy
list
create
delete
List
List compact
Load
Store
Delete
Present
Present stored
./ssikit.sh serve --help
docker run -itv $(pwd)/data:/app/data -p 192.168.0.1:7000-7003:7000-7003 ssikit serve --help
./ssikit.sh serve
./ssikit.sh serve -b 0.0.0.0

docker run -itv $(pwd)/data:/app/data -p 7000-7003:7000-7003 ssikit serve -b 0.0.0.0
./ssikit.sh serve -b 192.168.0.1
docker run -itv $(pwd)/data:/app/data -p 192.168.0.1:7000-7003:7000-7003 ssikit serve -b 0.0.0.0
./ssikit.sh serve -p 8000 -e 8001 -s 8002

docker run -itv $(pwd)/data:/app/data -p 8000-8002:8000-8002 ssikit serve -b 0.0.0.0 -p 8000 -e 8001 -s 8002
docker pull waltid/ssikit
alias ssikit="docker container run -p 7000-7004:7000-7004 -itv $(pwd)/data:/app/data docker.io/waltid/ssikit"
ssikit -h
git clone https://github.com/walt-id/waltid-ssikit.git
cd waltid-ssikit/
./ssikit.sh -h
alias ssikit="./ssikit.sh"
ssikit -h
ssikit -v

ssikit -v did create
implementation("id.walt:waltid-ssikit:VERSION")
  <dependency>
        <groupId>id.walt</groupId>
        <artifactId>waltid-ssikit</artifactId>
        <version>VERSION</version>
   </dependency>
https://maven.walt.id/repository/waltid/
https://maven.walt.id/repository/waltid-ssi-kit/
curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/did' \
  -H 'accept: application/json'
No parameters
[
    "string"
]
curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/did' \
  -H 'accept: application/json'
[
    "did:ebsi:zwdPobJGue3w86Gpqhq5Cni",
    "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z",
    "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
    "did:web:my.domain",
    "did:web:walt.id",
    "did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q"
]
curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/did/{id}' \
  -H 'accept: application/json'
No parameters
The DID document
curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/did/did%3Akey%3Az6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z' \
  -H 'accept: application/json'
{
    "assertionMethod":
    [
        "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z#z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z"
    ],
    "authentication":
    [
        "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z#z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z"
    ],
    "capabilityDelegation":
    [
        "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z#z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z"
    ],
    "capabilityInvocation":
    [
        "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z#z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z"
    ],
    "@context":
    [
        "https://www.w3.org/ns/did/v1"
    ],
    "id": "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z",
    "keyAgreement":
    [
        "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z#z6LSrs5FudTTsAUhHUoS1kzkhskwAWaYjyU13CVgZT7fwDWk"
    ],
    "verificationMethod":
    [
        {
            "controller": "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z",
            "id": "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z#z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z",
            "publicKeyBase58": "7g7ZKyYMckYQyVVZmBaRMR1j2Fj9m5biSwV7iz3HxeGc",
            "type": "Ed25519VerificationKey2019"
        },
        {
            "controller": "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z",
            "id": "did:key:z6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z#z6LSrs5FudTTsAUhHUoS1kzkhskwAWaYjyU13CVgZT7fwDWk",
            "publicKeyBase58": "GBu6PKebmhkxC6RfV7UoPHYTKN3S3NHrADn14zU9Dqjz",
            "type": "X25519KeyAgreementKey2019"
        }
    ]
}
curl -X 'DELETE' \
  'https://core.ssikit.walt.id/v1/did/{id}' \
  -H 'accept: application/json'
No parameters
Code 200
curl -X 'DELETE' \
  'https://core.ssikit.walt.id/v1/did/did%3Akey%3Az6Mkm8NbvDnnxJ2t5zLGSkYGCWZiqq11Axr58xQ3ZG1Jss3z' \
  -H 'accept: application/json'
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "method": "string",
    "keyAlias": "string",
    "method-dependent-options": "..."
}
The DID url string
{
    "method": "key",
    "keyAlias": "string",
    "useJwkJcsPub": "boolean"
}
{
  "method": "web",
  "keyAlias": "string",
  "didWebDomain": "string",
  "didWebPath": "string"
}
{
    "method": "ebsi",
    "keyAlias": "string",
    "version": "int"
}
{
    "method": "cheqd",
    "keyAlias": "string",
    "network": "string"
}
{
    "method": "iota",
    "keyAlias": "string"
}
{
    "method": "jwk",
    "keyAlias": "string"
}
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "key"
}'
{
    "method": "key"
}
did:key:z6MkqJfAPYYDiDeNERPMufpS1gxgzqiG5fvQnqbYTwY5xJDE
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/did/resolve' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "did": "string"
}
The DID document
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/did/resolve' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "did": "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa"
}'
{
    "did": "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa"
}
{
    "assertionMethod":
    [
        "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa#z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa"
    ],
    "authentication":
    [
        "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa#z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa"
    ],
    "capabilityDelegation":
    [
        "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa#z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa"
    ],
    "capabilityInvocation":
    [
        "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa#z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa"
    ],
    "@context":
    [
        "https://www.w3.org/ns/did/v1"
    ],
    "id": "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa",
    "keyAgreement":
    [
        "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa#z6LSkSwxKk6TFYcqcRHv7ALR87CTFK6bSkQsxwqczx1YgYik"
    ],
    "verificationMethod":
    [
        {
            "controller": "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa",
            "id": "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa#z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa",
            "publicKeyBase58": "CKK9rn4QHwPsXpjzSKGepGytPxcZZqpdGDmZAja4HchC",
            "type": "Ed25519VerificationKey2019"
        },
        {
            "controller": "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa",
            "id": "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa#z6LSkSwxKk6TFYcqcRHv7ALR87CTFK6bSkQsxwqczx1YgYik",
            "publicKeyBase58": "9mmnoSHbA5u6X2v9aWpToWyyQAZUk9Ej5y7wWVN1yAwz",
            "type": "X25519KeyAgreementKey2019"
        }
    ]
}
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/did/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '<request-body>'
The DID url string
Code 201
curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/did/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d 'did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa'
did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa

Java

Examples on how to issue and verify Verifiable Credentials in a Java project.

Kotlin

Examples on how to issue and verify Verifiable Credentials in a Kotlin project.

Docker Build

Downloading the Project

First clone the Git repo and switch into the project folder:

git clone https://github.com/walt-id/waltid-ssikit.git
cd waltid-ssikit/

Docker Container

Building the Docker Container

./ssikit.sh build-docker

or with Podman

./ssikit.sh build-podman

or without script

docker build -t ssikit .

Manually

podman build -t ssikit .

Docker Compose

Run as RESTful service via Docker Compose:

docker-compose build
docker-compose up
building the project
Key Management
Decentralized Identifiers
Verifiable Credentials
OpenID Connect (OIDC)
https://github.com/walt-id/waltid-ssikit
here
0xeb51
list
load
delete by url
create
resolve
import

Basics

EU Blockchain Service Infrastructure (EBSI)

EBSI is a blockchain run by member states and public authorities. The idea is to create a trusted, public ledger that serves as a single source of truth for vital information. As such, EBSI instantiates different Trust Registries, such as

  • Trusted Issuers Registry (TIR), which contains information about organisations (e.g. public keys, accreditations, legal name, ...)

  • Trusted Accreditation Organisation Registry (TAOR), which is similar to the TIR, but contains information about organisations that can authorise Issuers to issue credentials in regulated fields.

  • Trusted Schemas Registry (TSR), which contains information about semantic contexts and vocabularies, policies and templates of VCs and their data models to ensure semantic interoperability.

European Self-Sovereign Identity Framework (ESSIF)

ESSIF's goal is to bring SSI to Europe. To do so, it fullfills different functions:

  • Governance and Trust Framework: ESSIF drives the creation of a EU Governance and Trust Framework supported by Member States.

  • Standards and specifications: ESSIF creates business, functional and technical specifications, which make up the European “flavor of SSI”.

  • Facilitate Adoption: ESSIF coordinates the adoption of SSI across Europe starting with pilot projects of “Early Adopters” which are public authorities from different member states.

Note that ESSIF specifies its own DID Method and different types of Verifiable Credentials (VCs):

  • Verifiable IDs, which are mainly used to identify entities at a high-level of assurance. As such, they can be compared to passports or national IDs.

  • Verifiable Attestions, which encode basically any other type of identity information, such as education or work records, financial data or health data.

  • Verifiable Manadates, which enable delegation as outlined in this paper.

There are also other variations of VC that evolved over time such as Verifiable Accreditations (as issued by TAOS; see above) or Verifiable Authorizations (used to authorize parties to interact with EBSI).

Verifiable-Credentials

The following credentials management functions are available:

List credentials

The /v1/vc endpoint lists the available credentials.

curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/vc' \
  -H 'accept: application/json'
No parameters
The list of credential names (file names)

E.g. List the available credentials.

curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/vc' \
  -H 'accept: application/json'
[
    ""
]

Load credential

The /v1/vc/{id} endpoint loads a credential specified by:

  • id - path parameter (required) - the credential id

curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/vc/{id}' \
  -H 'accept: application/json'
No parameters
The credential string

E.g. Load the credential having id = urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270.

curl -X 'GET' \
  'https://core.ssikit.walt.id/v1/vc/urn%3Auuid%3Ad36986f1-3cc0-4156-b5a4-6d3deab84270' \
  -H 'accept: application/json'
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
    ],
    "credentialSubject":
    {
        "degree":
        {
            "name": "Bachelor of Science and Arts",
            "type": "BachelorDegree"
        },
        "id": "did:web:my.domain"
    },
    "id": "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270",
    "issued": "2022-10-07T09:53:41.369913097Z",
    "issuer":
    {
        "id": "did:web:walt.id"
    },
    "proof":
    {
        "created": "2022-10-07T09:53:41Z",
        "creator": "did:web:walt.id",
        "domain": "https://api.preprod.ebsi.eu",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ",
        "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
        "type": "Ed25519Signature2018"
    },
    "validFrom": "2022-10-07T09:53:41.369917079Z",
    "issuanceDate": "2022-10-07T09:53:41.369917079Z",
    "type":
    [
        "VerifiableCredential",
        "UniversityDegreeCredential"
    ]
}

Delete credential

The /v1/vc/{id} deletes a credential by:

  • id - path parameter (required) - the credential's id

curl -X 'DELETE' \
  'https://core.ssikit.walt.id/v1/vc/{id}' \
  -H 'accept: application/json'
No parameters
Code 200

E.g. Delete the credential with id = urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270.

curl -X 'DELETE' \
  'https://core.ssikit.walt.id/v1/vc/urn%3Auuid%3Ad36986f1-3cc0-4156-b5a4-6d3deab84270' \
  -H 'accept: application/json'

Create credential

The /v1/vc/create endpoint creates a credential.

{
    "issuerDid": "string",
    "subjectDid": "string",
    "credentialOffer": "string",
    "templateId": "string",
    "domain": "string",
    "nonce": "string"
}
The verifiable credential

E.g. Create a credential from the UniveristyDegree template, having issuer = did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa and holder = did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX.

{
    "issuerDid": "did:key:z6MkqmaCT2JqdUtLeKah7tEVfNXtDXtQyj4yxEgV11Y5CqUa",
    "subjectDid": "did:key:z6MkkLmAVeM3P6B2LJ2xGrK1wVojCoephK4G9VrCcct42ADX",
    "templateId": "UniversityDegree"
}
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
    ],
    "credentialSubject":
    {
        "degree":
        {
            "name": "Bachelor of Science and Arts",
            "type": "BachelorDegree"
        },
        "id": "did:web:my.domain"
    },
    "id": "urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270",
    "issued": "2022-10-07T09:53:41.369913097Z",
    "issuer":
    {
        "id": "did:web:walt.id"
    },
    "validFrom": "2022-10-07T09:53:41.369917079Z",
    "issuanceDate": "2022-10-07T09:53:41.369917079Z",
    "type":
    [
        "VerifiableCredential",
        "UniversityDegreeCredential"
    ],
    "proof":
    {
        "type": "Ed25519Signature2018",
        "creator": "did:web:walt.id",
        "created": "2022-10-07T09:53:41Z",
        "domain": "https://api.preprod.ebsi.eu",
        "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ"
    }
}

Present credentials

The /v1/vc/present endpoint creates a verifiable presentation from the supplied credential. Only JSON-LD format is supported.

curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/vc/present' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "vc": "string",
    "holderDid": "string",
    "domain": "string",
    "challenge": "string"
}
{
    "context":
    [
        "string"
    ],
    "id": "string",
    "holder": "string",
    "verifiableCredential":
    [
        {
            "json": "string",
            "issuanceDate": "string",
            "dateFormat":
            {
                "locale":
                {
                    "language": "string",
                    "script": "string",
                    "variant": "string",
                    "displayName": "string",
                    "country": "string",
                    "unicodeLocaleAttributes":
                    [
                        "string"
                    ],
                    "unicodeLocaleKeys":
                    [
                        "string"
                    ],
                    "displayLanguage": "string",
                    "displayScript": "string",
                    "displayCountry": "string",
                    "displayVariant": "string",
                    "extensionKeys":
                    [
                        "string"
                    ],
                    "iso3Language": "string",
                    "iso3Country": "string"
                },
                "decimalStyle":
                {
                    "zeroDigit": "string",
                    "positiveSign": "string",
                    "negativeSign": "string",
                    "decimalSeparator": "string"
                },
                "resolverStyle": "STRICT",
                "resolverFields":
                [
                    {
                        "baseUnit":
                        {
                            "dateBased": true,
                            "timeBased": true,
                            "duration":
                            {
                                "seconds": 0,
                                "nano": 0,
                                "negative": true,
                                "zero": true,
                                "units":
                                [
                                    {
                                        "dateBased": true,
                                        "timeBased": true,
                                        "durationEstimated": true
                                    }
                                ]
                            },
                            "durationEstimated": true
                        },
                        "rangeUnit":
                        {
                            "dateBased": true,
                            "timeBased": true,
                            "duration":
                            {
                                "seconds": 0,
                                "nano": 0,
                                "negative": true,
                                "zero": true,
                                "units":
                                [
                                    {
                                        "dateBased": true,
                                        "timeBased": true,
                                        "durationEstimated": true
                                    }
                                ]
                            },
                            "durationEstimated": true
                        },
                        "dateBased": true,
                        "timeBased": true
                    }
                ],
                "zone":
                {
                    "id": "string",
                    "rules":
                    {
                        "fixedOffset": true,
                        "transitions":
                        [
                            {
                                "offsetBefore":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetAfter":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "duration":
                                {
                                    "seconds": 0,
                                    "nano": 0,
                                    "negative": true,
                                    "zero": true,
                                    "units":
                                    [
                                        {
                                            "dateBased": true,
                                            "timeBased": true,
                                            "durationEstimated": true
                                        }
                                    ]
                                },
                                "gap": true,
                                "dateTimeBefore": "2022-10-09T11:30:48.206Z",
                                "dateTimeAfter": "2022-10-09T11:30:48.206Z",
                                "overlap": true,
                                "instant": "2022-10-09T11:30:48.206Z"
                            }
                        ],
                        "transitionRules":
                        [
                            {
                                "month": "JANUARY",
                                "timeDefinition": "UTC",
                                "standardOffset":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetBefore":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "offsetAfter":
                                {
                                    "totalSeconds": 0,
                                    "id": "string"
                                },
                                "dayOfWeek": "MONDAY",
                                "dayOfMonthIndicator": 0,
                                "localTime":
                                {
                                    "hour": 0,
                                    "minute": 0,
                                    "second": 0,
                                    "nano": 0
                                },
                                "midnightEndOfDay": true
                            }
                        ]
                    }
                },
                "chronology":
                {
                    "id": "string",
                    "calendarType": "string"
                }
            },
            "jwt": "string",
            "id": "string",
            "type":
            [
                "string"
            ],
            "subject": "string",
            "expirationDate": "string",
            "credentialSchema":
            {
                "id": "string",
                "type": "string"
            },
            "proof":
            {
                "type": "string",
                "creator": "string",
                "created": "string",
                "domain": "string",
                "proofPurpose": "string",
                "verificationMethod": "string",
                "jws": "string",
                "nonce": "string"
            },
            "challenge": "string",
            "validFrom": "string",
            "issued": "string",
            "issuer": "string"
        }
    ],
    "proof":
    {
        "type": "string",
        "creator": "string",
        "created": "string",
        "domain": "string",
        "proofPurpose": "string",
        "verificationMethod": "string",
        "jws": "string",
        "nonce": "string"
    },
    "issued": "string",
    "validFrom": "string",
    "expirationDate": "string",
    "json": "string",
    "issuanceDate": "string",
    "dateFormat":
    {
        "locale":
        {
            "language": "string",
            "script": "string",
            "variant": "string",
            "displayName": "string",
            "country": "string",
            "unicodeLocaleAttributes":
            [
                "string"
            ],
            "unicodeLocaleKeys":
            [
                "string"
            ],
            "displayLanguage": "string",
            "displayScript": "string",
            "displayCountry": "string",
            "displayVariant": "string",
            "extensionKeys":
            [
                "string"
            ],
            "iso3Language": "string",
            "iso3Country": "string"
        },
        "decimalStyle":
        {
            "zeroDigit": "string",
            "positiveSign": "string",
            "negativeSign": "string",
            "decimalSeparator": "string"
        },
        "resolverStyle": "STRICT",
        "resolverFields":
        [
            {
                "baseUnit":
                {
                    "dateBased": true,
                    "timeBased": true,
                    "duration":
                    {
                        "seconds": 0,
                        "nano": 0,
                        "negative": true,
                        "zero": true,
                        "units":
                        [
                            {
                                "dateBased": true,
                                "timeBased": true,
                                "durationEstimated": true
                            }
                        ]
                    },
                    "durationEstimated": true
                },
                "rangeUnit":
                {
                    "dateBased": true,
                    "timeBased": true,
                    "duration":
                    {
                        "seconds": 0,
                        "nano": 0,
                        "negative": true,
                        "zero": true,
                        "units":
                        [
                            {
                                "dateBased": true,
                                "timeBased": true,
                                "durationEstimated": true
                            }
                        ]
                    },
                    "durationEstimated": true
                },
                "dateBased": true,
                "timeBased": true
            }
        ],
        "zone":
        {
            "id": "string",
            "rules":
            {
                "fixedOffset": true,
                "transitions":
                [
                    {
                        "offsetBefore":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetAfter":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "duration":
                        {
                            "seconds": 0,
                            "nano": 0,
                            "negative": true,
                            "zero": true,
                            "units":
                            [
                                {
                                    "dateBased": true,
                                    "timeBased": true,
                                    "durationEstimated": true
                                }
                            ]
                        },
                        "gap": true,
                        "dateTimeBefore": "2022-10-09T11:30:48.207Z",
                        "dateTimeAfter": "2022-10-09T11:30:48.207Z",
                        "overlap": true,
                        "instant": "2022-10-09T11:30:48.207Z"
                    }
                ],
                "transitionRules":
                [
                    {
                        "month": "JANUARY",
                        "timeDefinition": "UTC",
                        "standardOffset":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetBefore":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "offsetAfter":
                        {
                            "totalSeconds": 0,
                            "id": "string"
                        },
                        "dayOfWeek": "MONDAY",
                        "dayOfMonthIndicator": 0,
                        "localTime":
                        {
                            "hour": 0,
                            "minute": 0,
                            "second": 0,
                            "nano": 0
                        },
                        "midnightEndOfDay": true
                    }
                ]
            }
        },
        "chronology":
        {
            "id": "string",
            "calendarType": "string"
        }
    },
    "jwt": "string",
    "type":
    [
        "string"
    ],
    "subject": "string",
    "credentialSchema":
    {
        "id": "string",
        "type": "string"
    },
    "issuer": "string",
    "challenge": "string"
}

E.g. Create a verifiable presentation from the provided VeriafiableID credential for a holder with did = did:web:my.domain.

curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/vc/present' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "vc": "{\"@context\":[\"https:\/\/www.w3.org\/2018\/credentials\/v1\"],\"credentialSchema\":{\"id\":\"https:\/\/api.preprod.ebsi.eu\/trusted-schemas-registry\/v1\/schemas\/0xb77f8516a965631b4f197ad54c65a9e2f9936ebfb76bae4906d33744dbcc60ba\",\"type\":\"FullJsonSchemaValidator2021\"},\"credentialSubject\":{\"currentAddress\":[\"1 Boulevard de la Libert\u00E9, 59800 Lille\"],\"dateOfBirth\":\"1993-04-08\",\"familyName\":\"DOE\",\"firstName\":\"Jane\",\"gender\":\"FEMALE\",\"id\":\"did:key:z6MkmRtH7cWeRnQfpeqDfBxa73jhSwUSKfBGUeB6Sk2DgbwR\",\"nameAndFamilyNameAtBirth\":\"Jane DOE\",\"personalIdentifier\":\"0904008084H\",\"placeOfBirth\":\"LILLE, FRANCE\"},\"evidence\":[{\"documentPresence\":[\"Physical\"],\"evidenceDocument\":[\"Passport\"],\"subjectPresence\":\"Physical\",\"type\":[\"DocumentVerification\"],\"verifier\":\"did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN\"}],\"id\":\"urn:uuid:5368e8a9-b1f2-49a6-8ef2-6ba6088baa90\",\"issued\":\"2022-10-11T10:19:31Z\",\"issuer\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"validFrom\":\"2022-10-11T10:19:31Z\",\"issuanceDate\":\"2022-10-11T10:19:31Z\",\"type\":[\"VerifiableCredential\",\"VerifiableAttestation\",\"VerifiableId\"],\"proof\":{\"type\":\"JsonWebSignature2020\",\"creator\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"created\":\"2022-10-11T10:19:32Z\",\"proofPurpose\":\"assertionMethod\",\"verificationMethod\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL#z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"jws\":\"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..Ab-s21gF5B-dAoYmMq9gb5vfYnQOrpECaWuU_vcTMmTofYzOaO0YPKcdAvXoUw--NTUZp9zrK4w3z9HPyHPBDw\"}}",
  "holderDid": "did:web:my.domain"
}'
{
    "vc": "{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],\"credentialSchema\":{\"id\":\"https://api.preprod.ebsi.eu/trusted-schemas-registry/v1/schemas/0xb77f8516a965631b4f197ad54c65a9e2f9936ebfb76bae4906d33744dbcc60ba\",\"type\":\"FullJsonSchemaValidator2021\"},\"credentialSubject\":{\"currentAddress\":[\"1 Boulevard de la Liberté, 59800 Lille\"],\"dateOfBirth\":\"1993-04-08\",\"familyName\":\"DOE\",\"firstName\":\"Jane\",\"gender\":\"FEMALE\",\"id\":\"did:key:z6MkmRtH7cWeRnQfpeqDfBxa73jhSwUSKfBGUeB6Sk2DgbwR\",\"nameAndFamilyNameAtBirth\":\"Jane DOE\",\"personalIdentifier\":\"0904008084H\",\"placeOfBirth\":\"LILLE, FRANCE\"},\"evidence\":[{\"documentPresence\":[\"Physical\"],\"evidenceDocument\":[\"Passport\"],\"subjectPresence\":\"Physical\",\"type\":[\"DocumentVerification\"],\"verifier\":\"did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN\"}],\"id\":\"urn:uuid:5368e8a9-b1f2-49a6-8ef2-6ba6088baa90\",\"issued\":\"2022-10-11T10:19:31Z\",\"issuer\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"validFrom\":\"2022-10-11T10:19:31Z\",\"issuanceDate\":\"2022-10-11T10:19:31Z\",\"type\":[\"VerifiableCredential\",\"VerifiableAttestation\",\"VerifiableId\"],\"proof\":{\"type\":\"JsonWebSignature2020\",\"creator\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"created\":\"2022-10-11T10:19:32Z\",\"proofPurpose\":\"assertionMethod\",\"verificationMethod\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL#z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"jws\":\"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..Ab-s21gF5B-dAoYmMq9gb5vfYnQOrpECaWuU_vcTMmTofYzOaO0YPKcdAvXoUw--NTUZp9zrK4w3z9HPyHPBDw\"}}",
    "holderDid": "did:web:my.domain"
}
{
    "@context":
    [
        "https://www.w3.org/2018/credentials/v1"
    ],
    "holder": "did:web:my.domain",
    "id": "urn:uuid:a6a93543-4fee-4127-8ec0-4c70eac60f2d",
    "type":
    [
        "VerifiablePresentation"
    ],
    "verifiableCredential":
    [
        {
            "@context":
            [
                "https://www.w3.org/2018/credentials/v1"
            ],
            "credentialSchema":
            {
                "id": "https://api.preprod.ebsi.eu/trusted-schemas-registry/v1/schemas/0xb77f8516a965631b4f197ad54c65a9e2f9936ebfb76bae4906d33744dbcc60ba",
                "type": "FullJsonSchemaValidator2021"
            },
            "credentialSubject":
            {
                "currentAddress":
                [
                    "1 Boulevard de la Liberté, 59800 Lille"
                ],
                "dateOfBirth": "1993-04-08",
                "familyName": "DOE",
                "firstName": "Jane",
                "gender": "FEMALE",
                "id": "did:key:z6MkmRtH7cWeRnQfpeqDfBxa73jhSwUSKfBGUeB6Sk2DgbwR",
                "nameAndFamilyNameAtBirth": "Jane DOE",
                "personalIdentifier": "0904008084H",
                "placeOfBirth": "LILLE, FRANCE"
            },
            "evidence":
            [
                {
                    "documentPresence":
                    [
                        "Physical"
                    ],
                    "evidenceDocument":
                    [
                        "Passport"
                    ],
                    "subjectPresence": "Physical",
                    "type":
                    [
                        "DocumentVerification"
                    ],
                    "verifier": "did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN"
                }
            ],
            "id": "urn:uuid:5368e8a9-b1f2-49a6-8ef2-6ba6088baa90",
            "issued": "2022-10-11T10:19:31Z",
            "issuer": "did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL",
            "proof":
            {
                "created": "2022-10-11T10:19:32Z",
                "creator": "did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL",
                "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..Ab-s21gF5B-dAoYmMq9gb5vfYnQOrpECaWuU_vcTMmTofYzOaO0YPKcdAvXoUw--NTUZp9zrK4w3z9HPyHPBDw",
                "proofPurpose": "assertionMethod",
                "type": "JsonWebSignature2020",
                "verificationMethod": "did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL#z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL"
            },
            "validFrom": "2022-10-11T10:19:31Z",
            "issuanceDate": "2022-10-11T10:19:31Z",
            "type":
            [
                "VerifiableCredential",
                "VerifiableAttestation",
                "VerifiableId"
            ]
        }
    ],
    "proof":
    {
        "type": "Ed25519Signature2018",
        "creator": "did:web:my.domain",
        "created": "2022-10-11T10:23:26Z",
        "domain": "https://api.preprod.ebsi.eu",
        "nonce": "dc2be572-cca4-43dc-9903-0fec1dcf786f",
        "proofPurpose": "authentication",
        "verificationMethod": "did:web:my.domain#c5b11445be0e4d37863170df3328630b",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..WqpWOUqaLf8D4aw40aS5R-h-_ZvF6YX1qhVOPULlPUuwP-8WdmfqV5jiwjx_-OL6t55v2ipPGVhY6Sfa47h5DQ"
    }
}

Verify credentials

The /v1/vc/verify endpoint verifies the supplied credential or presentation against the signature policy.

curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/vc/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "vcOrVp": "string"
}
{
    "verificationType": "string",
    "verified": boolean
}

E.g. Verify a presentation.

curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/vc/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "vcOrVp": "{\"@context\":[\"https:\/\/www.w3.org\/2018\/credentials\/v1\"],\"holder\":\"did:web:my.domain\",\"id\":\"urn:uuid:a6a93543-4fee-4127-8ec0-4c70eac60f2d\",\"type\":[\"VerifiablePresentation\"],\"verifiableCredential\":[{\"@context\":[\"https:\/\/www.w3.org\/2018\/credentials\/v1\"],\"credentialSchema\":{\"id\":\"https:\/\/api.preprod.ebsi.eu\/trusted-schemas-registry\/v1\/schemas\/0xb77f8516a965631b4f197ad54c65a9e2f9936ebfb76bae4906d33744dbcc60ba\",\"type\":\"FullJsonSchemaValidator2021\"},\"credentialSubject\":{\"currentAddress\":[\"1 Boulevard de la Libert\u00E9, 59800 Lille\"],\"dateOfBirth\":\"1993-04-08\",\"familyName\":\"DOE\",\"firstName\":\"Jane\",\"gender\":\"FEMALE\",\"id\":\"did:key:z6MkmRtH7cWeRnQfpeqDfBxa73jhSwUSKfBGUeB6Sk2DgbwR\",\"nameAndFamilyNameAtBirth\":\"Jane DOE\",\"personalIdentifier\":\"0904008084H\",\"placeOfBirth\":\"LILLE, FRANCE\"},\"evidence\":[{\"documentPresence\":[\"Physical\"],\"evidenceDocument\":[\"Passport\"],\"subjectPresence\":\"Physical\",\"type\":[\"DocumentVerification\"],\"verifier\":\"did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN\"}],\"id\":\"urn:uuid:5368e8a9-b1f2-49a6-8ef2-6ba6088baa90\",\"issued\":\"2022-10-11T10:19:31Z\",\"issuer\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"proof\":{\"created\":\"2022-10-11T10:19:32Z\",\"creator\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"jws\":\"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..Ab-s21gF5B-dAoYmMq9gb5vfYnQOrpECaWuU_vcTMmTofYzOaO0YPKcdAvXoUw--NTUZp9zrK4w3z9HPyHPBDw\",\"proofPurpose\":\"assertionMethod\",\"type\":\"JsonWebSignature2020\",\"verificationMethod\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL#z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\"},\"validFrom\":\"2022-10-11T10:19:31Z\",\"issuanceDate\":\"2022-10-11T10:19:31Z\",\"type\":[\"VerifiableCredential\",\"VerifiableAttestation\",\"VerifiableId\"]}],\"proof\":{\"type\":\"Ed25519Signature2018\",\"creator\":\"did:web:my.domain\",\"created\":\"2022-10-11T10:23:26Z\",\"domain\":\"https:\/\/api.preprod.ebsi.eu\",\"nonce\":\"dc2be572-cca4-43dc-9903-0fec1dcf786f\",\"proofPurpose\":\"authentication\",\"verificationMethod\":\"did:web:my.domain#c5b11445be0e4d37863170df3328630b\",\"jws\":\"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..WqpWOUqaLf8D4aw40aS5R-h-_ZvF6YX1qhVOPULlPUuwP-8WdmfqV5jiwjx_-OL6t55v2ipPGVhY6Sfa47h5DQ\"}}"
}'
{
    "vcOrVp": "{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],\"holder\":\"did:web:my.domain\",\"id\":\"urn:uuid:a6a93543-4fee-4127-8ec0-4c70eac60f2d\",\"type\":[\"VerifiablePresentation\"],\"verifiableCredential\":[{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],\"credentialSchema\":{\"id\":\"https://api.preprod.ebsi.eu/trusted-schemas-registry/v1/schemas/0xb77f8516a965631b4f197ad54c65a9e2f9936ebfb76bae4906d33744dbcc60ba\",\"type\":\"FullJsonSchemaValidator2021\"},\"credentialSubject\":{\"currentAddress\":[\"1 Boulevard de la Liberté, 59800 Lille\"],\"dateOfBirth\":\"1993-04-08\",\"familyName\":\"DOE\",\"firstName\":\"Jane\",\"gender\":\"FEMALE\",\"id\":\"did:key:z6MkmRtH7cWeRnQfpeqDfBxa73jhSwUSKfBGUeB6Sk2DgbwR\",\"nameAndFamilyNameAtBirth\":\"Jane DOE\",\"personalIdentifier\":\"0904008084H\",\"placeOfBirth\":\"LILLE, FRANCE\"},\"evidence\":[{\"documentPresence\":[\"Physical\"],\"evidenceDocument\":[\"Passport\"],\"subjectPresence\":\"Physical\",\"type\":[\"DocumentVerification\"],\"verifier\":\"did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN\"}],\"id\":\"urn:uuid:5368e8a9-b1f2-49a6-8ef2-6ba6088baa90\",\"issued\":\"2022-10-11T10:19:31Z\",\"issuer\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"proof\":{\"created\":\"2022-10-11T10:19:32Z\",\"creator\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\",\"jws\":\"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..Ab-s21gF5B-dAoYmMq9gb5vfYnQOrpECaWuU_vcTMmTofYzOaO0YPKcdAvXoUw--NTUZp9zrK4w3z9HPyHPBDw\",\"proofPurpose\":\"assertionMethod\",\"type\":\"JsonWebSignature2020\",\"verificationMethod\":\"did:key:z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL#z6Mkeu6eroi9VuHsqxtkWHxKS4egHtVH4snzRtuFFtUYwavL\"},\"validFrom\":\"2022-10-11T10:19:31Z\",\"issuanceDate\":\"2022-10-11T10:19:31Z\",\"type\":[\"VerifiableCredential\",\"VerifiableAttestation\",\"VerifiableId\"]}],\"proof\":{\"type\":\"Ed25519Signature2018\",\"creator\":\"did:web:my.domain\",\"created\":\"2022-10-11T10:23:26Z\",\"domain\":\"https://api.preprod.ebsi.eu\",\"nonce\":\"dc2be572-cca4-43dc-9903-0fec1dcf786f\",\"proofPurpose\":\"authentication\",\"verificationMethod\":\"did:web:my.domain#c5b11445be0e4d37863170df3328630b\",\"jws\":\"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..WqpWOUqaLf8D4aw40aS5R-h-_ZvF6YX1qhVOPULlPUuwP-8WdmfqV5jiwjx_-OL6t55v2ipPGVhY6Sfa47h5DQ\"}}"
}
{
    "verificationType": "VERIFIABLE_PRESENTATION",
    "verified": true
}

Import credential

The /v1/vc/import endpoint imports a verifiable credential.

curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/vc/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '<request-body>'
The credential string
Code 200

E.g. Import the UniversityDegree credential.

curl -X 'POST' \
  'https://core.ssikit.walt.id/v1/vc/import' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '"{\"@context\":[\"https:\/\/www.w3.org\/2018\/credentials\/v1\",\"https:\/\/www.w3.org\/2018\/credentials\/examples\/v1\"],\"credentialSubject\":{\"degree\":{\"name\":\"Bachelor of Science and Arts\",\"type\":\"BachelorDegree\"},\"id\":\"did:web:my.domain\"},\"id\":\"urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270\",\"issued\":\"2022-10-07T09:53:41.369913097Z\",\"issuer\":{\"id\":\"did:web:walt.id\"},\"validFrom\":\"2022-10-07T09:53:41.369917079Z\",\"issuanceDate\":\"2022-10-07T09:53:41.369917079Z\",\"type\":[\"VerifiableCredential\",\"UniversityDegreeCredential\"],\"proof\":{\"type\":\"Ed25519Signature2018\",\"creator\":\"did:web:walt.id\",\"created\":\"2022-10-07T09:53:41Z\",\"domain\":\"https:\/\/api.preprod.ebsi.eu\",\"nonce\":\"dc2be572-cca4-43dc-9903-0fec1dcf786f\",\"jws\":\"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ\"}}"'
"{\"@context\":[\"https:\/\/www.w3.org\/2018\/credentials\/v1\",\"https:\/\/www.w3.org\/2018\/credentials\/examples\/v1\"],\"credentialSubject\":{\"degree\":{\"name\":\"Bachelor of Science and Arts\",\"type\":\"BachelorDegree\"},\"id\":\"did:web:my.domain\"},\"id\":\"urn:uuid:d36986f1-3cc0-4156-b5a4-6d3deab84270\",\"issued\":\"2022-10-07T09:53:41.369913097Z\",\"issuer\":{\"id\":\"did:web:walt.id\"},\"validFrom\":\"2022-10-07T09:53:41.369917079Z\",\"issuanceDate\":\"2022-10-07T09:53:41.369917079Z\",\"type\":[\"VerifiableCredential\",\"UniversityDegreeCredential\"],\"proof\":{\"type\":\"Ed25519Signature2018\",\"creator\":\"did:web:walt.id\",\"created\":\"2022-10-07T09:53:41Z\",\"domain\":\"https:\/\/api.preprod.ebsi.eu\",\"nonce\":\"dc2be572-cca4-43dc-9903-0fec1dcf786f\",\"jws\":\"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..7EYkgjNRJ_hh0F5kONnPfrC4PLvg1g82czeANllDngsbk36a8lnHSlwersSqY0tdER4xIe7vbNVzi39C2DZTDQ\"}}"

Key Management

Key management functions like generation, listing, export/import, and deletion.

SSI-Kit CLI key management commands can be accessed with the key command. It provides the following functionality:

All commands have the help option available:

  • <your-command> -h

  • or <your-command> --help

E.g. key gen -h

Generate key

Use the gen command to create asymmetric key pair by the specified algorithm. Supported algorithms are:

  • RSA:

    • key gen -a RSA

    • or key gen --algorithm RSA

  • ECDSA Secp256k1:

    • key gen -a Secp256k1

    • or key gen --algorithm Secp256k1

  • EdDSA Ed25519 (default)

    • key gen

    • or key gen -a Ed25519

    • or key gen --algorithm Ed25519

The returned value represents the keyId of the newly created key.

E.g. key gen -a Secp256k1

List keys

Use the list command to list all keys in the key store:

  • key list

It will output the following fields:

  • key index - index within the list

  • keyId - key identification number

  • key algorithm - algorithm used to create the key

  • crypto service - the cryptographic service used to create the key

Import key

Use the import command to import a key in JWK or PEM format:

  • key import <your-key-file-path>

    • JWK - based on the JWK key ID and key material, an internal key object will be created and placed in the corresponding key store

    • PEM - if there's no key ID in the PEM file (which is usually the case), a random key ID will be generated and, based on the key material, an internal key object will be created and placed in the corresponding key store. PEM files must have the file extension 'pem':

      • RSA keys - file should contain either the private key or private and public keys concatenated with a 'new line' character

      • Ed25519, Secp256k1 - file should contain both private and public keys concatenated with a 'new line' character

E.g.

Ed25519 JWK public key

key import ./ed25519jwk.json

Secp256k1 PEM key

key import ./secp256k1.pem

Export key

Use the export command to export a specified key type with the specified id and format.

Available key type:

  • public (default):

    • key export <your-key-id>

    • or key export <your-key-id> --pub

  • private:

    • key export <your-key-id> --priv

Available export formats:

  • JWK (default):

    • key export <your-key-id>

    • or key export <your-key-id> -f JWK

    • or key export <your-key-id> --key-format JWK

  • PEM:

    • key export <your-key-id> -f PEM

    • key export <your-key-id> --key-format PEM

The output will display the exported key in the specified format.

E.g.

key export 17592087c6f04c358b9b813dbe2ef027 --pub -f PEM

key export 17592087c6f04c358b9b813dbe2ef027 --pub

key export 17592087c6f04c358b9b813dbe2ef027 --priv -f PEM

key export 17592087c6f04c358b9b813dbe2ef027 --priv

Delete key

Use the delete command to delete a key with the specified ID:

  • key delete <your-key-id>

E.g. key delete 17592087c6f04c358b9b813dbe2ef027

Building the Project

For building the project Gradle 7 as well as JDK 16 (or above) is required.

Building the project:

OpenID Connect (OIDC)

OIDC for verifiable presentation and credential issuance

OIDC commands, related to credential presentation and credential issuance through OIDC SIOPv2 specifications

Commands:

  • ci OIDC for Credential Issuance

  • vp OIDC for Verifiable Presentations

Examples

Decentralized Identifiers

Commands:

All commands have the help option available:

  • <your-command> -h

  • <your-command> --help

E.g. did create -h

Create DID

Creates a DID document using did create [options] command based on the corresponding SSI ecosystem (DID method). Optionally the associated asymmetric key is also created.

Options

  • -m, --did-method [key | web | ebsi | iota | jwk | cheqd] - Specify DID method [key], Supported DID methods are: "key", "web", "ebsi", "iota", "jwk"

  • -k, --key TEXT - Specific key (ID or alias)

  • -d, --domain TEXT - Domain for did:web

  • -p, --path TEXT - Path for did:web

  • -v, --version INT - Version of did:ebsi. Allowed values: 1 (default), 2

  • -n, --network [testnet | mainnet] - cheqd network, default is testnet

The returned value represents the DID document.

E.g. did create -m ebsi -k 8a2c3628acdd45999b4c0b5a69911437

IOTA support

For creating IOTA DIDs and registering them on the IOTA tangle, a wrapper library needs to be installed and available in the local library path.

The wrapper library is included in the SSIKit Docker image, such that for Docker users no additional setup is required.

CLI users can find instructions for build and SSIKit integration at:

Resolve DID

Resolves the DID document.

Options:

-d, --did TEXT DID to be resolved

-r, --raw / -t, --typed

-w, --write

List DIDs

List all created DIDs using did list command

Import DID

Import DID to custodian store using did import [options] command

Options

  • -k, --key-id TEXT - Specify key ID for imported did, if left empty, only public key will be imported

  • -f, --file TEXT - Load the DID document from the given file

  • -d, --did TEXT - Try to resolve DID document for the given DID

Delete DID

Use the delete command to delete a DID:

  • did delete <your did>

E.g. did delete -d "did:ebsi:zs79GYJvzEnQYxkAAj4UX1j"

Verifiable Credentials

VC related operations like issuing, verifying and revoking VCs.

Commands:

All commands have the help option available:

  • <your-command> -h

  • or <your-command> --help

E.g. vc issue -h

Issue and save VC

Use the issue command to issue a W3C Verifiable Credential with either a JWT or a JSON_LD signature.

options:

  • -i, --issuer-did TEXT DID of the issuer (associated with signing key). [Required]

  • -s, --subject-did TEXT DID of the VC subject (receiver of VC). [Required]

  • -v, --issuer-verification-method TEXT KeyId of the issuers' signing key

  • -y, --proof-type [JWT|LD_PROOF] Proof type to be used [LD_PROOF]

  • -p, --proof-purpose TEXT Proof purpose to be used [assertion]

  • --interactive Interactively prompt for VC data to fill in

  • --ld-signature, --ld-sig \[Ed25519Signature2018|Ed25519Signature2020|EcdsaSecp256k1Signature2019|RsaSignature2018|JsonWebSignature2020|JcsEd25519Signature2020]

  • --ecosystem \[DEFAULT|ESSIF|GAIAX|IOTA] Specify ecosystem, for specific defaults of issuing parameters

  • --statusType \[StatusList2021Entry|SimpleCredentialStatus2022] specify the credentialStatus type

e.g.

  • vc issue -t OpenBadgeCredential -s did:key:z6MkpuUYdpaZPcpnEWnkE8vb7s2u2geTZJden1BwGXsdFUz3 -i did:ebsi:zZ5apnsHPUXNqjWELjNZhYW, returns a credential document (JSON format)

Present VC

Use present command to present a VC or VP to a verifier.

-i, --holder-did TEXT DID of the holder (owner of the VC)

-v, --verifier-did TEXT DID of the verifier (recipient of the VP)

-d, --domain TEXT Domain name to be used in the LD proof

-c, --challenge TEXT Challenge to be used in the LD proof

Verify VC or VP

use verify command to verify

-p, --policy VALUE Verification policy. Can be specified multiple times. By default, SignaturePolicy is used. For more details on how to specify the policies, refer to Verification Policies.

List verification policies

To see available verification policies, use vc policies command

Import VC to custodian store

Import VC to custodian store

VC templates

Learn about VC template related functions like the listing and exporting of templates, as well as how to create/import your own custom VC template.

List VC templates in custodian store

  • list List VC Templates.

vc template list result

Export VC template from custodian store

  • export <template-name> Export VC Template.

Options:

  • -n, --name <Name> Name of the template

e.g. vc templates export --name VerifiableId

Import VC template to custodian store

  • import <customCredentialPath.json>

Options:

  • -n, --name <Name> Name of the template

Arguments:

  • credential path the last argument of the command references the path to the custom credential, which should be imported

e.g vc templates import -n MyCustomCredential custom.json

custom.json

{
  "type": [
    "VerifiableCredential",
    "MyCustomCredential" // name of the credential
  ],
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "id": "http://example.gov/credentials/3732",
  "issuer": {
    "id": "did:example:456"
  },
  "issued": "2020-03-10T04:24:12.164Z",
  "credentialSubject": { //custom credential subject
    "id": "",
    "firstName": "",
    "lastName": "",
    "country": "Austria"
  }
}

Output of the command

List VCs

  • list VCs saved in the custodian store

e.g. vc list

Project Configurations

Services come with their own configuration files.

The default mapping file is "service-matrix.properties", and looks like this:

e.g., to change the keystore service, simply replace the line

id.walt.services.keystore.KeyStoreService=id.walt.services.keystore.SqlKeyStoreService

with your own implementation mapping, e.g. for the Azure HSM keystore:

id.walt.services.keystore.KeyStoreService=id.walt.services.keystore.azurehsm.AzureHSMKeystoreService

To add a service configuration:

id.walt.services.keystore.KeyStoreService=id.walt.services.keystore.SqlKeyStoreService:sql.conf Service configuration is by default in HOCON format. Refer to the specific service on how their configuration is laid out.

Demo

The demo shows an end-to-end SSI use case from the perspective of an individual (Holder).

Issuer Portal: Shows issuance of Verifiable Credentials (VCs) to a Holder’s wallet.

  1. Click on "Sign in". You do not need to input an email or a password.

  2. Select and "confirm" your Verifiable Credential (VC) claim.

Wallet: Shows the receipt and management of VCs by a Holder.

  1. Accept the connection request (from the Issuer Portal), by clicking on "share".

  2. Review and accept the Verifiable Credential (VC).

Verifier Portal: Shows the presentation of VCs by Holder in order to authenticate or identify towards a Relying Party (Verifier).

  1. Connect the wallet to share VCs.

  2. Log into the wallet (you used before)

  3. Accept the credential request by the Verifier.

  4. Get access to the Verifier’s products, services or other benefits..

Local Build

For building the project JDK 16+ is required.

Downloading the Project

First clone the Git repo and switch into the project folder:

Wrapper

The walt.id wrapper script ssikit.sh is a convenient way for building and using the library on Linux.

The script takes one of the the following arguments:

build|build-docker|build-podman|extract|execute.

For example, for building the project, simply supply the "build" argument:

Gradle

Manually with Gradle:

After the Gradle build you can run the executable.

In build/distributions/ you have two archives, a .tar, and a .zip.

Extract either one of them, and run waltid-ssi-kit-1.0-SNAPSHOT/bin/waltid-ssi-kit.

Use Cases & Flow Diagrams

Note, that EBSI/ESSIF specifications are evolving, which means that some flows are not available in their final version. Modifications are to be expected.

ESSIF DID Registration

Creation and anchoring of a new DID on the EBSI ledger (incl. use of "Verifiable Authorizations" and EBSI access tokens).

ESSIF Onboarding

Onboarding of a legal entity to the EBSI/ESSIF ecosystem (incl. combined VC request and DID registration).

EBSI Auth API

Gaining access to protected EBSI/ESSIF services (incl. presentation of "Verifiable Authorization").

Issuance of Verifiable Credentials

The ESSIF protocol for issuance of verifiable credentials aims to being compliant with the OIDC for credential issuance specification. Refer to the respective section for details:

Exchange of Verifiable Presentations

The ESSIF protocol for presentation of verifiable credentials to a Verifier or Relying Party, aims to being compliant with the OIDC/SIOPv2 specification. Refer to this section for details:

Code examples

- list verifiable credentials

- load the verifiable credential

- delete the verifiable credential

- create a verifiable credential

- create a verifiable presentation from the supplied credentials

- verify credential / presentation

- import the verifiable credential

- using gen command

- using list command

- using import command

- using export command

- using delete command

DID related operations, like registering, updating and deactivating DIDs. For more info on DIDs, go .

- using create command.

- using resolve command.

- using list command.

to custodian store - using import command.

from custodian - using delete command.

-j, --useJwkJcsPub - specifies whether to create a did:key using the jwk_jcs-pub multicodec (code: )

VC related operations like issuing, verifying and revoking VCs. If you're new to VCs, check out the for an overview.

- using issue command

- using present command

- using verify command

- using policies command

- using import command

- using templates command

- using list command

-t, --template TEXT specify the VC template. To create your own template, have a look [Required]

For the configuration of service -> implementation mappings, is used.

Visit our .

Log into the (after being redirected from the Issuer Portal). The demo does not require the account-creation nor a valid passord. Just type a email address to log in you demo account.

Our hosted demo verifier is currently not working with our wallet. We are working on fixing the issue. Please in case of any questions.

Visit the .

For SSIKit usage examples, refer to:

Several code-examples how to use the ESSIF functionality of the SSI Kit are shown on

Docker
Local

OIDC For Credential Issuance

OIDC for Verifiable Presentations

here
0xeb51
https://github.com/walt-id/waltid-iota-identity-wrapper
intro section
list
load
delete
create
present
verify
import
Generate key
List keys
Import key
Export key
Delete key
Create DID
Resolve DID
List DIDs
Import DID
Delete DID
Issues and save VC
Present VC
Verify VC or VP
List verification policies
Import VC to custodian store
VC templates
List VCs
here
id.walt.services.vc.VCService=id.walt.services.vc.LetstrustVCService
id.walt.services.crypto.CryptoService=id.walt.services.crypto.SunCryptoService
id.walt.services.keystore.KeyStoreService=id.walt.services.keystore.SqlKeyStoreService
id.walt.services.key.KeyService=id.walt.services.key.WaltIdKeyService
git clone https://github.com/walt-id/waltid-ssikit.git
cd waltid-ssikit/
./ssikit.sh {build|build-docker|build-podman|extract|execute (default)}
./ssikit.sh build
gradle clean build
cd build/distributions
tar xf waltid-ssi-kit-1.0-SNAPSHOT.tar    # or unzip for the .zip
cd ../..  # go back to the root-directory

./build/distributions/waltid-ssi-kit-1.0-SNAPSHOT/bin/waltid-ssi-kit

Command line interface

ESSIF specific operations.

Commands:

  • onboard ESSIF Onboarding flow

  • auth-api ESSIF EBSI Authentication flow

  • did ESSIF DID operations.

  • tir ESSIF Trusted Issuer Registry operations.

  • timestamp EBSI Timestamp API operations.

  • taor ESSIF Trusted Accreditation Organization operations.

  • tsr ESSIF Trusted Schema Registry operations

ServiceMatrix
Issuer Portal
Web Wallet
reach out
Verifier Portal
EBSI DID registration
OIDC for credential issuance
OIDC/SIOPv2 for verifiable presentations
GitHub

Usage / examples

The following subsections show examples of interactions with the EBSI/ESSIF frameworks using the SSI Kit command line interface, REST APIs and library SDK.

Onboarding & DIDs

This use case describes the steps, which are required to register a DID on the EBSI blockchain.

CLI

Key generation (type ECDSA Secp256k1, which is required for signing ETH transactions)

./ssikit.sh key gen -a Secp256k1
=> keyId: 7db4b285984640d485842c0b1ccdcf92

Generation of the DID document

./ssikit.sh did create -m ebsi -k 7db4b285984640d485842c0b1ccdcf92
=> DID: did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg

EBSI/ESSIF Onboarding flow.

./ssikit.sh essif onboard --did did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg

After successfully completing the onboarding process, the Verifiable Authorization (validity of 6 months) from the Ebsi Onboarding Service is placed in data/ebsi/verifiable-authorization.json

EBSI/ESSIF Auth API flow

./ssikit.sh essif auth-api --did did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg

After successfully completing the Auth API flow, the decrypted EBSI Access Token (validity of 15min) can be accessed in file: /home/pp/dev/walt/data/ebsi/ebsi_access_token.json

EBSI/ESSIF DID registration

./ssikit.sh essif did register --did did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg

DID Resolution (only to check if the DID was correctly anchored with the EBSI blockchain)

./ssikit.sh did resolve --did did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg

The resulting DID document from the EBSI blockchain:

{
  "authentication": [
    "did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg#7db4b285984640d485842c0b1ccdcf92"
  ],
  "@context": [
    "https://w3id.org/did/v1"
  ],
  "id": "did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg",
  "verificationMethod": [
    {
      "controller": "did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg",
      "id": "did:ebsi:241ou8rtrYnBokFALv3PGFeTRYQuLdyZnpFk3wFFhhiDKdLg#7db4b285984640d485842c0b1ccdcf92",
      "publicKeyJwk": {
        "alg": "ES256K",
        "crv": "secp256k1",
        "kid": "7db4b285984640d485842c0b1ccdcf92",
        "kty": "EC",
        "use": "sig",
        "x": "wpFN5Pi6v3MiM6B5Awd4lqZk1usQQDDUAvVNXqXp4uw",
        "y": "iHVFCdaeIYbZheeQOtBCUpWCtoQhfPCx5N5MQuhbEFo"
      },
      "type": "Secp256k1VerificationKey2018"
    }
  ]
}

REST API

First pull the latest container

docker pull waltid/ssikit

Starting the container as RESTful service

docker run -itv $(pwd)/data:/app/data -p 7000-7004:7000-7004 waltid/ssikit -v serve -b 0.0.0.0

Key generation (type ECDSA Secp256k1, which is required for signing ETH transactions)

curl -X POST "http://127.0.0.1:7000/v1/key/gen" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"keyAlgorithm\":\"ECDSA_Secp256k1\"}"

Generation of the DID document

curl -X POST "http://127.0.0.1:7000/v1/did/create" -H  "accept: text/plain" -H  "Content-Type: application/json" -d "{\"method\":\"ebsi\",\"keyAlias\":\"751da5b181e64475a811a374ae1a6923\"}"
=>  did:ebsi:22tCpv2yh4EJLm6o18JiS2AebaQAL6QcHH83mS6Cz94QumtY

EBSI/ESSIF Onboarding flow

curl -X POST "http://127.0.0.1:7004/v1/client/onboard" -H  "accept: text/plain" -H  "Content-Type: application/json" -d "{\"bearerToken\":\"eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2MzEwODYxODUsImlhdCI6MTYzMTA4NTI4NSwiaXNzIjoiZGlkOmVic2k6NGpQeGNpZ3ZmaWZaeVZ3eW01emp4YUtYR0pUdDdZd0Z0cGc2QVh0c1I0ZDUiLCJvbmJvYXJkaW5nIjoicmVjYXB0Y2hhIiwidmFsaWRhdGVkSW5mbyI6eyJhY3Rpb24iOiJsb2dpbiIsImNoYWxsZW5nZV90cyI6IjIwMjEtMDktMDhUMDc6MTQ6NDRaIiwiaG9zdG5hbWUiOiJhcHAucHJlcHJvZC5lYnNpLmV1Iiwic2NvcmUiOjAuOSwic3VjY2VzcyI6dHJ1ZX19.InIzqVIAON07zuFkt6afLv3q6IO9XuqcmiH8CnVo6lMfFQMBv1Uz91-gkn__0RuYzzTgzPWBCmUn8E3tw_xE5Q\",\"did\":\"did:ebsi:22tCpv2yh4EJLm6o18JiS2AebaQAL6QcHH83mS6Cz94QumtY\"}"

EBSI/ESSIF Auth flow

curl -X POST "http://127.0.0.1:7004/v1/client/auth" -H  "accept: text/plain" -H  "Content-Type: text/plain" -d "did:ebsi:22tCpv2yh4EJLm6o18JiS2AebaQAL6QcHH83mS6Cz94QumtY"

EBSI/ESSIF DID registration

curl -X POST "http://127.0.0.1:7004/v1/client/registerDid" -H  "accept: text/plain" -H  "Content-Type: text/plain" -d "did:ebsi:22tCpv2yh4EJLm6o18JiS2AebaQAL6QcHH83mS6Cz94QumtY"

DID Resolution (only to check if the DID was correctly anchored with the EBSI blockchain)

curl -X POST "http://127.0.0.1:7000/v1/did/resolve" -H  "accept: text/plain" -H  "Content-Type: application/json" -d "{\"did\":\"did:ebsi:22tCpv2yh4EJLm6o18JiS2AebaQAL6QcHH83mS6Cz94QumtY\"}"

Code example

    KeyService keyService = KeyService.Companion.getService();
    DidEbsiService didEbsiService = DidEbsiService.Companion.getService();

    var keyId = keyService.generate(KeyAlgorithm.ECDSA_Secp256k1);
 
    var didEbsi = DidService.INSTANCE.create(DidMethod.ebsi, keyId.getId());

    EssifClient.INSTANCE.onboard(didEbsi, null);

    EssifClient.INSTANCE.authApi(didEbsi);

    didEbsiService.registerDid(didEbsi, ethKeyId.getId());

Build end-to-end use cases

This is a holistic SSI use case, which demonstrates the setup of two identities for an Issuer and a Holder on the EBSI blockchain. It also shows the steps to issue two diploma credentials to the Holder (e.g student), which then creates a Verifiable Presentation including both credentials in order to be verified. The Verifier then resolves the DIDs from the EBSI ledger and uses the corresponding public keys to verify the signatures from the issued credentials.

CLI

Creating a work-dir for all three parties of the trust triangle (Issuer, Holder & Verifier)

mkdir issuer
mkdir holder
mkdir verifier

Setting up the Issuer (generating a key, EBSI DID and registering it on the EBSI ledger)

cd issuer/
docker run -itv $(pwd)/data:/app/data waltid/ssikit key gen -a Secp256k1
docker run -itv $(pwd)/data:/app/data waltid/ssikit did create -m ebsi -k 48ff0d51910c4dc4b05b420547a05f9f
cat > data/bearer-token.txt    
docker run -itv $(pwd)/data:/app/data waltid/ssikit essif onboard --did did:ebsi:22NPNHrBUWCKDJWuvpJD5s2V7JZNQRQvajMHP9hiky57nfhC data/bearer-token.txt
docker run -itv $(pwd)/data:/app/data waltid/ssikit essif auth-api --did did:ebsi:22NPNHrBUWCKDJWuvpJD5s2V7JZNQRQvajMHP9hiky57nfhC
docker run -itv $(pwd)/data:/app/data waltid/ssikit essif did register --did did:ebsi:22NPNHrBUWCKDJWuvpJD5s2V7JZNQRQvajMHP9hiky57nfhC 

Setting up the Holder (generating a key, EBSI DID and registering it on the EBSI ledger)

cd ../holder/
docker run -itv $(pwd)/data:/app/data waltid/ssikit key gen -a Secp256k1
docker run -itv $(pwd)/data:/app/data waltid/ssikit did create -m ebsi -k 2c497f88593b4db9a571fb7146606fc2
cat > data/bearer-token.txt   
docker run -itv $(pwd)/data:/app/data waltid/ssikit essif onboard --did did:ebsi:2YiP8ae91JPNQ86YQWvPytdBP8rfKZYR8r95CE8aZ1ooUatr data/bearer-token.txt
docker run -itv $(pwd)/data:/app/data waltid/ssikit essif auth-api --did did:ebsi:2YiP8ae91JPNQ86YQWvPytdBP8rfKZYR8r95CE8aZ1ooUatr
docker run -itv $(pwd)/data:/app/data waltid/ssikit essif did register --did did:ebsi:2YiP8ae91JPNQ86YQWvPytdBP8rfKZYR8r95CE8aZ1ooUatr

Setting up the Verifier (only run ssikit in order to initialize the work-dir)

cd ../verifier/
docker run -itv $(pwd)/data:/app/data waltid/ssikit -h
cd ../issuer/
docker run -itv $(pwd)/data:/app/data waltid/ssikit vc issue -i did:ebsi:22NPNHrBUWCKDJWuvpJD5s2V7JZNQRQvajMHP9hiky57nfhC -s did:ebsi:2YiP8ae91JPNQ86YQWvPytdBP8rfKZYR8r95CE8aZ1ooUatr -t VerifiableDiploma --interactive data/bachelor.json
docker run -itv $(pwd)/data:/app/data waltid/ssikit vc issue -i did:ebsi:22NPNHrBUWCKDJWuvpJD5s2V7JZNQRQvajMHP9hiky57nfhC -s did:ebsi:2YiP8ae91JPNQ86YQWvPytdBP8rfKZYR8r95CE8aZ1ooUatr -t VerifiableDiploma --interactive data/master.json
cp data/master.json data/bachelor.json ../holder/data

Creating the Verifiable Presentation containing both - the Master and the Bachelor credential

cd ../holder/
docker run -itv $(pwd)/data:/app/data waltid/ssikit vc present --holder-did did:ebsi:2YiP8ae91JPNQ86YQWvPytdBP8rfKZYR8r95CE8aZ1ooUatr data/master.json data/bachelor.json
cp data/vc/presented/vp-1632686198721.json ../verifier/data

Verifying the Verifiable Presentation by resolving DIDs (public keys) from the EBSI ledger and verifying the signatures from each VC (Bachelor & Master degree credential) and from the VP itself.

docker run -itv $(pwd)/data:/app/data waltid/ssikit vc verify -p TrustedIssuerDidPolicy -p TrustedSubjectDidPolicy -p JsonSchemaPolicy -p SignaturePolicy data/vp-1632686198721.json

Output:    
Walt.ID SSI-Kit 1.0-SNAPSHOT (running on Java 16.0.2+7-67)

Verifying from file data/vp-1632686198721.json ...

Results:

TrustedIssuerDidPolicy:          true
TrustedSubjectDidPolicy:                 true
JsonSchemaPolicy:                true
Verified:                true

Note that the order of the policies does matter. The TrustedIssuerDidPolicy & TrustedSubjectDidPolicy are verifying the presents of the DIDs on the EBSI ledger, and if they are, the keys are imported to the key-store. Once the keys are available, the SignaturePolicy can be applied in order to verify each signature.

You can find more information about EBSI/ESSIF .

As prerequisite, the bearer token (validity of 15 min) from must be placed in file data/ebsi/bearer-token.txt

The shows how to register an EBSI DID in Java.

Issuing two credentials, one Bachelor & one Master degree (values are defined by running the interactive shell). Both credentials are based on the

here
https://app-pilot.ebsi.eu/users-onboarding/v2
did:ebsi example
VerifiableDiploma Template

IOTA

The following section outlines the planned integration of the IOTA identity framework with the walt.id SSI Kit and gives insight on the architecture of the integration and the required changes that need to be applied to the SSI Kit to establish smooth interoperability with the IOTA ecosystem.

Introduction

In addition to the open standards for decentralized identity, the IOTA identity frameword implements a custom DID method, which needs to be supported by the walt.id SSI Kit to ensure compatibility.

Integration overview

Thanks to the use of W3C standards for DID documents and verifiable credentials, the SSI Kit is mostly compatible with the IOTA identity framework, with regards to DID documents and issuance/validation of verifiable credentials. Also the key type Ed25519, used in the IOTA framework is already supported by the SSI Kit.

The following aspects have been identified, which require implementation changes and/or integration work in the SSI Kit:

  1. IOTA DID method: Creation, management and registration of DIDs on the IOTA tangle

  2. Key management: Integrate SSI Kit key management seamlessly, such that keys managed by the SSI Kit (or a supported key store implementation) can be leveraged in the context of the IOTA framework.

  3. Signature type: To ensure compatibility of issued credentials with both the SSI Kit and the IOTA framework, the LD-signature type JcsEd25519Signature2020 needs to be supported in the SSI Kit.

  4. Public key format: The public key, stored in the verification methods of the IOTA DID documents, is formatted in multibase encoding, for which support in the SSI Kit needs to be provided.

The following subsections give more details on the planned integration work.

Integration architecture

The following chart outlines the overall architecture of the integration between the walt.id SSI Kit and the IOTA framework:

Rust library wrapper

In order to overcome the native-to-managed-code gap between the IOTA identity framework libraries, written in Rust, and the SSI Kit in Kotlin/JVM, a wrapper library is implemented in Rust, which includes the IOTA libraries as a dependency and exposes a plain C-compatible application binary interface (ABI).

This approach also facilitates portability of the wrapper library to all operating systems and platforms supported by the Rust compiler and the IOTA framework library.

DID management

For DID creation and management, the wrapper library implements an interface method, called by the IotaService component in the SSI Kit.

The created DID document is returned to the SSI Kit, where it can be parsed and stored for further use.

Key management

In order to be able to make full use of the SSI Kit together with the IOTA framework, it is preferred to share the key store between both worlds.

The SSI Kit provides a key store abstraction layer, that has support for various key store implementations, including an embedded key store and cryptography library, as well as cloud-based HSM stores, such as Azure key vault and the walt.id Storage Kit, a general-purpose distributed encrypted data store.

LD signature type

Thus, to be compatible with the credentials issued by the IOTA framework,the SSI Kit needs to be extended to support this type of signature.

DID documents and verification material

Given the support of multibase encoded verification material, the DID documents should be fully compatible with the SSI Kit.

We apologize that our current implementation does not yet support the Stardust Upgrade from IOTA. As such, you cannot issue or verify credentials associated via a did:iota. Please refer to our for more information on when our products will be updated to include this latest changes.

The , much like the walt.id SSI Kit, is based on open standards for decentralized identity, such as the W3C specifications for and and provides creation, management and registration of DIDs on the IOTA DLT technology (tangle), as well, as issuance, signing and validation of verifiable credentials.

The wrapper library can be loaded in Kotlin/JVM using the abstracted foreign function layer library. The advantage compared to JNI (Java Native Interface) is that no Java-specific interface code needs to be written in the native wrapper library, such that the same library could be used from various other programming and scripting languages, that support loading of native dynamic libraries.

The public and private keys for creating the DID, should be managed by the SSI Kit and its key store abstraction layer, with support for various key store implementations (see also below).

The wrapper library makes use of the AccountBuilder of the identity_iota::account module to create and register a DID on the IOTA ledger. After creation the library updates the DID document to include the various , such that issuance (assertionMethod) and presentation (authentication) of verifiable credentials is permitted using the new DID.

In order to leverage the SSI Kit key store abstraction with the IOTA identity framework integration, we plan to implement a key store mediator component in the Rust wrapper library, which exposes the IOTA on the one hand, and, on the other hand, communicates the signing or encryption/decryption requests to the SSI Kit via a native-to-managed callback function. This key store mediator can be passed to the AccountBuilder as to storage interface to use for DID creation. The SSI Kit can then fulfill the cryptographic requests using the configured key store implementation and hand back the result to the wrapper library and IOTA framework internals.

The IOTA identity framework makes use of the LD-signature type for signing and validation of verifiable credentials.

To make the SSI Kit compatible with the DID documents created by the IOTA identity framework, it is required to support Multibase encoding of the verification material in the verification method objects, according to the latest , as for the time being, an older version of said specification is implemented, using Base58 encoding.

roadmap
IOTA identity framework
verifiable credentials
decentralized identifiers (DIDs)
JNR-FFI
verification method relationships
storage interface
JcsEd25519Signature2020
DID specification
Key management

Velocity

Intro to Velocity Network

Velocity Network Foundation

Velocity NetworkTM is a public permissioned distributed network, based on a permissioned version of the Ethereum Blockchain utilizing Hyperledger Besu. Operating a node and writing to the Velocity Ledger requires permission from the Velocity Network FoundationR.

The following data is stored on chain:

  • organization metadata - DID, profile, endpoint

  • credential metadata (encrypted) - ID, type, public key, revocation status

  • verification voucher transactions

  • credential types and schemas

Network participants

High level

  • Holder - a person that holds the credential on behalf of the subject (themselves or another person)

  • Issuer - an organization that creates and issues credentials

    • first party issuer - an entity that can directly attest to the claims within the credential

    • notary issuer - an entity that can evaluate evidence to attest to the claims within the credential

  • Relying Party - an entity that requests and verifies credentials from a Holder

Low level

  • Wallet Provider (Holder App Provider) - an organization offering digital wallets to be used by Holders

  • Credential Agent Operator - an organization operating a credential agent

    • Agent - an interface to the network used by organizations (Issuer, Relying Party, Holder) - call contracts, retrieve account states - form the 'layer-2' network

      • Tenant - an organization’s delegate on which behalf the agent is acting

  • Node Operator - an organization operating a node

    • Node - a participant on the network holding copies of the underlying ledger

      • Members (Stewards) - read-only nodes with limited data access that forward write operations to Validators

      • Validators - full-write permission nodes that participate in consensus

  • Velocity Network Registrar - a set of centralized services that are used for administering the accredited organizations and credential types on the Network

  • Credits hub - a module where Velocity credits are administered and credit reward transactions can be executed

  • Voucher hub - a module where Velocity vouchers are administered and top up transactions can be executed

  • The ledger - the distributed blockchain-based, continuously-replicated, global cryptographic database maintained by Stewards operating nodes communicating with the Velocity consensus protocol

Workflows

  • Issuing - the process of asserting claims about a Holder who receives the verifiable credential

    • by writing a transaction to the Velocity Ledger which includes the credential ID, its type, the Issuer ID, and the public key matching the private key that signed it

  • Revocation - the act of an Issuer revoking the validity of a credential

    • by writing a transaction to the Velocity Ledger marking the credential as revoked

  • Verification - the process of confirming that a verifiable credential is not modified, revoked or expired and is issued by a trusted authority

    • by accessing the Velocity Ledger to retrieve the unique public key associated with credential and verify its signature

Verifiable Credentials

Velocity currently uses the JWT format for encoding credentials with JWS signatures using SECP256K1 as proofs.

Verifiable credentials are divided into the following categories:

  • Layer-1 credential types - network’s core set of credential types (e.g. Email, IdDocument, OpenBadgeCredential)

    • for each issued credential, the Issuer receives a reward in the form of Velocity Credits

  • Layer-2 credential types - any custom credential type

    • should be mapped to a Layer-1 type in order for the Issuer to be eligible for a reward

More about credential types here https://docs.velocitynetwork.foundation/docs/developers/basics-credential-types.

Decentralized identifiers

  • did:ion - used to identify organizations or individuals

    • received when registering with the Registrar

  • did:velocity - used to identify credentials

    • is immutable

    • stores only a single key and credential type

    • resolving it will burn an NFT to permit DID resolution

Integration architecture
Generate key help command output
Generate Secp256k1 key command output
List keys command output
Ed25519 public key JWK input
JWK Ed25519 key import output
Secp256k1 key PEM input
PEM Secp256k1 key import output
Export output for PEM format public key
Export output for JWK format public key
Export output for PEM format private key
Export output for JWK format private key
Delete key output
Create did help command output
List dids command output

Basics

This section describes the main steps required to interact with Velocity network:

OIDC4VP profile for Login-with-IOTA

Introduction

DIDs and Key Material

DID method
Key algorithm

Verifiable Credentials and Proof Format

Format
Signature type

Authorization flow

Request

  • state: OPTIONAL. State provided by the authorization client, that is passed through to the response.

A request MUST contain either a presentation_definition or a presentation_definition_uri. Those two ways to request credential presentations are mutually exclusive. The wallet MUST refuse any request violating this requirement.

presentation_definition

Alternatively the request could contain the presentation_definition_uri parameter, containing a URL to a presentation definition object.

The following example shows a presentation definition object, requesting the presentation of a VerifiableId credential:

{
    "id": "vp token example",
    "input_descriptors": [
        {
            "id": "verifiable id credential",
            "format": {
                "ldp_vc": {
                    "proof_type": [
                        "JcsEd25519Signature2020"
                    ]
                }
            },
            "constraints": {
                "fields": [
                    {
                        "path": [
                            "$.type"
                        ],
                        "filter": {
                            "type": "string",
                            "pattern": "VerifiableId"
                        }
                    }
                ]
            }
        }
    ]
}

Example request

This is an example authorization request:

GET /authorize?
  scope=openid
  &presentation_definition=[...]
  &response_type=vp_token
  &redirect_uri=[...]
  &state=9925f001-9010-4dd3-9a58-5c140c85d824
  &nonce=9925f001-9010-4dd3-9a58-5c140c85d824
  &client_id=[...]
  &response_mode=post

Response

The response parameters depend on the response_type defined in the authorization request. Possible response parameters include:

  • state: Optional state parameter passed through from the authorization request.

Response types

  • If only vp_token is used as the response_type, the VP Token is provided in the authorization response.

  • If id_token is used as the response_type alongside vp_token, the VP Token is provided in the OpenID Connect authentication response along with the ID Token.

  • In all other cases, if vp_token is not used, but presentation_definition parameter is present, the VP Token is provided in the Token Response.

Any combination of vp_token with a response_type other than id_token is undefined.

vp_token

The vp_token response parameter contains the verifiable presentation or array of verifiable presentations, matching the input descriptors of the presentation definition, specified in the authorization request.

presentation_submission

Example responses

This is an example response for the respones_type=vp_token request parameter, with the presentation_submission and vp_token response parameters:

HTTP/1.1 302 Found
  Location: https://client.example.org/cb#
    presentation_submission=[...]
    &vp_token=[...]
    &state=9925f001-9010-4dd3-9a58-5c140c85d824

An example vp_token, containing a presentation with a VerifiableId credential:

{
  "type": [
    "VerifiablePresentation"
  ],
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/suites/jws-2020/v1"
  ],
  "id": "urn:uuid:73c01e73-6f18-4e8c-a751-ec9f4d25855e",
  "holder": "did:iota:6Nte6ZfQGQ81UZNGBLtDAJnFui8nBgEMjtMKDadYYexS",
  "verifiableCredential": [
    {
      "type": [
        "VerifiableCredential",
        "VerifiableAttestation",
        "VerifiableId"
      ],
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://w3id.org/security/suites/jws-2020/v1"
      ],
      "id": "urn:uuid:4be3b79e-16aa-4562-883c-e5e1c11fd623",
      "issuer": "did:iota:z6MkiprkVjgTngmWh6y2cEPDBPWiWpnSxaPiL4HR8vQRoR3h",
      "issuanceDate": "2022-12-20T10:02:57Z",
      "issued": "2022-12-20T10:02:57Z",
      "validFrom": "2022-12-20T10:02:57Z",
      "credentialSchema": {...},
      "credentialSubject": {
        "id": "did:iota:6Nte6ZfQGQ81UZNGBLtDAJnFui8nBgEMjtMKDadYYexS",
        "currentAddress": [...],
        "dateOfBirth": "1993-04-08",
        "familyName": "DOE",
        "firstName": "Jane",
        "gender": "FEMALE",
        "nameAndFamilyNameAtBirth": "Jane+DOE",
        "personalIdentifier": "0904008084H",
        "placeOfBirth": "LILLE,+FRANCE"
      },
      "evidence": [...],
      "proof": {
        "type": "JcsEd25519Signature2020",
        [...]
        "verificationMethod": "did:iota:[...]",
        "signatureValue": "[...]"
      }
    }
  ],
  "proof": {
    "type": "JcsEd25519Signature2020",
    [...]
    "proofPurpose": "authentication",
    "verificationMethod": "did:iota:[...]",
    "signatureValue": "[...]"
  }
}

An example presentation_submission object:

{
  "definition_id": "1",
  "descriptor_map": [
    {
      "format": "ldp_vp",
      "id": "0",
      "path": "$",
      "path_nested": {
        "format": "ldp_vc",
        "id": "0",
        "path": "$.verifiableCredential[0]"
      }
    }
  ],
  "id": "1"
}

Error response

Same-device flow (Web)

Example request

https://wallet.walt-test.cloud/api/siop/initiatePresentation/
  ?scope=openid
  &presentation_definition=[...]
  &response_type=vp_token
  &redirect_uri=https%3A%2F%2Fverifier.walt-test.cloud%2Fverifier-api%2Fverify
  &state=f3265a8c-4dff-4252-8df9-6569286e109a
  &nonce=f3265a8c-4dff-4252-8df9-6569286e109a
  &client_id=https%3A%2F%2Fverifier.walt-test.cloud%2Fverifier-api%2Fverify
  &response_mode=form_post

Example response

POST https://verifier.walt-test.cloud/verifier-api/verify

vp_token=[...]
&presentation_submission=[...]
&state=f3265a8c-4dff-4252-8df9-6569286e109a

Cross-device flow

Example request

openid://
  ?scope=openid
  &presentation_definition=[...]
  &response_type=vp_token
  &redirect_uri=https%3A%2F%2Fverifier.walt-test.cloud%2Fverifier-api%2Fverify
  &state=663667ae-fc5c-4cb8-87ab-1f506ca142e7
  &nonce=663667ae-fc5c-4cb8-87ab-1f506ca142e7
  &client_id=https%3A%2F%2Fverifier.walt-test.cloud%2Fverifier-api%2Fverify
  &response_mode=post

Example response

POST https://verifier.walt-test.cloud/verifier-api/verify

vp_token=[...]
&presentation_submission=[...]
&state=f3265a8c-4dff-4252-8df9-6569286e109a

References

EBSI

This section shows how you can use the SSI Kit to interact with Europe’s emerging identity ecosystem based on the

  • EU Blockchain Service Infrastructure (EBSI)

  • EU Self-Sovereign Identity Framework (ESSIF)

State of the EBSI/ESSIF specifications

Note, that some of the flows are not in their final version. Slight modifications are to be expected.

ESSIF DID Registration

Creation and anchoring of a new DID on the EBSI ledger (incl. use of "Verifiable Authorizations" and EBSI access tokens).

ESSIF Onboarding

Onboarding of a legal entity to the EBSI/ESSIF ecosystem (incl. combined VC request and DID registration).

EBSI Auth API

Gaining access to protected EBSI/ESSIF services (incl. presentation of "Verifiable Authorization").

Issuance of Verifiable Credentials

The ESSIF protocol for issuance of verifiable credentials aims to being compliant with the OIDC for credential issuance specification. Refer to the respective section for details:

Exchange of Verifiable Presentations

The ESSIF protocol for presentation of verifiable credentials to a Verifier or Relying Party, aims to being compliant with the OIDC/SIOPv2 specification. Refer to this section for details:

Code examples

REST API

ESSIF REST API functions.

The ESSIF API exposes the necessary endpoints for running the ESSIF specific flows between Issuers (incl. ESSIF Onboarding Services), Holders and Verifiers.

Aligned with the ESSIF terminology, the API is grouped by the User Wallet (wallet API for consumers / natural persons) and Enterprise Wallet (wallet API for organisations / legal entities).

Note that the EBSI/ESSIF specifications are expected to evolve which will be reflected in continuous updates of the proposed APIs.

The following functions are available:

Onboard

The /v1/client/onboard endpoint onboards the specified DID to the EBSI blockchain. It runs the ESSIF onboard API and requires a Bearer token, which can be acquired from https://app.preprod.ebsi.eu/users-onboarding.

E.g. Onboard the did = did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q.

Authorize

The /v1/client/auth runs the ESSIF authorization flow for the specified did.

E.g. Run the authorization flow for did = did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q.

Register DID

The /v1/client/registerDid endpoint registers the specified DID on the EBSI ledger.

E.g. Register did = did:ebsi:zwdPobJGue3w86Gpqhq5Cni on the EBSI ledger.

Create timestamp

The /v1/client/timestamp endpoint creates a timestamp on the EBSI ledger, using the provided DID as a key. The data will be written to the data-field of the timestamp.

E.g. Create a timestamp using did = did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q.

Load timestamp by id

The /v1/client/timestamp/id/{timestampId} endpoint loads the timestamp based on the provided parameter:

  • timestampId - path parameter (required) - the timestamp id

E.g. Load the timestamp having id = uEiBEtXzl3QXshn5Z1V4dgZVtMlvnx3E1f2IWFDQVqzEv_Q.

Load timestamp by hash

The /v1/client/timestamp/txhash/{txhash} endpoint loads the timestamp based on the provided parameter:

  • txhash - path parameter (required) - the transaction hash

E.g. Load the timestamp having the transcation hash 0x9c60ca0094771afe4093b0e47260eb623d5d18140e188e671cf912609cd0e169.

ESSIF DID registration
ESSIF Onboarding
EBSI Auth API

We apologize that our current implementation does not yet support the Stardust Upgrade from IOTA. As such, you cannot issue or verify credentials associated via a did:iota. Please refer to our for more information on when our products will be updated to include this latest changes.

Authors: Severin Stampler () December 2022

Login-with-IOTA is defined as a profile of the OpenID Connect for Verifiable Presentations specification [], which defines the protocol for authorization using SSI, based on top of OAuth 2.0 [] and introduces protocol extensions for the presentation of claims via Verifiable Credentials []. In this document we will describe the specifics of using the OIDC4VP protocol in the scope of Login-with-IOTA to ensure compatibility with the IOTA identity framework [].

The IOTA identity framework [] defines a custom DID method [], based on the public key of the user account. The key material used is an EdDSA/Ed25519 [] key pair.

To ensure compatibility with the IOTA identity framework [], the issuers and holders of verifiable credentials should use a did:iota for issuance and as credential subject.

The credentials used by the IOTA identity framework [] are in line with the W3C specification for Verifiable Credentials []. Every type of credential, that is compatible with the W3C specification, should in theory be supported.

Proofs for the credentials are created in the linked data format, ldp_vc or ldp_vp, as described by the W3C data integrity specification [], using [] as the credential format and the JCS Ed25519 Signature 2020 [] signature type.

The [] specification is based on top of OAuth 2.0 [], which enables implementers to also build on top of OpenID Connect [] and the Self-issued OpenId Provider specification [].

This Login-with-IOTA profile of the [] specification supports only W3C Verifiable Credentials [].

Like described by [], verifiable presentations can be requested by adding the presentation_definition parameter to the authorization request. The presentation is returned in the vp_token response parameter.

Both, and flows are supported by this profile. For cross-device scenarios [] introduces a new response mode post, to support verifier initiated verification.

The parameters for a Login-with-IOTA authorization request, are a subset of the parameters defined by the [] specification:

response_type: REQUIRED. this parameter is defined in []. The possible values are determined by the response type registry established by []. This specification introduces the response type vp_token. This response type asks the Authorization Server (AS) to return only a VP Token in the Authorization Response.

presentation_definition: CONDITIONAL. A string containing a presentation_definition JSON object as defined in Section 4 of [].

presentation_definition_uri: CONDITIONAL. A string containing a URL pointing to a resource where a presentation_definition JSON object as defined in Section 4 of [] can be retrieved .

nonce: REQUIRED. This parameter follows the definition given in []. It is used to securely bind the verifiable presentation(s) provided by the AS to the particular transaction.

The presentation_definition parameter must contain a JSON representation of a Presentation Definition object, according to the DIF Presentation Exchange specification [].

vp_token: The verifiable presentation or array of presentations matching the presentation definition in the request. The required format in this profile is [] / []. The JSON data must be URL encoded. See also section 7.3 of [].

id_token: The ID token as defined by section 2 of the [] core specification.

presentation_submission: The presentation submission object, as defined in [], which links the input descriptors of the presentation definition in the request to the corresponding presentation(s) in the vp_token response.

Depending of the response_type given in the authorization request, the response should contain the following parameters, like described in section 6.1 of []:

The only supported format of the verifiable presentation in this specification is the [] / [] format. The JSON data can be either a single presentation object or an array of JSON objects and must be URL encoded.

The presentation submission object contains the correlations of the input descriptors, specified in the presentation definition of the authorization request, with the verifiable presentations in the VP token of the response. The format of the presentation submission objects is defined in section 6 of [].

For creating compliant error responses, please refer to section 6.3 of [].

For the same device flow, the verifier or relying party, links directly to the authorization endpoint of the wallet, passing the request parameters, as specified in the section.

The response_mode should be set to form_post. After getting the user consent, the wallet will generate the response parameters, as specified in the section, and performs a HTTP FORM POST action to the redirect_uri specified in the authorization request. The relying party can now verify the authorization response and redirect the user to the protected web page.

For the cross-device flow, the verifier or relying party initiates an internally cached authorization session and displays a QR code containing the authorization request URI with the request parameters, as specified in the section.

The response_mode should be set to post. The wallet scans the QR code and parses the authorization request. After getting the user consent, the wallet will generate the response parameters, as specified in the section, and posts the response to the redirect_uri specified in the authorization request, via the HTTP POST method. The relying party can now verify the authorization response and update the state of the internally cached authorization session. Depending on the concrete implementation (for example by polling for the session state), the relying party UI can now be refreshed and redirected to the protected page.

[]

Terbu, O., Lodderstedt, T., Yasuda, K., Lemmon, A., Looker, T., "OpenID for Verifiable Presentations", September 2022,

[]

Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012,

[]

Sporny, M., Longley, D., Chadwick, D., "Verifiable Credentials Data Model v1.1", March 2022,

[]

IOTA Foundation, "IOTA Identity Framework Guide",

[]

Millenaar, J., IOTA Foundation, "IOTA DID Method Specification",

[]

Josefsson, S.; Liusvaara, I. (January 2017). Edwards-Curve Digital Signature Algorithm (EdDSA). IRTF. doi:10.17487/RFC8032. ISSN 2070-1721. RFC 8032.

[]

Longley, D., Sporny, M., "Verifiable Credential Data Integrity 1.0",

[]

Sporny, M., Longley, D., Kellog, G., Lanthaler, M., Champin, P., Lindström, N., "JSON-LD 1.1",

[]

Cohen, G., Steele, O, Decentralized Identity Foundation, "JCS Ed25519 Signature 2020",

[]

N. Sakimura, J. Bradley, M. Jones, B. de Medeiros, C. Mortimore, "OpenID Connect Core 1.0 incorporating errata set 1", November 8, 2014,

[]

K. Yasuda, M. Jones, T. Lodderstedt, "Self-Issued OpenID Provider v2", September 2022,

[]

Buchner, D., Zundel, B., Riedel, M., and K. H. Duffy, "Presentation Exchange 2.0.0", , .

**** you can find examples on how to use the SSI Kit command line interface to interact with the EBSI/ESSIF ecosystem.

For SSIKit usage examples, refer to:

Several code-examples how to use the ESSIF functionality of the SSI Kit are shown on

|

- EBSI onboarding flow, requests a Verifiable Authorization from EOS

- ESSIF authorization flow

- registers DID on the EBSI blockchain

- creates a timestamp in EBSI ledger

- loads a timestamp by the timestamp id

- loads a timestamp by the transaction hash

onboarding (did registration)
issuing credentials
inspecting credentials
roadmap
walt.id
OIDC4VP
https://openid.net/specs/openid-4-verifiable-presentations-1_0.html
RFC6749
https://www.rfc-editor.org/info/rfc6749
VC_DATA_MODEL
https://www.w3.org/TR/vc-data-model/
IOTA_IDENTITY
https://wiki.iota.org/identity.rs/introduction/
IOTA_DID
https://wiki.iota.org/identity.rs/specs/did/iota_did_method_spec/
RFC8032
https://datatracker.ietf.org/doc/html/rfc8032
VC_DATA_INTEGRITY
https://w3c.github.io/vc-data-integrity/
JSON_LD
https://www.w3.org/TR/json-ld11/
JCSEd25519Signature2020
https://identity.foundation/JcsEd25519Signature2020/
OIDC
https://openid.net/specs/openid-connect-core-1_0.html
SIOPv2
https://openid.bitbucket.io/connect/openid-connect-self-issued-v2-1_0.html
DIF.PresentationExchange
https://identity.foundation/presentation-exchange/spec/v2.0.0/
OIDC4VP
RFC6749
VC_DATA_MODEL
IOTA_IDENTITY
IOTA_IDENTITY
IOTA_DID
RFC8032
IOTA_IDENTITY
IOTA_IDENTITY
VC_DATA_MODEL
VC_DATA_INTEGRITY
JSON-LD
JcsEd25519Signature2020
OIDC4VP
RFC6749
OIDC
SIOPv2
OIDC4VP
VC_DATA_MODEL
OIDC4VP
same-device
cross-device
OIDC4VP
OIDC4VP
RFC6749
RFC6749
DIF.PresentationExchange
DIF.PresentationExchange
OIDC
DIF.PresentationExchange
ldp_vp
JSON-LD
OIDC4VP
OIDC
DIF.PresentationExchange
OIDC4VP
ldp_vp
JSON-LD
DIF.PresentationExchange
OIDC4VP
Authorization request
Authorization response
Authorization request
Authorization response
curl -X 'POST' \
  'https://essif.ssikit.walt.id/v1/client/onboard' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "bearerToken": "string",
    "did": "string"
}
The VerifiableAuthorization credential string
curl -X 'POST' \
  'https://essif.ssikit.walt.id/v1/client/onboard' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "bearerToken": "eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2NjUzOTc0ODksImlhdCI6MTY2NTM5NjU4OSwiaXNzIjoiZGlkOmVic2k6emNHdnFnWlRIQ3Rramd0Y0tSTDdIOGsiLCJvbmJvYXJkaW5nIjoicmVjYXB0Y2hhIiwidmFsaWRhdGVkSW5mbyI6eyJhY3Rpb24iOiJsb2dpbiIsImNoYWxsZW5nZV90cyI6IjIwMjItMTAtMTBUMTA6MDk6NDZaIiwiaG9zdG5hbWUiOiJhcHAucHJlcHJvZC5lYnNpLmV1Iiwic2NvcmUiOjAuOSwic3VjY2VzcyI6dHJ1ZX19.Qth9uTf4uXoPR9PiykUKyLV6qsOXtG70gJRghRzu9qMtyQmfqVD5hx2YwBgoWF9jebLCcmVtbr1KxVjuNcy1Cg",
  "did": "did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q"
}'
{
    "bearerToken": "eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2NjUzOTc0ODksImlhdCI6MTY2NTM5NjU4OSwiaXNzIjoiZGlkOmVic2k6emNHdnFnWlRIQ3Rramd0Y0tSTDdIOGsiLCJvbmJvYXJkaW5nIjoicmVjYXB0Y2hhIiwidmFsaWRhdGVkSW5mbyI6eyJhY3Rpb24iOiJsb2dpbiIsImNoYWxsZW5nZV90cyI6IjIwMjItMTAtMTBUMTA6MDk6NDZaIiwiaG9zdG5hbWUiOiJhcHAucHJlcHJvZC5lYnNpLmV1Iiwic2NvcmUiOjAuOSwic3VjY2VzcyI6dHJ1ZX19.Qth9uTf4uXoPR9PiykUKyLV6qsOXtG70gJRghRzu9qMtyQmfqVD5hx2YwBgoWF9jebLCcmVtbr1KxVjuNcy1Cg",
    "did": "did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q"
}
"{\"verifiableCredential\":{\"id\":\"vc:ebsi:authentication#b1a82eb3-9a29-429d-b440-91894ed07720\",\"issuer\":\"did:ebsi:zcGvqgZTHCtkjgtcKRL7H8k\",\"validFrom\":\"2022-10-10T11:35:23Z\",\"credentialSubject\":{\"id\":\"did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q\"},\"credentialSchema\":{\"id\":\"https://api.preprod.ebsi.eu/trusted-schemas-registry/v1/schemas/0x28d76954924d1c4747a4f1f9e3e9edc9ca965efbf8ff20e4339c2bf2323a5773\",\"type\":\"OID\"},\"issuanceDate\":\"2022-10-10T11:35:23Z\",\"expirationDate\":\"2023-04-10T11:35:23Z\",\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://www.w3.org/2018/credentials/examples/v1\",\"https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json\"],\"type\":[\"VerifiableCredential\",\"VerifiableAuthorisation\"],\"proof\":{\"type\":\"EcdsaSecp256k1Signature2019\",\"created\":\"2022-10-10T11:35:23Z\",\"proofPurpose\":\"assertionMethod\",\"verificationMethod\":\"did:ebsi:zcGvqgZTHCtkjgtcKRL7H8k#keys-1\",\"jws\":\"eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1QifQ..WEwqx6kOJMA5Mk6xZ7uTfkZB8RDnAhnnIWInBH6BlJNjtsbzIfpHyzB11Gh1xWQVejD3i-0jnwxJyHs8m4JtuQ\"}}}"
curl -X 'POST' \
  'https://essif.ssikit.walt.id/v1/client/auth' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '<request-body>'
The did string
Code 200
curl -X 'POST' \
  'https://essif.ssikit.walt.id/v1/client/auth' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d 'did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q'
did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q
curl -X 'POST' \
  'https://essif.ssikit.walt.id/v1/client/registerDid' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '<request-body>'
The did url string
Code 200
curl -X 'POST' \
  'https://essif.ssikit.walt.id/v1/client/registerDid' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d 'did:ebsi:zwdPobJGue3w86Gpqhq5Cni'
did:ebsi:zwdPobJGue3w86Gpqhq5Cni
curl -X 'POST' \
  'https://essif.ssikit.walt.id/v1/client/timestamp' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '<request-body>'
{
    "did": "string",
    "ethDidAlias": "string",
    "data": "string"
}
The transaction hash
curl -X 'POST' \
  'https://essif.ssikit.walt.id/v1/client/timestamp' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "did": "did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q",
  "data": "my-data"
}'
{
    "did": "did:ebsi:zYubw2L8tCZSKKpAcMmCY2Q",
    "data": "my-data"
}
0x9c60ca0094771afe4093b0e47260eb623d5d18140e188e671cf912609cd0e169
curl -X 'GET' \
  'https://essif.ssikit.walt.id/v1/client/timestamp/id/{timestampId}' \
  -H 'accept: application/json'
No parameters
The timestamp json object
curl -X 'GET' \
  'https://essif.ssikit.walt.id/v1/client/timestamp/id/uEiBEtXzl3QXshn5Z1V4dgZVtMlvnx3E1f2IWFDQVqzEv_Q' \
  -H 'accept: application/json'
{
    "blockNumber": 6434223,
    "data": "0x7b2274657374223a202234346239343965322d336661652d343564372d626666392d396464666436663666376134227d",
    "hash": "mEiBsHu0aNKVDJlqfyxS4pFYH4aFW86s0s60uJl+SmJT8aw",
    "href": "https://api.preprod.ebsi.eu/timestamp/v2/timestamps/uEiBEtXzl3QXshn5Z1V4dgZVtMlvnx3E1f2IWFDQVqzEv_Q",
    "timestamp": "2022-10-10T11:51:16.000Z",
    "timestampId": "uEiBEtXzl3QXshn5Z1V4dgZVtMlvnx3E1f2IWFDQVqzEv_Q",
    "timestampedBy": "0x635A4045A3f82d2C5597225614747c02998B112a",
    "transactionHash": "0x9c60ca0094771afe4093b0e47260eb623d5d18140e188e671cf912609cd0e169"
}
curl -X 'GET' \
  'https://essif.ssikit.walt.id/v1/client/timestamp/txhash/{txhash}' \
  -H 'accept: application/json'
No parameters
The timestamp json object
curl -X 'GET' \
  'https://essif.ssikit.walt.id/v1/client/timestamp/txhash/0x9c60ca0094771afe4093b0e47260eb623d5d18140e188e671cf912609cd0e169' \
  -H 'accept: application/json'
{
    "blockNumber": 6434223,
    "data": "0x7b2274657374223a202234346239343965322d336661652d343564372d626666392d396464666436663666376134227d",
    "hash": "mEiBsHu0aNKVDJlqfyxS4pFYH4aFW86s0s60uJl+SmJT8aw",
    "href": "https://api.preprod.ebsi.eu/timestamp/v2/timestamps/uEiBEtXzl3QXshn5Z1V4dgZVtMlvnx3E1f2IWFDQVqzEv_Q",
    "timestamp": "2022-10-10T11:51:16.000Z",
    "timestampId": "uEiBEtXzl3QXshn5Z1V4dgZVtMlvnx3E1f2IWFDQVqzEv_Q",
    "timestampedBy": "0x635A4045A3f82d2C5597225614747c02998B112a",
    "transactionHash": "0x9c60ca0094771afe4093b0e47260eb623d5d18140e188e671cf912609cd0e169"
}

Issuing

Issuing involves an exchange between a Holder and an Issuer, by which the Holder receives a set of offers from the Issuer. Once the Holder accepts the offers, the Issuer converts them into verifiable credentials and supplies them to the Holder.

Depending on data source location and process initiating party, the following issuing types are supported:

  • custom - credential agent loads offers from itself as well as calling out webhooks

    • demand triggered - Holder initiates the credential claiming process

      • Issuer responds with the available credential offers according to Holder’s criteria

    • supply triggered - Issuer initiates the credential claiming process

      • offers are made available to the Holder using a notification mechanism by sending a deep-link or qr-code to claim the credentials

  • batch - credential agent loads offers only from itself

    • a specialized version of supply triggered custom issuing

More information on issuing can be found at https://docs.velocitynetwork.foundation/docs/developers/developers-guide-issuing.

Here
EBSI DID registration
OIDC for credential issuance
OIDC/SIOPv2 for verifiable presentations
GitHub
Swagger
ReDoc
did:iota
EdDSA/Ed25519
ldp_vc / ldp_vp
JcsEd25519Signature2020
onboard
authorize
register did
create timestamp
load timestamp by id
load timestamp by hash

Onboarding

In order to operate on Velocity network, any entity (regardless of scope - issuer, relying party or credential agent operator) has to register with the network.

The onboarding is currently done manually and will custody a DID on the DID:ION network:

  • get an account with the registrar

  • set up the organization(s)

    • set the required services according to the use case:

      • issuer - VlcCareerIssuer_v1

      • verifier - VlcInspector_v1

      • agent operator - VlcCredentialAgentOperator_v1

  • configure the tenants

    • add the required keys according to the use case:

      • issuer - ISSUING_METADATA

      • verifier - EXCHANGES

      • agent operator - DLT_TRANSACTIONS

The configuration steps from above can be completed either using:

More information on Velocity onboarding can be found at https://docs.velocitynetwork.foundation/docs/developers/developers-guide-getting-started.

Inspection

The verification process (inspection) is initiated by disclosure exchanges where the Relying Party requests credentials from Holder. These exchanges can be encoded in the following ways:

  • deep links - a URI that matches the spec:

  • QR-codes - a visual representation of a deep link

Depending on the use case, the Relying Party can request either:

  • verified credentials

    • requires payment in tokens

    • returns the verification checks (policies) result

  • unverified credentials:

    • requires no payment in tokens

    • can be verified later

Verification policies

The verification checks performed against the credential are the following:

  • UNTAMPERED

    • pass - hasn't been tampered

    • fail - has been tampered

    • voucher_reserve_exhausted - a voucher is required for verification

  • TRUSTED_ISSUER

    • pass - issuer is trusted

    • fail - issuer is not a member of Velocity

    • self_signed - data attested by the Holder

    • voucher_reserve_exhausted - a voucher is required for verification

  • UNREVOKED

    • pass - hasn't been revoked

    • has been revoked

    • voucher_reserve_exhausted - a voucher is required for verification

  • UNEXPIRED

    • pass - hasn't expired

    • fail - has expired

More details on credential verification checks can be found at https://docs.velocitynetwork.foundation/docs/developers/developers-guide-disclosure-exchange#credential-verification-checks.

More on credential verification at https://docs.velocitynetwork.foundation/docs/developers/developers-guide-disclosure-exchange.

Integration with SSIKit

The interaction with Velocity network is implemented in SSIKit using a Rest API client which currently exposes the functionality through the command-line-interface. The available functions can grouped as follows:

  • organization related

    • onboarding

    • tenant configuration

  • credential related

    • issuance

    • verification

In order to cover the credential related functions, but also tenant management, SSIKit uses a credential agent deployed on walt.id infrastructure. For this, walt.id is registered on Velocity network (currently only on testnet) as a credential agent operator and can issue and verify credentials on behalf of issuer using either issuer's keys or walt.id keys. The diagram below shows how Velocity integration is currently done with SSIKit.

The organization related functions, such as onboarding and DID acquisition, are implemented by calling Velocity network registrar Rest API.

Command line interface

This section describes the following functions implemented as part of Velocity network integration:

Velocity network specific operation are available under the velocity command:

 ./ssikit.sh velocity -h

Integration architecture

Onboarding

Velocity onboading commands are available under the onboard command as follows:

DID acquisition

E.g. Onboarding organization.

Tenant management

Every organization needs a tenant on the credential agent. Tenant functions are available under the tenant command:

  • create tenant

E.g. Add a tenant having verifier, issuer and agent operator purposes.

Disclosure management

In order to be able to issue / verify credential, it is required to have the correct identification disclosure set up. Current disclosure management functions are:

  • create disclosure

E.g. Create an integrated issuing identification disclosure.

ESSIF DID registration
ESSIF Onboarding
EBSI Auth API

by sending an email to

or

integration architecture

velocity-command

In order to be able to onboard the did:cheqd on testnet and mainnet, SSIKit relies on a deployed on walt.id infrastructure. The DID will be created using a key imported into or also created with SSIKit.

Once an account was set up with the registrar (see ), cli-tool can be used to register the organization, using the command:

support@velocitynetwork.foundation
registration UI
Rest API
velocity-network://inspect?request_uri=[REQUEST_URI]&inspectorDid=[INSPECTOR_DID]&vendorOriginContext=[VENDOR_ORIGIN_CONTEXT]
onboarding
issuance
verification
./ssikit.sh velocity onboard -h
./ssikit.sh velocity onboard organization <org-file>
./ssikit.sh velocity onboard organization organization.json
{
    "profile":
    {
        "name": "WaltID",
        "location":
        {
            "countryCode": "AT",
            "regionCode": "W"
        },
        "founded": "2021",
        "logo": "https://images.squarespace-cdn.com/content/v1/609c0ddf94bcc0278a7cbdb4/d7a7bc88-c700-4efe-a95f-8d3086bccb9d/Walt.id_Logo_round.png?format=1500w"
    },
    "serviceEndpoints":
    [
        {
            "id": "#credential-agent-operator-1",
            "serviceEndpoint": "https://agent.velocity.walt.id",
            "type": "VlcCredentialAgentOperator_v1"
        },
        {
            "id": "#credential-agent-inspector-1",
            "serviceEndpoint": "https://agent.velocity.walt.id",
            "type": "VlcInspector_v1"
        },
        {
            "id": "#credential-agent-issuer-1",
            "serviceEndpoint": "https://agent.velocity.walt.id",
            "type": "VlcCareerIssuer_v1",
            "credentialTypes":
            [
                "OpenBadgeCredential",
                "EducationDegree",
                "CurrentEmploymentPosition",
                "PastEmploymentPosition",
                "Badge",
                "Certification",
                "Course",
                "Assessment",
                "AssessmentDec2020",
                "VaccinationCertificate-Apr2021",
                "CourseRegistrationV1.0",
                "CourseCompletionV1.0",
                "CourseAttendanceV1.0",
                "EducationDegreeRegistrationV1.0",
                "EducationDegreeStudyV1.0",
                "EducationDegreeGraduationV1.0",
                "CertificationV1.0",
                "LicenseV1.0",
                "OpenBadgeV1.0",
                "AssessmentV1.0",
                "EmploymentCurrentV1.0",
                "EmploymentPastV1.0",
                "VerifiableCredential",
                "ComprehensiveLearnerRecord",
                "CourseRegistrationV1.1",
                "CourseCompletionV1.1",
                "CourseAttendanceV1.1",
                "EducationDegreeRegistrationV1.1",
                "EducationDegreeStudyV1.1",
                "EducationDegreeGraduationV1.1",
                "CertificationV1.1",
                "LicenseV1.1",
                "AssessmentV1.1",
                "EmploymentCurrentV1.1",
                "EmploymentPastV1.1",
                "BadgeV1.1",
                "OpenBadgeV2.0",
                "OpenBadgeV2.1"
            ]
        }
    ]
}
{
    "id": "did:ion:org-did",
    "didDoc":
    {
        "@context":
        [
            "https://www.w3.org/ns/did/v1",
            {
                "@base": "<did:ion:org-did>"
            }
        ],
        "id": "<did:ion:org-did>",
        "verificationMethod":
        [
            {
                "id": "#vc-signing-key-1",
                "type": "EcdsaSecp256k1VerificationKey2019",
                "controller": "",
                "publicKeyJwk":
                {
                    "crv": "secp256k1",
                    "x": "<x-value>",
                    "y": "<y-value>",
                    "kty": "EC"
                }
            },
            {
                "id": "#eth-account-key-1",
                "type": "EcdsaSecp256k1VerificationKey2019",
                "controller": "",
                "publicKeyJwk":
                {
                    "crv": "secp256k1",
                    "x": "<x-value>",
                    "y": "<y-value>",
                    "kty": "EC"
                }
            },
            {
                "id": "#exchange-key-1",
                "type": "EcdsaSecp256k1VerificationKey2019",
                "controller": "",
                "publicKeyJwk":
                {
                    "crv": "secp256k1",
                    "x": "<x-value>",
                    "y": "<y-value>",
                    "kty": "EC"
                }
            }
        ],
        "assertionMethod":
        [
            "#vc-signing-key-1",
            "#eth-account-key-1",
            "#exchange-key-1"
        ],
        "service":
        [
            {
                "type": "VlcCredentialAgentOperator_v1",
                "id": "#credentialagent-1",
                "serviceEndpoint": "https://agent.samplevendor.com/acme"
            },
            {
                "type": "VlcCareerIssuer_v1",
                "id": "#issuer-1",
                "serviceEndpoint": "https://agent.samplevendor.com/acme",
                "credentialTypes":
                [
                    "CertificationV1.1",
                    "LicenseV1.1",
                    "CourseCompletionV1.1",
                    "EducationDegreeGraduationV1.1",
                    "EmploymentCurrentV1.1",
                    "EmploymentPastV1.1"
                ]
            },
            {
                "type": "VlcInspector_v1",
                "id": "#inspector-1",
                "serviceEndpoint": "https://agent.samplevendor.com/acme"
            }
        ]
    },
    "profile":
    {
        "name": "Test Organization",
        "location":
        {
            "countryCode": "US",
            "regionCode": "NY"
        },
        "logo": "https://images.squarespace-cdn.com/content/v1/609c0ddf94bcc0278a7cbdb4/d7a7bc88-c700-4efe-a95f-8d3086bccb9d/Walt.id_Logo_round.png?format=1500w",
        "website": "http://www.organization.com",
        "cntactEmail": "contact@example.com",
        "founded": "2021-01-01",
        "registrationNumbers":
        [
            {
                "authority": "DunnAndBradstreet",
                "number": "1",
                "uri": "uri://uri"
            }
        ],
        "id": "<did:ion:org-did>",
        "verifiableCredentialJwt": "http://registrar.velocitynetwork.foundation/api/v0.6/organizations/<did:ion:org-did>/resolve-vc/<token>",
        "permittedVelocityServiceCategory":
        [
            "CredentialAgentOperator",
            "Issuer",
            "Inspector"
        ]
    },
    "keys":
    [
        {
            "id": "#vc-signing-key-1",
            "purposes":
            [
                "ISSUING_METADATA"
            ],
            "key": "<key-value>",
            "publicKey": "<key-value>",
            "algorithm": "SECP256K1",
            "encoding": "hex",
            "controller": "<did:ion:org-did>"
        },
        {
            "id": "#eth-account-key-1",
            "purposes":
            [
                "DLT_TRANSACTIONS"
            ],
            "key": "<key-value>",
            "publicKey": "<key-value>",
            "algorithm": "SECP256K1",
            "encoding": "hex",
            "controller": "<did:ion:org-did>"
        },
        {
            "id": "#exchange-key-1",
            "purposes":
            [
                "EXCHANGES"
            ],
            "key": "<key-value>",
            "publicKey": "<key-value>",
            "algorithm": "SECP256K1",
            "encoding": "hex",
            "controller": "<did:ion:org-did>"
        }
    ],
    "authClients":
    [
        {
            "type": "auth0",
            "clientType": "cao-node-client",
            "clientId": "<id-value>",
            "clientSecret": "<secret-value>",
            "serviceId": "#credentialagent-1"
        }
    ]
}
./ssikit.sh velocity onboard tenant -h
./ssikit.sh velocity onboard tenant tenant.json
{
    "serviceIds":
    [
        "#credential-agent-operator-1",
        "#credential-agent-inspector-1",
        "#credential-agent-issuer-1"
    ],
    "did": "<did:ion:org-did>",
    "keys":
    [
        {
            "purposes":
            [
                "DLT_TRANSACTIONS"
            ],
            "algorithm": "SECP256K1",
            "encoding": "hex",
            "kidFragment": "#eth-account-key-1",
            "key": "<key-value>"
        },
        {
            "purposes":
            [
                "EXCHANGES"
            ],
            "algorithm": "SECP256K1",
            "encoding": "hex",
            "kidFragment": "#exchange-key-1",
            "key": "<key-value>"
        },
        {
            "purposes":
            [
                "ISSUING_METADATA"
            ],
            "algorithm": "SECP256K1",
            "encoding": "hex",
            "kidFragment": "#vc-signing-key-1",
            "key": "<key-value>"
        }
    ]
}
{
    "id": "634d9327aa4dc9cf44a8f37a",
    "createdAt": "2022-10-14T17:38:47.231Z"
}
./ssikit.sh velocity onboard disclosure -h
./ssikit.sh velocity onboard disclosure -i did:ion:1234567890 disclosure.json
{
    "types":
    [
        {
            "type": "EmailV1.0"
        }
    ],
    "vendorEndpoint": "integrated-issuing-identification",
    "vendorDisclosureId": "MSFT0001",
    "purpose": "Id Check",
    "duration": "16m",
    "termsUrl": "https://www.velocityexperiencecenter.com/terms-and-conditions-vnf",
    "activationDate": "2021-02-16T00:00:01Z",
    "identityMatchers":
    {
        "vendorUserIdIndex": 0,
        "rules":
        [
            {
                "valueIndex": 0,
                "path":
                [
                    "$.emails"
                ],
                "rule": "pick"
            }
        ]
    }
}
{
    "types":
    [
        {
            "type": "EmailV1.0"
        }
    ],
    "vendorDisclosureId": "MSFT0001",
    "vendorEndpoint": "integrated-issuing-identification",
    "identityMatchers":
    {
        "rules":
        [
            {
                "path":
                [
                    "$.emails"
                ],
                "rule": "pick",
                "valueIndex": 0
            }
        ],
        "vendorUserIdIndex": 0
    },
    "purpose": "Id Check",
    "duration": "16m",
    "termsUrl": "https://www.velocityexperiencecenter.com/terms-and-conditions-vnf",
    "activationDate": "2021-02-16T00:00:01.000Z",
    "id": "634d9625b6b4b8ab66563fab",
    "createdAt": "2022-10-14T17:51:33.769Z",
    "updatedAt": "2022-10-14T17:51:33.769Z"
}
tenant management
disclosure management
cheqd architecture infrastructure
onboard-cmd
organization-cmd
tenant-cmd
disclosure-cmd
cheqd universal registrar
onboarding
DID acquisition
tenant management
disclosure management
offer management
credential management

Inspection

Velocity credential verification is available with the verify command:

./ssikit.sh velocity verify -h

E.g. Verify credential.

./ssikit.sh velocity verify -i did:ion:1234567890 credential.jwt checks.json
eyJqd2siOnsia3R5IjoiRUMiLCJleHQiOnRydWUsImtleV9vcHMiOlsidmVyaWZ5Il0sIngiOiJVd3V5Y2lfMUJNa05DdVkwZ0lPWFZ3ZDZTOXBPMldOUWpsdUVXbWd3TGNBIiwieSI6Ik5vYlp6WFh1VUtNQmIwU1ZpaGo2cG10RWY2cXd4Y1FwSHlOMmRwSHBjM1kiLCJjcnYiOiJQLTI1NiJ9LCJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJpZCI6Ijc1NmZlMWIzLWYwOGEtNDgxYy05ZWFlLTU2ZWIwMGI2NWQ1NyIsInR5cGUiOlsiSWREb2N1bWVudCIsIlZlcmlmaWFibGVDcmVkZW50aWFsIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImZpcnN0TmFtZSI6eyJsb2NhbGl6ZWQiOnsiZW4iOiJBZGFtIn19LCJsYXN0TmFtZSI6eyJsb2NhbGl6ZWQiOnsiZW4iOiJTbWl0aCJ9fSwia2luZCI6IkRyaXZlcnNMaWNlbnNlIiwiYXV0aG9yaXR5Ijp7ImxvY2FsaXplZCI6eyJlbiI6IkNhbGlmb3JuaWEgRE1WIn19LCJsb2NhdGlvbiI6eyJjb3VudHJ5Q29kZSI6IlVTIiwicmVnaW9uQ29kZSI6IkNBIn0sImRvYiI6eyJkYXkiOjIwLCJtb250aCI6NiwieWVhciI6MTk2Nn0sImlkZW50aXR5TnVtYmVyIjoiMTIzMTAzMTIzMTIiLCJkZWZhdWx0Ijp0cnVlfX0sInN1YiI6ImFkYW0uc21pdGhAZXhhbXBsZS5jb20iLCJhdWQiOiIgIiwiaXNzIjoiNzU2ZmUxYjMtZjA4YS00ODFjLTllYWUtNTZlYjAwYjY1ZDU3IiwianRpIjoiNzU2ZmUxYjMtZjA4YS00ODFjLTllYWUtNTZlYjAwYjY1ZDU3IiwiaWF0IjoxNjIwMTI4NjgyLCJuYmYiOjE2MjAxMjg2ODJ9.iqbGO5LfYzUmvesVSCquWHekbC-z3VCvls156zsNnmvz7y6sFtcH7lH0IkRNwljGQQvsce50O7RG06QOSnMS4g
{
    "TRUSTED_ISSUER": "SELF_SIGNED",
    "UNREVOKED": "PASS",
    "UNEXPIRED": "NOT_APPLICABLE",
    "UNTAMPERED": "PASS"
}
Verification result:
true
{
    "TRUSTED_ISSUER": "SELF_SIGNED",
    "UNREVOKED": "PASS",
    "UNEXPIRED": "NOT_APPLICABLE",
    "UNTAMPERED": "PASS"
}

Verify VC

Verify credentials using the CLI

Verify credentials using the REST API

Issue VC

Issue VC using the CLI

Issue VC using the REST API

cheqd

A Cosmos based blockchain

Intro

Getting Started

Create DID

did:cheqd requires keys of type Ed25519. They can be either:

  • imported into SSIKit - and further used when creating the did by specifying the kid

  • or created with SSIKit

    • standalone

    • by default when running the did-create command

Using the CLI | Command Line Interface

E.g. create a did:cheqd on testnet and also create the key for it by default

ssikit did create -m cheqd -n testnet

or

ssikit did create -m cheqd --network testnet

Using the REST API

Create a did:cheqd document on the test or main network

POST https://core.ssikit.walt.id/v1/did/create/

Request Body

Name
Type
Description

method*

String

did schema (use cheqd)

network

String

mainnet or testnet

did:cheqd:testnet:dc3a71fb-be38-4145-a80a-dfc67628ab53

Issuing

Velocity issuance commands are available under issue command as follows:

  • offer management

  • credential management

./ssikit.sh velocity issue -h

Offer management

Before being able to issue verifiable credentials, the credential data needs to be prepared. Offers represent the way to set up credential data. Basically, an offer is a credential that has not been signed. The offer management functions can be accessed from the command:

./ssikit.sh velocity issue offer -h

Currently available functions are:

  • create offer

E.g. Create an offer.

./ssikit.sh velocity issue -i did:velocity:0xd4df29726d500f9b85bc6c7f1b3c021f16305692 -d 61966dfc4732da2ea0e64826 -m adam.smith@example.com
{
    "type":
    [
        "PastEmploymentPosition"
    ],
    "credentialSubject":
    {
        "vendorUserId": "adam.smith@example.com",
        "company": "did:velocity:0xd4df29726d500f9b85bc6c7f1b3c021f16305692",
        "companyName":
        {
            "localized":
            {
                "en": "Microsoft Corporation"
            }
        },
        "title":
        {
            "localized":
            {
                "en": "Director, Communications (HoloLens & Mixed Reality Experiences)"
            }
        },
        "startMonthYear":
        {
            "month": 10,
            "year": 2010
        },
        "endMonthYear":
        {
            "month": 5,
            "year": 2022
        },
        "location":
        {
            "countryCode": "US",
            "regionCode": "MA"
        },
        "description":
        {
            "localized":
            {
                "en": "Big Data, AI, Hybrid, IoT, Datacenter, Mixed Reality/HoloLens, D365, Power Platform - all kinds of fun stuff!!!"
            }
        }
    },
    "offerCreationDate": "2020-08-04T21:13:32.019Z",
    "offerExpirationDate": "2021-08-04T21:13:32.019Z",
    "offerId": "ptIQrgxaicFX0QPVf_Z1L"
}
{
    "type":
    [
        "PastEmploymentPosition"
    ],
    "credentialSubject":
    {
        "vendorUserId": "adam.smith@example.com",
        "company": "did:velocity:0xd4df29726d500f9b85bc6c7f1b3c021f16305692",
        "companyName":
        {
            "localized":
            {
                "en": "Microsoft Corporation"
            }
        },
        "title":
        {
            "localized":
            {
                "en": "Director, Communications (HoloLens & Mixed Reality Experiences)"
            }
        },
        "startMonthYear":
        {
            "month": 10,
            "year": 2010
        },
        "endMonthYear":
        {
            "month": 5,
            "year": 2022
        },
        "location":
        {
            "countryCode": "US",
            "regionCode": "MA"
        },
        "description":
        {
            "localized":
            {
                "en": "Big Data, AI, Hybrid, IoT, Datacenter, Mixed Reality/HoloLens, D365, Power Platform - all kinds of fun stuff!!!"
            }
        }
    },
    "offerCreationDate": "2020-08-04T21:13:32.019Z",
    "offerExpirationDate": "2021-08-04T21:13:32.019Z",
    "offerId": "ptIQrgxaicFX0QPVf_Z1L",
    "id": "634d9aacb6b4b8ab66563fac",
    "createdAt": "2022-10-14T18:10:52.726Z",
    "updatedAt": "2022-10-14T18:10:52.726Z",
    "exchangeId": "634d9a9caa4dc9cf44a8f37f",
    "issuer":
    {
        "id": "did:velocity:0x6872fedef46b03e9863a56859a1cdb45648907f7"
    }
}

Credential management

Credential management functions include:

  • issue credential

./ssikit.sh velocity issue credential -h

E.g. Issue credential.

./ssikit.sh velocity issue credential -i did:velocity:0x6872fedef46b03e9863a56859a1cdb45648907f7 -c PastEmploymentCredential credential-data.json
{
    "type":
    [
        "PastEmploymentPosition"
    ],
    "credentialSubject":
    {
        "vendorUserId": "adam.smith@example.com",
        "company": "did:velocity:0xd4df29726d500f9b85bc6c7f1b3c021f16305692",
        "companyName":
        {
            "localized":
            {
                "en": "Microsoft Corporation"
            }
        },
        "title":
        {
            "localized":
            {
                "en": "Director, Communications (HoloLens & Mixed Reality Experiences)"
            }
        },
        "startMonthYear":
        {
            "month": 10,
            "year": 2010
        },
        "endMonthYear":
        {
            "month": 5,
            "year": 2022
        },
        "location":
        {
            "countryCode": "US",
            "regionCode": "MA"
        },
        "description":
        {
            "localized":
            {
                "en": "Big Data, AI, Hybrid, IoT, Datacenter, Mixed Reality/HoloLens, D365, Power Platform - all kinds of fun stuff!!!"
            }
        }
    },
    "offerCreationDate": "2020-08-04T21:13:32.019Z",
    "offerExpirationDate": "2021-08-04T21:13:32.019Z",
    "offerId": "ptIQrgxaicFX0QPVf_Z1L"
}
velocity-network://issue?request_uri=https://stagingagent.velocitycareerlabs.io/api/holder/v0.6/org/did:velocity:0x6872fedef46b03e9863a56859a1cdb45648907f7/issue/get-credential-manifest?exchange_id=634d9a9caa4dc9cf44a8f37f&credential_types=PastEmploymentPosition
verify-cmd

on how to verify VCs using the CLI.

on how to verify VCs using REST.

on how to issue VCs using the CLI.

on how to issue VCs using REST.

The is a Cosmos SDK-based blockchain that facilitates the exchange of trusted, verifiable data off-chain , using on-chain identifiers (Decentralised Identifiers ''). The cheqd Network leverages the method and enables to be written to the network, associated with a DID and controlled using the verification methods in the DID Document. Through this approach, the cheqd Network is able to natively support all major credential types: VC-JWT, JSON-LD and AnonCreds across an array of enterprise SDKs. cheqd also has a dedicated token, $CHEQ, used for identity writes to the network, voting in a decentralised governance framework as well as for various payment flows between verifiers, holders and issuers of Verifiable Credentials.

- Create your first did:cheqd

- Issue your first Verifiable Credential based on a did:cheqd

- Verify your Credential based on a did:cheqd

DID cheqd scheme is supported with the same functionality as the other DID schemes (see Decentralized Identifiers for command-line interface or #decentralised-identifiers for REST API). Creating a did:cheqd will also onboard with the . The created DID can be checked at or using the .

on how to build and run the SSI-Kit's CLI.

on how to build and run the SSI-Kit's REST API.

issue-cmd
offer-cmd
credential-cmd
cheqd Network
Verifiable Credentials
DIDs
cheqd DID
linked resources
Create DID
Issue VC
Verify VC
Universal Registrar
https://resolver.cheqd.net/1.0/identifiers/{your-did}
Universal Resolver
Detailed instructions
Detailed instructions
Detailed instructions
Detailed instructions
Detailed instructions
Detailed instructions

Parameterized Policies

Some policies may require a parameter or argument for execution. The parameter is indicated in the policy list output, together with the expected data type.

Using A Parameterized Policy

My First VC

In this tutorial, our fictional SSI Use-Case involves Emma, a recent university graduate, who wants to apply for a job. The employer requires proof of her academic credentials. To achieve this, she will use her Verifiable Degree Credential issued by her university.

Where we start:

Utilizing the walt.id SSI-Kit's REST-API, we will provide Emma with the Verifiable Degree Credential by creating a DID for both the university (Issuer) and Emma (Holder). After that, the employer (Verifier) will authenticate the Degree Credential using the associated DIDs.

What we do:

Running the SSI-Kit

Make sure you have Docker or a JDK 16 build environment including Gradle installed on your machine

Pull the docker container directly from docker hub and run the project

docker run -p 7000-7004:7000-7004 -itv $(pwd)/data:/app/data waltid/ssikit serve -b 0.0.0.0

This will create a folder called data in your current directory as storage for the VC, DIDs, Keys and other things which need to be stored in order to provide all the functionality.

  1. Clone the project

git clone https://github.com/walt-id/waltid-ssikit.git

2. Change the folder

cd waltid-ssikit/

3. Run the project

The first time you run the command you will be asked to built the project. You can confirm the prompt.

./ssikit.sh serve

Creating the DIDs

curl -X 'POST' \
  'http://localhost:7002/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "{method}"
}'

Body Parameters method: [string] method of the did. Value can be one of key, web, ebsi, iota, cheqd, jwk Example

curl -X 'POST' \
  'http://localhost:7002/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "key"
}'

Create DIDs for the University (Issuer) and Emma (Holder) using the example above twice. Make sure to save the DIDs somewhere, as we will be needing them later for the issuance of the credential.

Issuing a Verifiable University Degree Credential

{
  "type": ["VerifiableCredential", "UniversityDegreeCredential"],
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "id": "http://example.gov/credentials/3732",
  "issuer": {
    "id": "did:example:456"
  },
  "issuanceDate" : "2023-03-21T15:35:08Z",
  "issued" : "2023-03-21T15:35:08Z",
  "validFrom" : "2023-03-21T15:35:08Z",
  "credentialSubject": {
    "id": "did:example:123",
    "degree": {
      "name": "Bachelor of Science and Arts",
      "type": "BachelorDegree"
    }
  },
  "proof" : {
    "type" : "JsonWebSignature2020",
    "creator" : "did:example:456",
    "created" : "2023-03-21T15:35:08Z",
    "verificationMethod" : "did:example:456",
    "jws" : "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..zDI3Wc6jWN7288tlat3LohWsoZiIkBODvlmLPtCy49vUZxpv1NYtZNCMd5Z4RxVQSSbkjPSDzDfAmlOBLhUZBg"
  }
}

This Verifiable Diploma includes the following key elements:

  • "type": Defines the credential as both a general "VerifiableCredential" and a more specific "UniversityDegreeCredential".

  • "@context": Provides references to the necessary standards and examples for interpreting the credential.

  • "id": A unique identifier for the credential.

  • "issuer": The DID of the university issuing the diploma (e.g., "did:example:456").

  • "issuanceDate": The timestamp indicating when the credential was issued.

  • "issued": The timestamp indicating when the credential was issued.

  • "validFrom": The timestamp indicating from when the credential is valid.

  • "credentialSubject": Contains the DID of the credential holder (Emma - e.g., "did:example:123") and the details of the degree earned, such as the name of the degree and its type.

  • proof: The proof object contains the digital signature and related information that is used to verify the authenticity and integrity of the Verifiable Credential.

    • type: "JsonWebSignature2020" indicates the cryptographic suite used for generating the digital signature. In this case, it's the JSON Web Signature (JWS) standard based on the Ed25519 signature algorithm.

    • creator: "did:example:456" is the DID of the entity that created the digital signature, in this case, the issuer of the Verifiable Credential.

    • created: "2023-03-21T15:35:08Z" is the timestamp when the digital signature was created. It is in the ISO 8601 format.

    • verificationMethod: "did:example:456" is the identifier for the public key or cryptographic method used to verify the digital signature.

    • jws: is the actual digital signature (JWS) generated using the Ed25519 algorithm. This signature is used to verify the authenticity and integrity of the Verifiable Credential.

Now that we know how the credential looks like, let's issue it.

Issue

curl -X 'POST' \
  'http://localhost:7001/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "{template type}",
  "config": {
    "issuerDid": "{issuerDid}",
    "subjectDid": "{subjectDid}",
    "proofType": "{proofType}"
  },
  "credentialData": {
    "id": "{subjectDid}",
    "degree": {
      "name": "{Degree name}",
      "type": "{Degree type}"
    }
  }
}'

Body Parameters

  • templateId: [string] The identifier of the template used for issuing a Verifiable Credential. This template defines the structure and format of the credential being issued.

  • config: [object] Contains configuration parameters for the issuance process.

    • issuerDid: [string] The DID of the entity issuing the credential (University).

    • subjectDid: [string] The DID of the entity receiving the credential (Emma).

    • proofType: [string] Specifies the format and cryptographic algorithm used for the digital signature of the Verifiable Credential. E.g. LD_PROOF

  • credentialData: [object] Contains the actual data of the credential being issued.

    • credentialSubject: [object] Holds the information about the credential holder and the earned degree.

      • id: [string] The DID of the credential holder, identical to the subjectDid in the config object.

      • degree: [object] Contains details of the degree earned by the credential holder.

        • name: [string] The name of the earned degree (e.g., "Bachelor of Science and Arts").

        • type: [string] The type of the earned degree (e.g., "BachelorDegree").

Example:

curl -X 'POST' \
  'http://localhost:7001/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "UniversityDegree",
  "config": {
    "issuerDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "subjectDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "proofType": "LD_PROOF"
  },
  "credentialData": {
    "id": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "degree": {
      "name": "Bachelor of Science and Arts",
      "type": "BachelorDegree"
    }
  }
}'

Awesome, you just issued your first VC 🎉. Now Emma can use it to prove her academic credentials to her employer.

Verify The University Degree Credential

Emma needs to verify her academic credentials to her employer, which involves the following steps performed by the verifier (employer):

  1. Verify the credential's digital signature: The Verifier checks if the digital signature on the credential is valid and has been signed by the Issuer's private key. This ensures that the credential was indeed issued by the claimed Issuer.

  2. Check the Issuer's DID: The Verifier validates the Issuer's Decentralized Identifier (DID) by resolving it to a DID Document. This step helps confirm the Issuer's identity and retrieve their public key for signature verification.

  3. Verify the Holder's DID: The Verifier checks the credential's subject (i.e., the Holder) by validating their DID. This ensures that the credential was issued to the correct entity and prevents unauthorized use of the credential.

  4. Check the credential's status: (Not for our use-case) The Verifier may also query the credential's status on a registry, ledger, or another trusted source. This step helps confirm whether the credential is still valid or has been revoked by the Issuer.

  5. Check the credential's integrity: The Verifier confirms that the credential data has not been tampered with since issuance. This is typically done by comparing the signed data with the credential's content to detect any discrepancies.

  6. Verify the credential's issuance and expiration dates: The Verifier checks the issuance and expiration dates (if applicable) of the credential to ensure it was issued within the specified time frame and is still valid.

curl -X 'POST' \
  'http://localhost:7003/v1/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "policies": [
    {
      "policy": "SignaturePolicy"
    }
  ],
  "credentials": [{Emma's Credential}]
}'

Example

curl -X 'POST' \
  'http://localhost:7003/v1/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "policies": [
    {
      "policy": "SignaturePolicy"
    }
  ],
  "credentials": [
    {
      "type": [
        "VerifiableCredential",
        "UniversityDegreeCredential"
      ],
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1",
        "https://w3id.org/security/suites/jws-2020/v1"
      ],
      "id": "urn:uuid:a78bcd04-183b-4e57-91fe-954cb8dc6a04",
      "issuer": {
        "id": "did:key:z6MkgjQxcoh1JWXMgG7xPNeBaqUXWu42LAW8G5KmE7J6d1CG"
      },
      "issuanceDate": "2023-03-21T15:54:16Z",
      "issued": "2023-03-21T15:54:16Z",
      "validFrom": "2023-03-21T15:54:16Z",
      "credentialSubject": {
        "id": "did:key:z6MkgjQxcoh1JWXMgG7xPNeBaqUXWu42LAW8G5KmE7J6d1CG",
        "degree": {
          "name": "Bachelor of Science and Arts",
          "type": "BachelorDegree"
        }
      },
      "degree": {
        "name": "Bachelor of Science and Arts",
        "type": "BachelorDegree"
      },
      "proof": {
        "type": "JsonWebSignature2020",
        "creator": "did:key:z6MkgjQxcoh1JWXMgG7xPNeBaqUXWu42LAW8G5KmE7J6d1CG",
        "created": "2023-03-21T15:54:16Z",
        "verificationMethod": "did:key:z6MkgjQxcoh1JWXMgG7xPNeBaqUXWu42LAW8G5KmE7J6d1CG#z6MkgjQxcoh1JWXMgG7xPNeBaqUXWu42LAW8G5KmE7J6d1CG",
        "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..9LiRH2WXqAWIgA54PJ3Qt6ECOSykuU2b_n7UTA-2otZqX-sNP79VgZ5cBlLZeUTis90pAtsRS5uoAblxWjwcDg"
      }
    }
  ]
}'

You have successfully issued and verified a Verifiable Credential. Great job!! Emma can start her new job 🎉 Where to go next?

Verification Policies

For verification of verifiable credentials, the SSI-Kit offers a wide range of predefined static and parameterized verification policies, which are ready-to-use and are designed for common use cases. For more complex verification, the creation of custom policies using a policy execution engine such as the Open Policy Agent can be used.

Static Verification Policies

Predefined and covering a variety of common use cases, enabling developers to verify credentials without having to dive into dynamic or custom policy creation and scripting languages. Some of these policies include SignaturePolicy, JsonSchemaPolicy, ValidFromBeforePolicy, ExpirationDateAfterPolicy, and more.

Parameterized Verification Policies

Parameterized policies are a type of policy that requires certain parameters or arguments for their execution.

Dynamic Verification Policies

Dynamic policies offer a more customized approach to credential verification, enabling even the most complex of use-cases. Policies can be created based on different policy engine languages.

Credential Templates

They are the blueprint on which Verifiable Credentials are issued, and we offer two variants:

Static Policies

Static verification policies are predefined for verifying credentials in standard use cases. The following lists out supported static policies by SSI-Kit along with their arguments

General policies

EBIS/ESSIF Specific Policies

GAIA-X specific policies

Advanced VC

Onboarding Emma to a Virtual Company, issuing custom credentials, and utilizing dynamic verification policies.

Where we start:

Using the walt.id SSI-Kit's REST API, we'll streamline access control within the company by

    • Confirm Emma's employment status

    • Assess her role within the company

    • Grant or deny access to specific areas on the company campus based on the above.

Running the SSI-Kit

Make sure you have Docker or a JDK 16 build environment including Gradle installed on your machine

Now with the SSI-Kit up and running, we can create the DID for the company, establishing its Digital Identity.

Establishing a Digital Identity (DID)

You have two options for creating a DID: executing a curl command or visiting the swagger docs. The custodian endpoint should be visible in the terminal after you have run the serve command, visit the endpoint to see the swagger docs.

Body Parameters method: [string] method of the did. Value can be one of key, web, ebsi, iota, cheqd, jwk Example

Creating an EmployeeID Template

Let's create one for an EmployeeID. The template will include the following properties:

  • id: Identifier for the employee

  • name: Name of the employee

  • role: Role or designation in the company

  • joiningDate: Date of joining the company

Saving the credential template

Path Parameters

  • id: The name for the credential template, which we will later reference during issuance. e.g. EmployeeID

Body Use the JSON structure from above as the body. Example

We can streamline the process of issuing a credential to Emma by utilizing the EmployeeID credential template. However, we also have the opportunity to further simplify the process using an additional feature: prefilling credential properties. This will be particularly beneficial as Emma likely won't be the only one receiving the Engineer role assignment. By creating a template where the Engineer role is prefilled, we can improve the issuance process.

EngineerEmployeeID Template

You can now also save this template and use it later for the issuance of our VC, or use the one we created before and provide the value for the role attribute during issuance.

Issuing a Verifiable Credential to Emma

Body Parameters

  • templateId: [string] The identifier of the template used for issuing a Verifiable Credential. In our case this would be the EmployeeID or EngineerEmployeeID template.

  • config: [object] Contains configuration parameters for the issuance process.

    • issuerDid: [string] The DID of the entity issuing the credential (University).

    • subjectDid: [string] The DID of the entity receiving the credential (Emma).

    • proofType: [string] Specifies the format and cryptographic algorithm used for the digital signature of the Verifiable Credential. E.g. LD_PROOF

    • statusType: [statusType] Specifies if the credential should be issued with status and the type of the status. Options StatusList2021Entry or SimpleCredentialStatus2022

  • credentialData: [object] Contains the actual data of the credential being issued.

    • credentialSubject: [object] Holds the information about the employee as described in the EmployeeID credential template.

The id in the credential subject we don't need to provide as this will be prefilled automatically with the DID of Emma.

Example EmployeeID:

Example EngineerEmployeeID:

Now we can use the issued VC in the company campus verification system.

Authenticating with Door Access System

To successfully authorize access, our authentication system needs to verify four crucial elements regarding the Verifiable Credential presented during the verification process:

  1. Confirm the signature of the Verifiable Credential to ensure it's legitimate.

  2. Ascertain the credential's validity by validating its current status, ensuring it has not expired or been revoked.

  3. Verify that the issuer is indeed our company, thereby eliminating any fraudulent issuers.

  4. Evaluate whether the role of the employee, as indicated on the credential, authorizes them to access the desired area.

To facilitate successful verification, we will use Verification Policies. For the initial two cases, which are relatively common, we can utilize our built-in policies, namely SignaturePolicy and CredentialStatusPolicy. These policies essentially verify that the signature is authentic and that the status is still valid.

Creating Custom Policies - IsCompany

Make sure to replace {issuerDID} with the DID of your issuer (company)

Creating Custom Policies - IsRole

This custom policy holds greater flexibility, as it accepts an argument containing a 'role' property. This property is then cross-verified with the role present in the Verifiable Credential. Alternatively, the role can be hardcoded, and the policy can be renamed accordingly, such as IsEngineer, similar to the IsCompany policy.

Saving the policies

Path parameters:

  • policyName: [string] Name of the policy, e.g. IsCompany

Query parameters:

  • update: [boolean] Specifies if existing policy with same name should be overridden (if mutable)

  • downloadPolicy: [boolean] When using an URL to reference the to created policy. Downloads and/or saves the policy definition locally, rather than keeping the reference to the original URL\

Body

  • name: [string] Policy name, must not conflict with existing policies

  • description: [string] Optional policy description

  • input: [JSON] Input JSON object for rego query, which can be overridden/extended on verification. Can be a JSON string or JSON file

  • policy: [URL, REGO] Whole Policy or URL to policy definition.

  • dataPath: [JSON path] JSON path to the data in the credential which should be verified, default: "$" (whole credential object)

  • policyQuery: [string] The query string in the policy engine language. Defaults to "data.system.main".

  • policyEngine: [string] Policy engine type, default: OPA. Options, OPA

  • applyToVC: [boolean] Apply/Don't apply to verifiable credentials (default: apply)

  • applyToVP: [boolean] Apply/Don't apply to verifiable presentation (default: don't apply)

Using the endpoint above, you can save both policies.

Verifying the credential with all policies

Now with the custom policies created, we will use those and the two predefined ones to verify Emma's credential and enable access.

Body

  • policies: [array] A list of policy definitions to verify against

    • policy: [string] The name/id of the policy

    • argument: [JSON] The argument needed by the policy (optional)

  • credentials: [array] An array of credentials in JWT, or LD_PROOF format

Congratulations, you've reached the finish line! 🎉 You have skillfully utilized an array of features to bring this use case to life. Now, you have the opportunity to explore further and deepen your understanding of the concepts introduced today. Happy building!

Next Steps

Please refer to the to exectute the command successfully. Let's verify a credential using the parameterless SignaturePolicy and ChallengePolicy which taks a paramter.

ssikit vc verify \
-p SignaturePolicy \
-p ChallengePolicy='{"challenges": ["362df5ec-37ab-46a7-aa71-767d8f277b69"]}' \
src/test/resources/rego/VerifiableId.json

Flags

  • -p, --policy: Verification policy. Can be specified multiple times. By default, SignaturePolicy is used. To specify a policy argument (if required), use the format PolicyName='{"myParam": "myValue", ...}', to specify the JSON object directly, or PolicyName=path/to/arg.json, to read the argument from a JSON file.

The Challange Policy

It checks that the challenge of the credential is one of the challenges given in the ChallengePolicyArg argument.

Please refer to the to serve the API. Using the /v1/verify enpoint in the Auditor API to verify a credential

curl -X 'POST' \
  'http://127.0.0.1:7003/v1/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '{
  "policies": [
    {
      "policy": "SignaturePolicy"
    }, 
    {
      "policy": "ChallengePolicy",
      "argument": {
        "challenges": [ "362df5ec-37ab-46a7-aa71-767d8f277b69" ]
      }
    }
  ],
  "credentials": [
     {
      "@context" : [ "https://www.w3.org/2018/credentials/v1" ],
      [...]
    }
  ]
}'

Body

{
  "policies": [
    {
      "policy": "SignaturePolicy"
    }, 
    {
      "policy": "ChallengePolicy",
      "argument": {
        "challenges": [ "362df5ec-37ab-46a7-aa71-767d8f277b69" ]
      }
    }
  ],
  "credentials": [
     {
      "@context" : [ "https://www.w3.org/2018/credentials/v1" ],
      [...]
    }
  ]
}
  • policies: [array] A list of policy definitions to verify against

    • policy: [string] The name/id of the policy

    • argument: [JSON] The argument needed by the policy (if required)

  • credentials: [array] An array of credentials in JWT, or LD_PROOF format

- for Emma + University

to Emma

from Emma

Now with the project up and running, visit the URL displayed in your terminal. We will use it, to create our first DID (Decentralised Identifier). If you want to learn more about DIDs, visit the

Using the DIDs from the previous step, we will now issue a University Degree Credential. To issue the credential, we will be using the . Below you find the final credential structure. Verifiable Diploma

To verify the credential, we will be using the endpoint.

Exploring ssi-kit Capabilities - Familiarize yourself with the various features of ssi-kit by reviewing the or section.

- Discover the potential applications of Verification Policies and how they can be useful for your particular use-case.

- Visit our ecosystem overview page to explore the different ecosystems (did:methods) that we support.

for the most relevant use-cases

to help you issue use-case specific verifiable credentials when the prebuild ones are not enough. You can also watch our to custom templates.

Name
Description
Argument
Name
Description
Argument
Name
Description
Argument

In this tutorial, we will expand on the by now onboarding Emma to a virtual company. During the onboarding, Emma will receive an EmployeeID credential, which will be based on a custom credential template using the status property. With that, you learn about two more concepts; Custom credential templates and the status property. The credential will also have Emma's role as a property, which can then be checked with a dynamic verification policy, another new concept.

: The company will be set up as the issuer through its own Digital Identity (DID).

: This template will be used for generating verifiable credentials for employees.

: Emma, an employee, will be issued a Verifiable Credential, making her the holder.

: The system, acting as the Verifier, will:

Pull the docker container directly from docker hub and run the project

This will create a folder called data in your current directory as storage for the VC, DIDs, Keys and other things which need to be stored in order to provide all the functionality.

  1. Clone the project

2. Change the folder

3. Run the project

The first time you run the command you will be asked to built the project. You can confirm the prompt.

Create one DID for the company using the command above. In case you don't have done the My First VC tutorial and still have the DID for Emma, create another one for her. Make sure to save both, as we will be needing them later for the issuance of the EmployeID. You can also use to see all previously created DIDs.

The SSI-Kit supports the creation of , which are blueprints that establish reusable data structures based on which credentials can be issued.

In order to issue Emma's EmployeeID VC, we will use one of the credential templates. Additionally, we will include a credential status so that we have the option to revoke the credential if Emma leaves the company without needing to remove it from her ownership. For more information on credential status and the types we support, read .

For the additional cases, we will create custom policies, leveraging the Open Policy Agent (OPA) Engine and the REGO language. You can learn more about it .

Please install the Open Policy Agent as described , to ensure seamless verification.

- Dive deeper into credential templates and what you can do with them

- Learn more about the credential status property and what is enables.

- Explore our pre-build templates and learn more about how to build and leverage custom ones using OPA (Open Policy Agent) and the Rego language.

SSI-Kit setup section
SSI-Kit setup section
walt.id Custodian API
general section.
Signatory API endpoint
Auditor API
REST API
Command Line
Understanding Verification Policies
Exploring Supported Ecosystems
Run the SSI-Kit and expose API
Create DIDs
Issue Credential
Verify Credential

SignaturePolicy

Verifies the signature of the W3C Verifiable credential.

None

JsonSchemaPolicy

Verifies against the associated JSON schema. Note that the attribute credentialSchema must be set and the JSON schema must be accessible by the http URL.

None

ValidFromBeforePolicy

Verifies the credentials based on their valid-from date

None

ExpirationDateAfterPolicy

Verifies the credentials based on their expiration date

None

ChallengePolicy

Verifies challenge

ChallengePolicyArg, which contains specific challenges to check against.

VpTokenClaimPolicy

Verify verifiable presentation by OIDC/SIOPv2 VP token claim.

VpTokenClaim

CredentialStatusPolicy

Verifies credentials based on their status

None

EbsiTrustedSchemaRegistryPolicy

Verify by EBSI Trusted Schema Registry. Checks performed:

  • credential schema id has the correct format

None

EbsiTrustedIssuerDidPolicy

Verify by trusted issuer did. Checks performed:

  • issuer did is resolvable against EBSI

None

EbsiTrustedIssuerRegistryPolicy

Verify by EBSI Trusted Issuer Registry record. Checks performed:

  • issuer has any record on trusted registry having an authorization claim matching the VC schema

  • issuer's TIR record contains a VerifiableId credential

  • the authorized claim record (from p.1) has the type provided as argument to the policy

  • issuer's accreditation is valid - verifies against EbsiTrustedIssuerAccreditationPolicy

EbsiTrustedIssuerRegistryPolicyArg

EbsiTrustedSubjectDidPolicy

Verify by trusted subject did. Checks performed:

  • subject did is resolvable against EBSI

None

EbsiTrustedIssuerAccreditationPolicy

Verify by issuer's authorized claims. Checks performed:

  • fetches the attribute specified by the termsOfUse property

  • checks whether the credential stored as the attribute body has the required accreditation claims to match the current VC schema

None

IssuedDateBeforePolicy

Verify by issuance date.

None

GaiaxTrustedPolicy

Verify Gaiax trusted fields.

None

GaiaxSDPolicy

Verify Gaiax SD fields.

None

docker run -p 7000-7004:7000-7004 -itv $(pwd)/data:/app/data waltid/ssikit serve -b 0.0.0.0
git clone https://github.com/walt-id/waltid-ssikit.git
cd waltid-ssikit/
./ssikit.sh serve
curl -X 'POST' \
  'http://localhost:7002/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "{method}"
}'
curl -X 'POST' \
  'http://localhost:7002/did/create' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "key"
}'
{
  "type": ["VerifiableCredential", "EmployeeID"],
  "credentialSubject": {
    "id": "",
    "name": "",
    "role": "",
    "joiningDate": ""
  }
}
curl -X 'POST' \
  'http://127.0.0.1:7001/v1/templates/{id}' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json' \
  -d '{credentialTemplate}'
curl -X 'POST' \
  'http://127.0.0.1:7001/v1/templates/EmployeeID' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": ["VerifiableCredential", "EmployeeID"],
    "credentialSubject": {
        "id": "",
        "name": "",
        "role": "",
        "joiningDate": ""
    }
}'
{
    "type": ["VerifiableCredential", "EmployeeID"],
    "credentialSubject": {
        "id": "",
        "name": "",
        "role": "Engineer",
        "joiningDate": ""
    }
}
curl -X 'POST' \
  'http://localhost:7001/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "{template type}",
  "config": {
    "issuerDid": "{issuerDid}",
    "subjectDid": "{subjectDid}",
    "proofType": "{proofType}",
    "statusType": "{statusType}"
  },
  "credentialData": {
    "id": "{subjectDID}",
    "name": "{name}",
    "role": "{role}",
    "joiningDate": "{joiningDate}"
  }
}'
curl -X 'POST' \
  'http://localhost:7001/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "EmployeeID",
  "config": {
    "issuerDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "subjectDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "proofType": "LD_PROOF",
    "statusType": "StatusList2021Entry"
  },
  "credentialData": {
    "name": "Emma",
    "role": "Engineer",
    "joiningDate": "2023-06-28"
  }
}'
curl -X 'POST' \
  'http://localhost:7001/v1/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "templateId": "EngineerEmployeeID",
  "config": {
    "issuerDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "subjectDid": "did:key:z6MkmE21F2dAHkM71tnYdBEGaSvnPpxBFZYi2wtzYbTwqvgK",
    "proofType": "LD_PROOF",
    "statusType": "StatusList2021Entry"
  },
  "credentialData": {
    "name": "Emma",
    "joiningDate": "2023-06-28"
  }
}'
package system

default main = false

main {
    input.credentialData.issuer == {issuerDID}
}
package system

default main = false

main {
    input.parameter.role == input.credentialData.credentialSubject.role
}
curl -X 'POST' \
  'http://127.0.0.1:7003/v1/create/{{policyName}}?update=true&downloadPolicy=true' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "IsCompany",
    "description": "Test",
    "input": {},
    "policy": "package system

default main = false

main {
    input.credentialData.issuer == \"did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z\"
}",
}
",
    "dataPath": "$",
    "policyQuery": "data.system.main",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}'
{
    "name": "MyCustomPolicy",
    "description": "Test",
    "input": {},
    "policy": "package system

               default main = false

               main {
                 input.credentialData.issuer == \"did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z\"
    }",
    "dataPath": "$",
    "policyQuery": "data.system.main",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}
curl -X 'POST' \
  'http://127.0.0.1:7003/v1/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '{
    "policies": [
        {
            "policy": "SignaturePolicy"
        },
        {
            "policy": "CredentialStatusPolicy"
        },
        {
            "policy": "IsRole",
            "argument": {"role": "Engineer"}
        },
        {
            "policy": "IsCompany"
        }
    ],
    "credentials": [{
  "type" : [ "VerifiableCredential", "EngineerEmployeeID" ],
  "@context" : [ "https://www.w3.org/2018/credentials/v1", "https://w3id.org/security/suites/jws-2020/v1" ],
  "id" : "urn:uuid:ae9cf1f3-8609-4685-9928-5073b6990af4",
  "issuer" : "did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z",
  "issuanceDate" : "2023-06-28T13:55:15Z",
  "issued" : "2023-06-28T13:55:15Z",
  "validFrom" : "2023-06-28T13:55:15Z",
  "credentialSubject" : {
    "id" : "did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z",
    "name" : "Emma",
    "role" : "Engineer",
    "joiningDate" : "2023-06-28"
  },
  "credentialStatus" : {
    "id" : "http://127.0.0.1:7001/v1/credentials/status/revocation#2",
    "statusListCredential" : "http://127.0.0.1:7001/v1/credentials/status/revocation",
    "statusListIndex" : "2",
    "statusPurpose" : "revocation",
    "type" : "StatusList2021Entry"
  },
  "proof" : {
    "type" : "JsonWebSignature2020",
    "created" : "2023-06-28T13:55:15Z",
    "verificationMethod" : "did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z#z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z",
    "jws" : "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9.._uFLlXHpNgFsUJFwahcIh_VeLsps8n5ZaifMMvAMqmOkESWN1eoJNNkGfAYY_R185ia-qkKRKwb2rsNzPUcvAA"
  }
}]
}
'
{
    "policies": [
        {
            "policy": "SignaturePolicy"
        },
        {
            "policy": "CredentialStatusPolicy"
        },
        {
            "policy": "IsRole",
            "argument": {"role": "Engineer"}
        },
        {
            "policy": "IsCompany"
        }
    ],
    "credentials": [
      {... credential ... }
    ]
}
Learn more about Static Verification Policies.
Learn more about Parameterized Verification Polices.
Learn more about Dynamic Verification Policies.
"My First VC" tutorial
credential templates
our guide
here
here
Credential Templates
Credential Status
Verification Policies
Prebuild templates
intro video
Custom Templates
Establishing a Digital Identity (DID)
Creating an EmployeeID Template
Issuing a Verifiable Credential to Emma
Authenticating with Door Access System
the list DID endpoint
Introduction to Verification Policies
Introduction to Credential Templates

Dynamic/Custom Policies

SSI Kit supports custom policies, written in any of the supported policy engine languages. A dynamic policy can either be executed on the fly (if all required parameters are provided) or saved under a specific name for later reference in the verify command or REST API.

Getting Started

Creating Dynamic Policies

Example of a Rego policy

A simple Rego policy that takes a credential subject as input and verifies the subject DID against a given parameter would look like this:

This policy file is located in the SSIKit test resources: src/test/resources/rego/subject-policy.rego

Executing a Policy On-The-Fly

Saving a Dynamic Policy

You can save the policy by name, which simplifies its usage in future verifications.

Flags:

  • -n, --name: Policy name, must not conflict with existing policies

  • -D, --description: Optional policy description

  • -p, --policy: Path or URL to policy definition. e.g.: rego file for OPA policy engine

  • -i, --input: Input JSON object for rego query, which can be overridden/extended on verification. Can be a JSON string or JSON file

  • -d, --data-path: JSON path to the data in the credential which should be verified, default: "$" (whole credential object)

  • -s, --save-policy: Downloads and/or saves the policy definition locally, rather than keeping the reference to the original URL

  • -f, --force: Override existing policy with that name (static policies cannot be overridden!)

  • -e, --policy-engine: Policy engine type, default: OPA. Options, OPA

  • --vc / --no-vc: Apply/Don't apply to verifiable credentials (default: apply)

  • --vp / --no-vp: Apply/Don't apply to verifiable presentations (default: don't apply)

Path parameters:

  • policyName: [string] Name of the policy, e.g. MyCustomPolicy

Query parameters:

  • update: [boolean] Specifies if existing policy with same name should be overridden (if mutable)

  • downloadPolicy: [boolean] When using an URL to reference the to created policy. Downloads and/or saves the policy definition locally, rather than keeping the reference to the original URL

Body

  • name: [string] Policy name, must not conflict with existing policies

  • description: [string] Optional policy description

  • input: [JSON] Input JSON object for rego query, which can be overridden/extended on verification. Can be a JSON string or JSON file

  • policy: [URL, REGO] Whole Policy or URL to policy definition.

  • dataPath: [JSON path] JSON path to the data in the credential which should be verified, default: "$" (whole credential object)

  • policyQuery: [string] The query string in the policy engine language. Defaults to "data.system.main".

  • policyEngine: [string] Policy engine type, default: OPA. Options, OPA

  • applyToVC: [boolean] Apply/Don't apply to verifiable credentials (default: apply)

  • applyToVP: [boolean] Apply/Don't apply to verifiable presentaion (default: don't apply)

Dynamic Policies | Data Classes

Dynamic Policy Argument

A dynamic policy requires an argument of the DynamicPolicyArg type, defined as follows:

The properties are as follows:

  • name: The policy name. Defaults to "DynamicPolicy".

  • description: An optional description of the policy.

  • input: A generic map (JSON object) holding the input data required by the policy. If no input is required, this can be an empty map.

  • policy: The policy definition. Can be a file path, URL, JSON Path (if policy is defined in a credential property), or the policy script directly.

  • dataPath: The path to the credential data to be verified. Defaults to the entire credential object ($). If you want to use only the credential subject as verification data, specify the JSON path like this: $.credentialSubject.

  • policyQuery: The query string in the policy engine language. Defaults to "data.system.main".

  • policyEngine: The engine used for policy execution. Defaults to OPA (Open Policy Agent).

  • applyToVC: Determines whether this policy should apply to verifiable credentials. Defaults to true.

  • applyToVP: Determines whether this policy should apply to verifiable presentations. Defaults to false.

Policy Execution and Input Data

The policy is executed by the specified policy engine, with the Open Policy Agent currently being the only supported engine. OPA receives an input object containing the dynamic policy's input parameter and the credential data configured in the policy argument.

The input object for the policy engine is structured as follows:

This structure allows the REGO policy definition to access the input properties as follows:

  • input.parameter: The input object defined in the DynamicPolicyArg's input property.

  • input.credentialData: The credential data selected by the JSON path provided in the DynamicPolicyArg's dataPath property.

Removing Dynamic Policies

Removing a Dynamic Policy

Selective Disclosure

Guide to SD-JWTs for selective disclosure; create, verify.

Concept

Selective Disclosure in Action

Using Dynamic Policies

Verification with a Dynamic Policy

Note: To use dynamic policies with Open Policy Agent, setup of the OPA Engine is required. Refer to the for more details.

- Learn how to create a dynamic policy via CLI or REST

- Learn how to verify a VC using a dynamic policy via CLI or REST

- Learn how to remove a dynamic policy via CLI or REST

- Examine data classes used internally.

Creating a Sample Policy using

Please refer to the to exectute the command successfully.

Please refer to the to exectute the command successfully. Example

Please refer to the to serve the API.

Please refer to the to exectute the command successfully.

  • -n, --name: name of the dynamic policy to remove

Please refer to the to serve the API.

Path parameters:

  • policyName: [string] Name of the policy to delete

- Learn about selective disclosure and its importance in the context of digital identity, and how SD-JWTs can be used for implementing it.

- Learn how to issue a Verifiable Credential using the SD-JWT format.

- Learn how to verify a Verifiable Credential using the SD-JWT format.

Once a dynamic policy has been saved with a specific name, as explained in , you can use it to verify Verifiable Credentials.

Please refer to the to exectute the command successfully.

  • -p, --policy: Verification policy. Can be specified multiple times. By default, SignaturePolicy is used. To specify a policy argument (if required), use the format PolicyName='{"myParam": "myValue", ...}', to specify the JSON object directly, or PolicyName=path/to/arg.json, to read the argument from a JSON file.

We can verify a credential with the SubjectPolicy and VerifiableId located in src/test/resources/rego/VerifiableId.json, which are provided when cloning the project, so no setup is needed.

Please refer to the to serve the API.

Body

  • policies: [array] A list of policy definitions to verify against

    • policy: [string] The name/id of the policy

    • argument: [JSON] The argument needed by the policy (optional)

  • credentials: [array] An array of credentials in JWT, or LD_PROOF format

package system

default main = false

main {
    input.parameter.user == input.credentialData.credentialSubject.id
}
ssikit vc policies create \
    -n "MyCustomPolicy" \
    -D "Verifies credential subject against a provided DID" \
    -p src/test/resources/rego/subject-policy.rego \
    -i '{ "user": "did:key:z6MkgERd8hghGSBndxduiXtUdbYmtbcX9TeNdAL2BAhvXoAp" }'
curl -X 'POST' \
  'http://127.0.0.1:7003/v1/create/{{policyName}}?update=true&downloadPolicy=true' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "MyCustomPolicy",
    "description": "Test",
    "input": {},
    "policy": "package system

default main = false

main {
    input.parameter.user == input.credentialData.credentialSubject.id
}
",
    "dataPath": "$",
    "policyQuery": "data.system.main",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}'
{
    "name": "MyCustomPolicy",
    "description": "Test",
    "input": {},
    "policy": "package system

               default main = false

               main {
                 input.parameter.user == input.credentialData.credentialSubject.id
               }",
    "dataPath": "$",
    "policyQuery": "data.system.main",
    "policyEngine": "OPA",
    "applyToVC": true,
    "applyToVP": true
}
data class DynamicPolicyArg (
    val name: String = "DynamicPolicy",
    val description: String? = null,
    val input: Map<String, Any?>,
    val policy: String,
    val dataPath: String = "\$",
    val policyQuery: String = "data.system.main",
    val policyEngine: PolicyEngineType = PolicyEngineType.OPA,
    val applyToVC: Boolean = true,
    val applyToVP: Boolean = false
)
data class PolicyEngineInput(
    val credentialData: Map<String, Any?>,
    val parameter: Map<String, Any?>?
)

SimpleCredentialStatus2022

SimpleCredentialStatus2022 is a credentialStatus method by which the status of a verifiable credential can be checked. When a credential is issued with a SimpleCredentialStatus2022 credentialStatus type, it gets assigned a non-delegated revocation base-token. In order to check the status or revoke the verifiable credential, a delegated revocation derived-token is used.

OPA Engine configuration
Create a dynamic policy
Use a dynamic policy
Remove a dynamic policy
Data classes
R
ego
ssikit vc verify -p DynamicPolicy='{ "policy": "src/test/resources/rego/subject-policy.rego", \
  "input": { "user": "did:key:z6MkgERd8hghGSBndxduiXtUdbYmtbcX9TeNdAL2BAhvXoAp" } }' \
  src/test/resources/rego/VerifiableId.json
SSI-Kit setup section
SSI-Kit setup section
SSI-Kit setup section
ssikit vc policies remove -n MyCustomPolicy
curl -X 'DELETE' \
  'http://127.0.0.1:7003/v1/delete/{{name}}' \
  -H 'accept: */*'
SSI-Kit setup section
SSI-Kit setup section
Intro
Issuing a SD-JWT Credential
Verifying a SD-JWT Credential
the previous section
ssikit vc verify \
  -p SubjectPolicy='{ "user": "did:key:z6MkgERd8hghGSBndxduiXtUdbYmtbcX9TeNdAL2BAhvXoAp" }' \
  src/test/resources/rego/VerifiableId.json
curl -X 'POST' \
  'http://127.0.0.1:7003/v1/verify' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -d '{
    "policies": [
        {
            "policy": "MyCustomPolicy",
            "argument": {
                "user": "did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z"
            }
        }
    ],
    "credentials": [
        "eyJraWQiOiJkaWQ6a2V5Ono2TWtyRnR6WVM1Ulc3NDh2dkFqQVJaNENZakJNdmVWOUxZZlNBRm92NDM5Qm04WiN6Nk1rckZ0ellTNVJXNzQ4dnZBakFSWjRDWWpCTXZlVjlMWWZTQUZvdjQzOUJtOFoiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJzdWIiOiJkaWQ6a2V5Ono2TWtyRnR6WVM1Ulc3NDh2dkFqQVJaNENZakJNdmVWOUxZZlNBRm92NDM5Qm04WiIsIm5iZiI6MTY4Nzg2NDU2NCwiaXNzIjoiZGlkOmtleTp6Nk1rckZ0ellTNVJXNzQ4dnZBakFSWjRDWWpCTXZlVjlMWWZTQUZvdjQzOUJtOFoiLCJpYXQiOjE2ODc4NjQ1NjQsInZjIjp7InR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJWZXJpZmlhYmxlQXR0ZXN0YXRpb24iLCJWZXJpZmlhYmxlSWQiXSwiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwiaWQiOiJ1cm46dXVpZDplMDY3ZDVmYy0zNWFlLTRkMGUtYTk1ZS03MzdmMGUwYzIzM2IiLCJpc3N1ZXIiOiJkaWQ6a2V5Ono2TWtyRnR6WVM1Ulc3NDh2dkFqQVJaNENZakJNdmVWOUxZZlNBRm92NDM5Qm04WiIsImlzc3VhbmNlRGF0ZSI6IjIwMjMtMDYtMjdUMTE6MTY6MDRaIiwiaXNzdWVkIjoiMjAyMy0wNi0yN1QxMToxNjowNFoiLCJ2YWxpZEZyb20iOiIyMDIzLTA2LTI3VDExOjE2OjA0WiIsImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vd2FsdC1pZC93YWx0aWQtc3Npa2l0LXZjbGliL21hc3Rlci9zcmMvdGVzdC9yZXNvdXJjZXMvc2NoZW1hcy9WZXJpZmlhYmxlSWQuanNvbiIsInR5cGUiOiJGdWxsSnNvblNjaGVtYVZhbGlkYXRvcjIwMjEifSwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6a2V5Ono2TWtyRnR6WVM1Ulc3NDh2dkFqQVJaNENZakJNdmVWOUxZZlNBRm92NDM5Qm04WiIsImN1cnJlbnRBZGRyZXNzIjpbIjEgQm91bGV2YXJkIGRlIGxhIExpYmVydMOpLCA1OTgwMCBMaWxsZSJdLCJkYXRlT2ZCaXJ0aCI6IjE5OTMtMDQtMDgiLCJmYW1pbHlOYW1lIjoiRE9FIiwiZmlyc3ROYW1lIjoiVGFtaW5vIiwiZ2VuZGVyIjoiRkVNQUxFIiwibmFtZUFuZEZhbWlseU5hbWVBdEJpcnRoIjoiSmFuZSBET0UiLCJwZXJzb25hbElkZW50aWZpZXIiOiIwOTA0MDA4MDg0SCIsInBsYWNlT2ZCaXJ0aCI6IkxJTExFLCBGUkFOQ0UifSwiZXZpZGVuY2UiOlt7ImRvY3VtZW50UHJlc2VuY2UiOlsiUGh5c2ljYWwiXSwiZXZpZGVuY2VEb2N1bWVudCI6WyJQYXNzcG9ydCJdLCJzdWJqZWN0UHJlc2VuY2UiOiJQaHlzaWNhbCIsInR5cGUiOlsiRG9jdW1lbnRWZXJpZmljYXRpb24iXSwidmVyaWZpZXIiOiJkaWQ6ZWJzaToyQTlCWjlTVWU2QmF0YWNTcHZzMVY1Q2RqSHZMcFE3YkVzaTJKYjZMZEhLblF4YU4ifV19LCJqdGkiOiJ1cm46dXVpZDplMDY3ZDVmYy0zNWFlLTRkMGUtYTk1ZS03MzdmMGUwYzIzM2IifQ.tyLqPczrzyRQQNBoR1z5fR9oA50XiT8IX9OpQY_1qLA71eInI71fFOulDsS9WuwfT2FjN5ugjihLaiRVx7OcAg"
    ]
}'
{
    "policies": [
        {
            "policy": "MyCustomPolicy",
            "argument": {
                "user": "did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z"
            }
        }
    ],
    "credentials": [
        "eyJraWQiOiJkaWQ6a2V5Ono2TWtyRnR6WVM1Ulc3NDh2dkFqQVJaNENZakJNdmVWOUxZZlNBRm92NDM5Qm04WiN6Nk1rckZ0ellTNVJXNzQ4dnZBakFSWjRDWWpCTXZlVjlMWWZTQUZvdjQzOUJtOFoiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJzdWIiOiJkaWQ6a2V5Ono2TWtyRnR6WVM1Ulc3NDh2dkFqQVJaNENZakJNdmVWOUxZZlNBRm92NDM5Qm04WiIsIm5iZiI6MTY4Nzg2NDU2NCwiaXNzIjoiZGlkOmtleTp6Nk1rckZ0ellTNVJXNzQ4dnZBakFSWjRDWWpCTXZlVjlMWWZTQUZvdjQzOUJtOFoiLCJpYXQiOjE2ODc4NjQ1NjQsInZjIjp7InR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJWZXJpZmlhYmxlQXR0ZXN0YXRpb24iLCJWZXJpZmlhYmxlSWQiXSwiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwiaWQiOiJ1cm46dXVpZDplMDY3ZDVmYy0zNWFlLTRkMGUtYTk1ZS03MzdmMGUwYzIzM2IiLCJpc3N1ZXIiOiJkaWQ6a2V5Ono2TWtyRnR6WVM1Ulc3NDh2dkFqQVJaNENZakJNdmVWOUxZZlNBRm92NDM5Qm04WiIsImlzc3VhbmNlRGF0ZSI6IjIwMjMtMDYtMjdUMTE6MTY6MDRaIiwiaXNzdWVkIjoiMjAyMy0wNi0yN1QxMToxNjowNFoiLCJ2YWxpZEZyb20iOiIyMDIzLTA2LTI3VDExOjE2OjA0WiIsImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vd2FsdC1pZC93YWx0aWQtc3Npa2l0LXZjbGliL21hc3Rlci9zcmMvdGVzdC9yZXNvdXJjZXMvc2NoZW1hcy9WZXJpZmlhYmxlSWQuanNvbiIsInR5cGUiOiJGdWxsSnNvblNjaGVtYVZhbGlkYXRvcjIwMjEifSwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6a2V5Ono2TWtyRnR6WVM1Ulc3NDh2dkFqQVJaNENZakJNdmVWOUxZZlNBRm92NDM5Qm04WiIsImN1cnJlbnRBZGRyZXNzIjpbIjEgQm91bGV2YXJkIGRlIGxhIExpYmVydMOpLCA1OTgwMCBMaWxsZSJdLCJkYXRlT2ZCaXJ0aCI6IjE5OTMtMDQtMDgiLCJmYW1pbHlOYW1lIjoiRE9FIiwiZmlyc3ROYW1lIjoiVGFtaW5vIiwiZ2VuZGVyIjoiRkVNQUxFIiwibmFtZUFuZEZhbWlseU5hbWVBdEJpcnRoIjoiSmFuZSBET0UiLCJwZXJzb25hbElkZW50aWZpZXIiOiIwOTA0MDA4MDg0SCIsInBsYWNlT2ZCaXJ0aCI6IkxJTExFLCBGUkFOQ0UifSwiZXZpZGVuY2UiOlt7ImRvY3VtZW50UHJlc2VuY2UiOlsiUGh5c2ljYWwiXSwiZXZpZGVuY2VEb2N1bWVudCI6WyJQYXNzcG9ydCJdLCJzdWJqZWN0UHJlc2VuY2UiOiJQaHlzaWNhbCIsInR5cGUiOlsiRG9jdW1lbnRWZXJpZmljYXRpb24iXSwidmVyaWZpZXIiOiJkaWQ6ZWJzaToyQTlCWjlTVWU2QmF0YWNTcHZzMVY1Q2RqSHZMcFE3YkVzaTJKYjZMZEhLblF4YU4ifV19LCJqdGkiOiJ1cm46dXVpZDplMDY3ZDVmYy0zNWFlLTRkMGUtYTk1ZS03MzdmMGUwYzIzM2IifQ.tyLqPczrzyRQQNBoR1z5fR9oA50XiT8IX9OpQY_1qLA71eInI71fFOulDsS9WuwfT2FjN5ugjihLaiRVx7OcAg",
        "{\n  \"type\" : [ \"VerifiableCredential\", \"VerifiableAttestation\", \"VerifiableId\" ],\n  \"@context\" : [ \"https://www.w3.org/2018/credentials/v1\", \"https://w3id.org/security/suites/jws-2020/v1\" ],\n  \"id\" : \"urn:uuid:ed0de88b-4df7-458d-9ed6-8caa07a02e2d\",\n  \"issuer\" : \"did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z\",\n  \"issuanceDate\" : \"2023-06-27T11:32:36Z\",\n  \"issued\" : \"2023-06-27T11:32:36Z\",\n  \"validFrom\" : \"2023-06-27T11:32:36Z\",\n  \"credentialSchema\" : {\n    \"id\" : \"https://raw.githubusercontent.com/walt-id/waltid-ssikit-vclib/master/src/test/resources/schemas/VerifiableId.json\",\n    \"type\" : \"FullJsonSchemaValidator2021\"\n  },\n  \"credentialSubject\" : {\n    \"id\" : \"did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z\",\n    \"currentAddress\" : [ \"1 Boulevard de la Liberté, 59800 Lille\" ],\n    \"dateOfBirth\" : \"1993-04-08\",\n    \"familyName\" : \"DOE\",\n    \"firstName\" : \"Tamino\",\n    \"gender\" : \"FEMALE\",\n    \"nameAndFamilyNameAtBirth\" : \"Jane DOE\",\n    \"personalIdentifier\" : \"0904008084H\",\n    \"placeOfBirth\" : \"LILLE, FRANCE\"\n  },\n  \"evidence\" : [ {\n    \"documentPresence\" : [ \"Physical\" ],\n    \"evidenceDocument\" : [ \"Passport\" ],\n    \"subjectPresence\" : \"Physical\",\n    \"type\" : [ \"DocumentVerification\" ],\n    \"verifier\" : \"did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN\"\n  } ],\n  \"proof\" : {\n    \"type\" : \"JsonWebSignature2020\",\n    \"created\" : \"2023-06-27T11:32:36Z\",\n    \"verificationMethod\" : \"did:key:z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z#z6MkrFtzYS5RW748vvAjARZ4CYjBMveV9LYfSAFov439Bm8Z\",\n    \"jws\" : \"eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..P_CJAzsdjsVzL5Zx2hnH3riuq5nhmlIYt8yRc21r1ZiuTMMWQ0Ugo0Ep85gtYjDwCDdS3FNVbDudz-fPqhXMAw\"\n  }\n}"
    ]
}
SSI-Kit setup section
SSI-Kit setup section
Intro to Selective Disclosure with VCs

Intro

Selective Disclosure allows holders to reveal only necessary information.

What is Selective Disclosure?

Selective disclosure enables a holder to choose which pieces of information contained in a Verifiable Credential will be revealed to a verifier, rather than being forced to reveal all the data present in a Verifiable Credential.

For example, Alice could now only share her age to verify being old enough to purchase products offered in an ecommerce shop, without revealing other personal information present in her Verifiable ID document used for verification. This allows for greater privacy and control over personal data.

The importance of Selective Disclosure

Selective disclosure is a critical aspect of SSI because it enables individuals to share only the minimum amount of personal information necessary to complete a transaction or interaction, while keeping the rest of their personal data private. This reduces the risk of identity theft and other types of fraud.

SD-JWTs: A Mechanism for Selective Disclosure

What is an SD-JWT

A Selective Disclosure JSON Web Token (SD-JWT) is a type of in which the claims in the body are hashed, making them unreadable without disclosure. By providing the necessary disclosures, the original values of the claims can be revealed.

How it works

When presenting a classical credential via JWT, claims are visible to the verifier in plain text. With an SD-JWT credential, claims are encrypted in a hashed format, making them unreadable. This allows the holder to choose which claims to reveal to the verifier by providing the plain text key-value pairs (known as disclosures) next to the SD-JWT. The verifier can then hash these disclosures and compare them to the values in the SD-JWT, verifying that the claim was part of the SD-JWT. Additionally, SD-JWTs also allow for decoy hashes to be included in the credential, which are dummy values to conceal the actual number of claims in the credential.

In the following section, we will see how to issue and verify SD-JWT credentials.

StatusList2021Entry

StatusList2021Entry is a credentialStatus method by which the status of a verifiable credential can be checked. The basic idea of it is each issued credential has a corresponding position in a bit-string (also called the status list), having a value of either 0 - not revoked, or 1 - revoked. This status list is published by the issuer as a verifiable credential with a type that includes StatusList2021Credential.

The StatusList2021Entry credentialStatus contains the following fields:

  • id - a URL identifying the status information for the verifiable credential

  • type - StatusList2021Entry

  • statusPurpose - the purpose of the status entry (typically revocation or suspension)

  • statusListIndex - the bit position of the credential within the bit-string

  • statusListCredential - the URL of the StatusList2021Credential credential that encapsulates the bit-string

e.g.

{
  "id": "https://example.com/credentials/status/3#94567",
  "type": "StatusList2021Entry",
  "statusPurpose": "revocation",
  "statusListIndex": "94567",
  "statusListCredential": "https://example.com/credentials/status/3"
}

StatusList2021Credential

The StatusList2021Credential is a verifiable credential that encapsulates the bit-string information about all the credentials ever issued. The following fields have to be explicitly provided:

  • id - (optional) the URL to this credential (should match the statusListCredential value from StatusList2021Entry)

  • type - should contain StatusList2021Credential

  • credentialSubject

    • type - StatusList2021

    • statusPurpose - the purpose of the status credential (StatusList2021Entry should match this value)

    • encodedList - the compressed and base64 encoded value of the bit-string

e.g.

{
  "id": "https://example.com/credentials/status/3",
  "type": ["VerifiableCredential", "StatusList2021Credential"],
  "credentialSubject": {
    "id": "https://example.com/status/3#list",
    "type": "StatusList2021",
    "statusPurpose": "revocation",
    "encodedList": "H4sIAAAAAAAAA-3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
  },
  "other-verifiable-credential-properties": {}
}

Credential Statuses

The credentialStatus property is used to identify the status of a verifiable credential. It is an optional property (meaning when it's missing, the credential is not subject to any status change), but when specified, it includes the following mandatory fields:

  • id - a URI which identifies a location for the credential's status

  • type - an arbitrary string which identifies the type of the credential status (typically revocation or suspension)

Depending on the type, a credentialStatus property can contain additional fields, according to its model specification.

Verifying a SD-JWT Credential

Verifier requests, holder shares selective disclosures, verifier verifies hashes and signature.

SD-JWT Credential Verification Process

  1. Selective Disclosure Sharing: During the verification process, the verifier asked for a certain set of claims. The selective disclosure sharing mechanism allows the holder then to only share does require claims through sending the whole SD-JWT plus the disclosures which are needed for verification. This process therefore helps with privacy by not revealing more identity information than what's specifically requested.

  2. Hash Comparison and Tamper Check: The verifier then compares the hashed values of the shared disclosures with the values present in the SD-JWT. If the hashed values match, the verifier can be confident that the shared values haven't been tampered with and are actually part of the SD-JWT.

  3. Transfer Format: Transferring the credential from holder to verifier happens through the sharing of the SD-JWT with the concatenated disclosures which were chosen to be revealed using the ~ sign. An example of this format would be:

eyJraWQiOiI5MmJlMTAzYjRkZmY0OGYxYmE5ODc4ZGQyNmZhZjcxZSIsImN0eSI6ImNyZWRlbnRpYWwtY2xhaW1zLXNldCtqc29uIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRWREU0EifQ.eyJjcmVkZW50aWFsU2NoZW1hIjp7ImlkIjoiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3dhbHQtaWQvd2FsdGlkLXNzaWtpdC12Y2xpYi9tYXN0ZXIvc3JjL3Rlc3QvcmVzb3VyY2VzL3NjaGVtYXMvVmVyaWZpYWJsZUlkLmpzb24iLCJ0eXBlIjoiRnVsbEpzb25TY2hlbWFWYWxpZGF0b3IyMDIxIn0sImV2aWRlbmNlIjpbeyJkb2N1bWVudFByZXNlbmNlIjpbIlBoeXNpY2FsIl0sInZlcmlmaWVyIjoiZGlkOmVic2k6MkE5Qlo5U1VlNkJhdGFjU3B2czFWNUNkakh2THBRN2JFc2kySmI2TGRIS25ReGFOIiwiZXZpZGVuY2VEb2N1bWVudCI6WyJQYXNzcG9ydCJdLCJ0eXBlIjpbIkRvY3VtZW50VmVyaWZpY2F0aW9uIl0sInN1YmplY3RQcmVzZW5jZSI6IlBoeXNpY2FsIn1dLCJpc3N1YW5jZURhdGUiOiIyMDIxLTA4LTMxVDAwOjAwOjAwWiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7InBlcnNvbmFsSWRlbnRpZmllciI6IjA5MDQwMDgwODRIIiwiZmlyc3ROYW1lIjoiSmFuZSIsIl9zZCI6WyJuNWRYOEVpTUNoQ1hBR0o3elZCM1duQjc4Y3lBVFp3T1hwVkpCTUdOUzhzIiwiemFxMTNsa2lHLTd2am90SFppM0psSmhwS2JtUjFTVnV6Q3pLYVZYOUZRUSIsInhyYjdTOFZsNlctb0dMaVVQcTVlMmplVFpKVk5mYmRtNW9KNjd0VlVQem8iLCJwT0Jmb3hmQndqQUNPbXZ4aTNUSTc0RDN4Y2FwZS1RWVlGeUNPZEpPel9VIiwiRm1ZcmFmbWotUW9lbE1sSkQtVTN2OVgwS3hXTkZwelhwRl9McVc2dkZ0byJdLCJwbGFjZU9mQmlydGgiOiJMSUxMRSwgRlJBTkNFIiwiZ2VuZGVyIjoiRkVNQUxFIiwiZmFtaWx5TmFtZSI6IkRPRSIsImlkIjoiZGlkOmVic2k6MkFFTUFxWFdLWU11MUpIUEFnR2NnYTRkeHU3VGhnZmdOOTVWeUpCSkdaYlNKVXRwIiwibmFtZUFuZEZhbWlseU5hbWVBdEJpcnRoIjoiSmFuZSBET0UiLCJjdXJyZW50QWRkcmVzcyI6WyIxIEJvdWxldmFyZCBkZSBsYSBMaWJlcnTDqSwgNTk4MDAgTGlsbGUiXX0sIl9zZF9hbGciOiJzaGEtMjU2IiwiaWQiOiJ1cm46dXVpZDozYWRkOTRmNC0yOGVjLTQyYTEtODcwNC00ZTRhYTUxMDA2YjQiLCJ2YWxpZEZyb20iOiIyMDIxLTA4LTMxVDAwOjAwOjAwWiIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJWZXJpZmlhYmxlQXR0ZXN0YXRpb24iLCJWZXJpZmlhYmxlSWQiXSwiaXNzdWVkIjoiMjAyMS0wOC0zMVQwMDowMDowMFoiLCJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJpc3N1ZXIiOiJkaWQ6ZWJzaToyQTlCWjlTVWU2QmF0YWNTcHZzMVY1Q2RqSHZMcFE3YkVzaTJKYjZMZEhLblF4YU4ifQ.5TZ1n6iDHtW3lnKA_7ofSQ-BWyvEr39LThGdIc1OMgUejG6JF6blGkTqcoaQABQJKq6pFgkhjrYcpDG8QcObDA~
WyJXeS11VjJDa216SmJ4NGtjeTJQWjF3IiwiZGF0ZU9mQmlydGgiLCIxOTkzLTA0LTA4Il0~WyJXeS11VjJDa216SmJ4NGtjeTJQWjF3IiwiZGF0ZU9mQmlydGgiLCIxOTkzLTA0LTA4Il0

Verification in Action

Using either the CLI, Kotlin or REST option, you can start verifying your SD-JWT credential.

Creating a SD-JWT Credential Presentation

We create a presentation to provide the verifier with the holder's credentials for verification. The presentation can include data from multiple credentials, making verification easier as only one interaction is required. We provide the holder DID and the disclosures to create a presentation, which we can then present to a verifier, via the present command. Example Command

ssikit vc present \
-i did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a \
-c 234235 \
--sd credentialSubject \
--sd credentialSubject.dateOfBirth \
vc.txt

Options:

  • -i, --holder-did: DID of the holder (owner of the VC)

  • -c, --challange: Challenge to be used in the LD proof

  • --sd, --selective-disclosure: Path to selectively disclosed fields, in a simplified JsonPath format. Can be specified multiple times. By default NONE of the sd fields are disclosed, for multiple credentials, the path can be prefixed with the index of the presented credential, e.g. "credentialSubject.familyName", "0.credentialSubject.familyName", "1.credentialSubject.dateOfBirth". other options

  • --sd-all-for: Selects all selective disclosures for the credential at the specified index to be disclosed. Overrides --sd flags!

  • --sd-all: Selects all selective disclosures for all presented credentials to be disclosed.

Example Response

eyJraWQiOiJkaWQ6a2V5Ono2TWt0b3BSZ0Nvb0M1TGJqUlVzNmI2WWg3UjVtTkZURW15TG1TWVpRZDVMbTE0YSN6Nk1rdG9wUmdDb29DNUxialJVczZiNlloN1I1bU5GVEVteUxtU1laUWQ1TG0xNGEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJzdWIiOiJkaWQ6a2V5Ono2TWt0b3BSZ0Nvb0M1TGJqUlVzNmI2WWg3UjVtTkZURW15TG1TWVpRZDVMbTE0YSIsIm5iZiI6MTY4NjY1NjQxMSwiaXNzIjoiZGlkOmtleTp6Nk1rdG9wUmdDb29DNUxialJVczZiNlloN1I1bU5GVEVteUxtU1laUWQ1TG0xNGEiLCJ2cCI6eyJ0eXBlIjpbIlZlcmlmaWFibGVQcmVzZW50YXRpb24iXSwiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwiaWQiOiJ1cm46dXVpZDo1MzQ0YWZmMi0wN2ZiLTRiZTktYmM3Yi0xZjFlZWM1NTNhMDUiLCJob2xkZXIiOiJkaWQ6a2V5Ono2TWt0b3BSZ0Nvb0M1TGJqUlVzNmI2WWg3UjVtTkZURW15TG1TWVpRZDVMbTE0YSIsInZlcmlmaWFibGVDcmVkZW50aWFsIjpbImV5SnJhV1FpT2lKa2FXUTZhMlY1T25vMlRXdDBiM0JTWjBOdmIwTTFUR0pxVWxWek5tSTJXV2czVWpWdFRrWlVSVzE1VEcxVFdWcFJaRFZNYlRFMFlTTjZOazFyZEc5d1VtZERiMjlETlV4aWFsSlZjelppTmxsb04xSTFiVTVHVkVWdGVVeHRVMWxhVVdRMVRHMHhOR0VpTENKMGVYQWlPaUpLVjFRaUxDSmhiR2NpT2lKRlpFUlRRU0o5LmV5SnpkV0lpT2lKa2FXUTZhMlY1T25vMlRXdDBiM0JTWjBOdmIwTTFUR0pxVWxWek5tSTJXV2czVWpWdFRrWlVSVzE1VEcxVFdWcFJaRFZNYlRFMFlTSXNJbTVpWmlJNk1UWTROalkxTmpNMU1Td2lhWE56SWpvaVpHbGtPbXRsZVRwNk5rMXJkRzl3VW1kRGIyOUROVXhpYWxKVmN6WmlObGxvTjFJMWJVNUdWRVZ0ZVV4dFUxbGFVV1ExVEcweE5HRWlMQ0pwWVhRaU9qRTJPRFkyTlRZek5URXNJblpqSWpwN0luUjVjR1VpT2xzaVZtVnlhV1pwWVdKc1pVTnlaV1JsYm5ScFlXd2lMQ0pXWlhKcFptbGhZbXhsUVhSMFpYTjBZWFJwYjI0aUxDSldaWEpwWm1saFlteGxTV1FpWFN3aVFHTnZiblJsZUhRaU9sc2lhSFIwY0hNNkx5OTNkM2N1ZHpNdWIzSm5Mekl3TVRndlkzSmxaR1Z1ZEdsaGJITXZkakVpWFN3aWFXUWlPaUoxY200NmRYVnBaRG94TW1GaE5qUmpZeTAyTnpnekxUUTJZV0l0T0dWaU1TMWlPV1UyTkRkaVpHVTFOek1pTENKcGMzTjFaWElpT2lKa2FXUTZhMlY1T25vMlRXdDBiM0JTWjBOdmIwTTFUR0pxVWxWek5tSTJXV2czVWpWdFRrWlVSVzE1VEcxVFdWcFJaRFZNYlRFMFlTSXNJbWx6YzNWaGJtTmxSR0YwWlNJNklqSXdNak10TURZdE1UTlVNVEU2TXprNk1URmFJaXdpYVhOemRXVmtJam9pTWpBeU15MHdOaTB4TTFReE1Ub3pPVG94TVZvaUxDSjJZV3hwWkVaeWIyMGlPaUl5TURJekxUQTJMVEV6VkRFeE9qTTVPakV4V2lJc0ltTnlaV1JsYm5ScFlXeFRZMmhsYldFaU9uc2lhV1FpT2lKb2RIUndjem92TDNKaGR5NW5hWFJvZFdKMWMyVnlZMjl1ZEdWdWRDNWpiMjB2ZDJGc2RDMXBaQzkzWVd4MGFXUXRjM05wYTJsMExYWmpiR2xpTDIxaGMzUmxjaTl6Y21NdmRHVnpkQzl5WlhOdmRYSmpaWE12YzJOb1pXMWhjeTlXWlhKcFptbGhZbXhsU1dRdWFuTnZiaUlzSW5SNWNHVWlPaUpHZFd4c1NuTnZibE5qYUdWdFlWWmhiR2xrWVhSdmNqSXdNakVpZlN3aVpYWnBaR1Z1WTJVaU9sdDdJbVJ2WTNWdFpXNTBVSEpsYzJWdVkyVWlPbHNpVUdoNWMybGpZV3dpWFN3aVpYWnBaR1Z1WTJWRWIyTjFiV1Z1ZENJNld5SlFZWE56Y0c5eWRDSmRMQ0p6ZFdKcVpXTjBVSEpsYzJWdVkyVWlPaUpRYUhsemFXTmhiQ0lzSW5SNWNHVWlPbHNpUkc5amRXMWxiblJXWlhKcFptbGpZWFJwYjI0aVhTd2lkbVZ5YVdacFpYSWlPaUprYVdRNlpXSnphVG95UVRsQ1dqbFRWV1UyUW1GMFlXTlRjSFp6TVZZMVEyUnFTSFpNY0ZFM1lrVnphVEpLWWpaTVpFaExibEY0WVU0aWZWMHNJbDl6WkNJNld5SlFjWFI1UmpaWU4yVTJWVGR5UkU0d2JsTkJYMXBpVEZOTk5VNDVlVXcxYkZOUVlYWXdNa05NZUVaVklsMTlMQ0pxZEdraU9pSjFjbTQ2ZFhWcFpEb3hNbUZoTmpSall5MDJOemd6TFRRMllXSXRPR1ZpTVMxaU9XVTJORGRpWkdVMU56TWlmUS4wb2QxNFI5ckxsejBuaFJSY19HU3RxZ1g4eE5YSjk4Y3JsdWRiYmN5UUFMdUJyRC1CNnZwS2kzbzlBWmIwNGpOZ0FWanp1SVhKWUYweUpNOWdLLVlCUX5XeUpqUTBKbFZDMTVlV05HVUVjeWEyeDFia0V3T0Zobklpd2laR0YwWlU5bVFtbHlkR2dpTENJd0lsMH5XeUl6TTBOcWJYaDNibkZQTkY5WFVtWnZOMGxUV1ZWUklpd2lZM0psWkdWdWRHbGhiRk4xWW1wbFkzUWlMSHNpYVdRaU9pSmthV1E2YTJWNU9ubzJUV3QwYjNCU1owTnZiME0xVEdKcVVsVnpObUkyV1dnM1VqVnRUa1pVUlcxNVRHMVRXVnBSWkRWTWJURTBZU0lzSW1OMWNuSmxiblJCWkdSeVpYTnpJanBiSWxacFpXNXVZU0pkTENKbVlXMXBiSGxPWVcxbElqb2lRbUYxYldGdWJpSXNJbVpwY25OMFRtRnRaU0k2SWxSaGJXbHVieUlzSW1kbGJtUmxjaUk2SWsxaGJHVWlMQ0p1WVcxbFFXNWtSbUZ0YVd4NVRtRnRaVUYwUW1seWRHZ2lPaUpLWVc1bElFUlBSU0lzSW5CbGNuTnZibUZzU1dSbGJuUnBabWxsY2lJNklqQTVNRFF3TURnd09EUklJaXdpY0d4aFkyVlBaa0pwY25Sb0lqb2lUWFZ1YVdOb0lpd2lYM05rSWpwYklrSlNaWGczVFRSaWMxcHdTVEJCY0V4cVpFUjNRM05KTFd0MVJWZDJNbFpPYVdGVk5VMDVaR0ZzTkRnaVhYMWR-Il19LCJpYXQiOjE2ODY2NTY0MTEsIm5vbmNlIjoiMjM0MjM1IiwianRpIjoidXJuOnV1aWQ6NTM0NGFmZjItMDdmYi00YmU5LWJjN2ItMWYxZWVjNTUzYTA1In0.bLCEF-1BoXn2IKx53MJ27JxBk3bI_waDEk4Gb6qZycmHxx0UqzQt3zfUdGcRadrmOUtnoDKc9pgJOAz4NJFzBQ

Parseing the presentation to JSON

Using the parse command, you can print the presenation as a JSON object.

ssikit vc parse -r -c ata/vc/presented/vp-1686656411530.json

Options:

  • -r: Recursively parse credentials in presentation

  • -c: Credential content or file path

Verifying SD-JWT Presentation

We can check the validity of the presentation by providing the verify command with it. Use the storage location printed at the end of the last command.

Example Command

ssikit vc verify data/vc/presented/vp-1686656411530.json

Example Output

Results:

SignaturePolicy:	 passed
Verified:		 true

coming soon

Demo

Issuing a SD-JWT Credential

Learn about issuing SD-JWT credentials which includes hashing, creating disclosures and adding decoy hashes

SD-JWT Credential Issuance Process

  1. Credential Creation: The issuer first creates the credential, as usual.

  2. Conversion to SD-JWT Credential: The issuer then transforms the credential into an SD-JWT. This is done by hashing all or only a subset of claims, adding decoy hashes, and preparing disclosures. At the end, the SD-JWT credential can contain plain-text claims next to disclosable ones.

  3. Claim Hashing: The claim is transformed into a disclosure, which is a plain-text representations of the claim, by concatenating the attribute name and value, then prefixing it with a salt. The salt prevents attackers from guessing plain-text values via dictionary attacks. This is then converted to a base64 string, which will represent the disclosure. For example, the disclosure may look like this (salt + attribute name + value): [ “dC12Y2xpYi9tYXN0ZXI”, “given_name”, “John” ]. The disclosure is then put into a hash function, and the result gets included in the SD-JWT.

  4. Adding Decoy Hashes: At this point, decoy hashes are also added to the SD-JWT. These decoy hashes are essentially dummy values that help conceal the actual number of claims a credential holds. By using decoy hashes, the issuer can prevent potential observers from determining how many claims are contained within the credential based on the number of hashes.

  5. SD-JWT Credential Transfer to Holder: The issuer sends the SD-JWT and all disclosures to the holder. Because the holder now has the SD-JWT credential as well as all the disclosures, he can read the entire content of the credential. This allows the holder to decide which disclosures to send alongside the SD-JWT in a transaction with a verifier.

  6. Transfer Format: On transfer, the SD-JWT is shared with the concatenated disclosures using the ~ sign. An example of this format would be:

eyJraWQiOiI5MmJlMTAzYjRkZmY0OGYxYmE5ODc4ZGQyNmZhZjcxZSIsImN0eSI6ImNyZWRlbnRpYWwtY2xhaW1zLXNldCtqc29uIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRWREU0EifQ.eyJjcmVkZW50aWFsU2NoZW1hIjp7ImlkIjoiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3dhbHQtaWQvd2FsdGlkLXNzaWtpdC12Y2xpYi9tYXN0ZXIvc3JjL3Rlc3QvcmVzb3VyY2VzL3NjaGVtYXMvVmVyaWZpYWJsZUlkLmpzb24iLCJ0eXBlIjoiRnVsbEpzb25TY2hlbWFWYWxpZGF0b3IyMDIxIn0sImV2aWRlbmNlIjpbeyJkb2N1bWVudFByZXNlbmNlIjpbIlBoeXNpY2FsIl0sInZlcmlmaWVyIjoiZGlkOmVic2k6MkE5Qlo5U1VlNkJhdGFjU3B2czFWNUNkakh2THBRN2JFc2kySmI2TGRIS25ReGFOIiwiZXZpZGVuY2VEb2N1bWVudCI6WyJQYXNzcG9ydCJdLCJ0eXBlIjpbIkRvY3VtZW50VmVyaWZpY2F0aW9uIl0sInN1YmplY3RQcmVzZW5jZSI6IlBoeXNpY2FsIn1dLCJpc3N1YW5jZURhdGUiOiIyMDIxLTA4LTMxVDAwOjAwOjAwWiIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7InBlcnNvbmFsSWRlbnRpZmllciI6IjA5MDQwMDgwODRIIiwiZmlyc3ROYW1lIjoiSmFuZSIsIl9zZCI6WyJuNWRYOEVpTUNoQ1hBR0o3elZCM1duQjc4Y3lBVFp3T1hwVkpCTUdOUzhzIiwiemFxMTNsa2lHLTd2am90SFppM0psSmhwS2JtUjFTVnV6Q3pLYVZYOUZRUSIsInhyYjdTOFZsNlctb0dMaVVQcTVlMmplVFpKVk5mYmRtNW9KNjd0VlVQem8iLCJwT0Jmb3hmQndqQUNPbXZ4aTNUSTc0RDN4Y2FwZS1RWVlGeUNPZEpPel9VIiwiRm1ZcmFmbWotUW9lbE1sSkQtVTN2OVgwS3hXTkZwelhwRl9McVc2dkZ0byJdLCJwbGFjZU9mQmlydGgiOiJMSUxMRSwgRlJBTkNFIiwiZ2VuZGVyIjoiRkVNQUxFIiwiZmFtaWx5TmFtZSI6IkRPRSIsImlkIjoiZGlkOmVic2k6MkFFTUFxWFdLWU11MUpIUEFnR2NnYTRkeHU3VGhnZmdOOTVWeUpCSkdaYlNKVXRwIiwibmFtZUFuZEZhbWlseU5hbWVBdEJpcnRoIjoiSmFuZSBET0UiLCJjdXJyZW50QWRkcmVzcyI6WyIxIEJvdWxldmFyZCBkZSBsYSBMaWJlcnTDqSwgNTk4MDAgTGlsbGUiXX0sIl9zZF9hbGciOiJzaGEtMjU2IiwiaWQiOiJ1cm46dXVpZDozYWRkOTRmNC0yOGVjLTQyYTEtODcwNC00ZTRhYTUxMDA2YjQiLCJ2YWxpZEZyb20iOiIyMDIxLTA4LTMxVDAwOjAwOjAwWiIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJWZXJpZmlhYmxlQXR0ZXN0YXRpb24iLCJWZXJpZmlhYmxlSWQiXSwiaXNzdWVkIjoiMjAyMS0wOC0zMVQwMDowMDowMFoiLCJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJpc3N1ZXIiOiJkaWQ6ZWJzaToyQTlCWjlTVWU2QmF0YWNTcHZzMVY1Q2RqSHZMcFE3YkVzaTJKYjZMZEhLblF4YU4ifQ.5TZ1n6iDHtW3lnKA_7ofSQ-BWyvEr39LThGdIc1OMgUejG6JF6blGkTqcoaQABQJKq6pFgkhjrYcpDG8QcObDA~~

Issuance in Action

Using either the CLI, Kotlin or REST option, you can start issuing your SD-JWT credential.

Demo Video

Our implementation of selective disclosure currently does not follow any specific standard, as standards in the field are still under development. As reference, we used the reference by IETF. Please note that our implementation is subject to change.

Comparison of normal and SD-JWT credential

More details about StatusList2021Entry and StatusList2021Credential can be found at .

Currently, supports the following credentialStatus methods:

More details on credentialStatus specification can be found at .

Disclosure Verification: The verifier, upon receiving the shared disclosures and the SD-JWT, can confirm that the shared disclosures are a part of the SD-JWT. This is done by hashing the received disclosures in the same manner as the issuer did during .

, if you never used the SSi-Kit before. I will be using ssikit as an alias for ./ssikit.sh in this section.

DID creation

Creating a did:key for our SD-JWT credential. Please refer to for all options.

ssikit did create

Example Response

walt.id SSI Kit 1.SNAPSHOT (running on Java 18.0.1+10-24)

Creating did:id.walt.cli.did.KeyMethodOption@59c04bee (key: 98de22f79c7e445dbedc0c72a18f6f9a)

Results:


DID created: did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a


DID document (below, JSON):

{
    "assertionMethod" : [
        "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a#z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a"
    ],
    "authentication" : [
        "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a#z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a"
    ],
    "capabilityDelegation" : [
        "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a#z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a"
    ],
    "capabilityInvocation" : [
        "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a#z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a"
    ],
    "@context" : "https://www.w3.org/ns/did/v1",
    "id" : "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a",
    "keyAgreement" : [
        "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a#z6LSdemtq8mkV4nRKqvQvGkvs1JzSm4sCKKWNh6KkVox1vFn"
    ],
    "verificationMethod" : [
        {
            "controller" : "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a",
            "id" : "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a#z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a",
            "publicKeyBase58" : "FMZP5xZMrXr8cveAR28hr1s5wnybptiz5RddaM7KqnHC",
            "type" : "Ed25519VerificationKey2019"
        },
        {
            "controller" : "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a",
            "id" : "did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a#z6LSdemtq8mkV4nRKqvQvGkvs1JzSm4sCKKWNh6KkVox1vFn",
            "publicKeyBase58" : "2ybjJpxtPc4gETYePdEyYR6WbcXkVi9MViNeG3ARJYV2",
            "type" : "X25519KeyAgreementKey2019"
        }
    ]
}

Issue VC with SD-JWT format

We will be using the VerifiableId credential template for this example, but you can use whatever template you want. When issuing we specify the format of the VC as SD-JWT, the fields which we want to make selectily discloable and the number of decoy digests we want to include (optiona).

ssikit vc issue -s did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a \
-i did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a \
-y SD_JWT -t VerifiableId \
--sd credentialSubject \
--sd credentialSubject.dateOfBirth \
--num-decoys 2 \
--interactive vc.txt

Options:

  • -s, --subject-did: DID of the subject

  • -i, --issuer-did: DID of the issuer

  • -y, --proof-type: Either JWT, LD_PROOF or SD_JWT

  • -t, --template: VC template, e.g VerifiableId

  • --sd, --selective-disclosure: Path to selectively disclosable fields (if supported by chosen proof type), in a simplified JsonPath format, can be specified multiple times, e.g credentialSubject.dataOfBirth

  • --num-decoys: Number of SD-JWT decoy digests to add (fixed mode), or max num of decoy digests (random mode)

  • --interactive: Interactively prompt for VC data to fill in

  • vc.txt: Path to output the generated VC

Example Response

Receiving a JWT token with disclosures appended via '~'.

eyJraWQiOiJkaWQ6a2V5Ono2TWt0b3BSZ0Nvb0M1TGJqUlVzNmI2WWg3UjVtTkZURW15TG1TWVpRZDVMbTE0YSN6Nk1rdG9wUmdDb29DNUxialJVczZiNlloN1I1bU5GVEVteUxtU1laUWQ1TG0xNGEiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJzdWIiOiJkaWQ6a2V5Ono2TWt0b3BSZ0Nvb0M1TGJqUlVzNmI2WWg3UjVtTkZURW15TG1TWVpRZDVMbTE0YSIsIm5iZiI6MTY4NjU3OTY5NCwiaXNzIjoiZGlkOmtleTp6Nk1rdG9wUmdDb29DNUxialJVczZiNlloN1I1bU5GVEVteUxtU1laUWQ1TG0xNGEiLCJpYXQiOjE2ODY1Nzk2OTQsInZjIjp7InR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJWZXJpZmlhYmxlQXR0ZXN0YXRpb24iLCJWZXJpZmlhYmxlSWQiXSwiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwiaWQiOiJ1cm46dXVpZDoyZDM1YWFkMC1jY2UyLTQyODYtYWRmNy1jNGY5YTJlNTdmOTYiLCJpc3N1ZXIiOiJkaWQ6a2V5Ono2TWt0b3BSZ0Nvb0M1TGJqUlVzNmI2WWg3UjVtTkZURW15TG1TWVpRZDVMbTE0YSIsImlzc3VhbmNlRGF0ZSI6IjIwMjMtMDYtMTJUMTQ6MjE6MzRaIiwiaXNzdWVkIjoiMjAyMy0wNi0xMlQxNDoyMTozNFoiLCJ2YWxpZEZyb20iOiIyMDIzLTA2LTEyVDE0OjIxOjM0WiIsImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vd2FsdC1pZC93YWx0aWQtc3Npa2l0LXZjbGliL21hc3Rlci9zcmMvdGVzdC9yZXNvdXJjZXMvc2NoZW1hcy9WZXJpZmlhYmxlSWQuanNvbiIsInR5cGUiOiJGdWxsSnNvblNjaGVtYVZhbGlkYXRvcjIwMjEifSwiZXZpZGVuY2UiOlt7ImRvY3VtZW50UHJlc2VuY2UiOlsiUGh5c2ljYWwiXSwiZXZpZGVuY2VEb2N1bWVudCI6WyJQYXNzcG9ydCJdLCJzdWJqZWN0UHJlc2VuY2UiOiJQaHlzaWNhbCIsInR5cGUiOlsiRG9jdW1lbnRWZXJpZmljYXRpb24iXSwidmVyaWZpZXIiOiJkaWQ6ZWJzaToyQTlCWjlTVWU2QmF0YWNTcHZzMVY1Q2RqSHZMcFE3YkVzaTJKYjZMZEhLblF4YU4ifV0sIl9zZCI6WyJDQVlnNmc2bXJJTkFtdURDMzVKbXFMYy1DT1JBNC1MV2Fua2hKVWdVeHhzIl19LCJqdGkiOiJ1cm46dXVpZDoyZDM1YWFkMC1jY2UyLTQyODYtYWRmNy1jNGY5YTJlNTdmOTYifQ.xHwzXlrx0qS3grAQXWbZAX26Vg8enUegcVGMktl22Tr_ir19GHNidD6ZgEAJzlfmYS08hQDTAuDxsxE5J-ZvCA~~

Parsing the response

Viewing body of SD-JWT in JSON format

ssikit vc parse -c vc.txt

Options:

  • -c: credential content or file path

Example Responsen

{
    "type":[
        "VerifiableCredential",
        "VerifiableAttestation",
        "VerifiableId"
    ],
    "@context":[
        "https://www.w3.org/2018/credentials/v1"
    ],
    "id":"urn:uuid:2d35aad0-cce2-4286-adf7-c4f9a2e57f96",
    "issuer":"did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a",
    "issuanceDate":"2023-06-12T14:21:34Z",
    "issued":"2023-06-12T14:21:34Z",
    "validFrom":"2023-06-12T14:21:34Z",
    "credentialSchema":{
        "id":"https://raw.githubusercontent.com/walt-id/waltid-ssikit-vclib/master/src/test/resources/schemas/VerifiableId.json",
        "type":"FullJsonSchemaValidator2021"
    },
    "credentialSubject":{
        "id":"did:key:z6MktopRgCooC5LbjRUs6b6Yh7R5mNFTEmyLmSYZQd5Lm14a",
        "currentAddress":[
            "Vienna"
        ],
        "familyName":"Baumann",
        "firstName":"Tamino",
        "gender":"Male",
        "nameAndFamilyNameAtBirth":"Jane DOE",
        "personalIdentifier":"0904008084H",
        "placeOfBirth":"Munich",
        "dateOfBirth":"2023"
    },
    "evidence":[
        {
            "documentPresence":[
                "Physical"
            ],
            "evidenceDocument":[
                "Passport"
            ],
            "subjectPresence":"Physical",
            "type":[
                "DocumentVerification"
            ],
            "verifier":"did:ebsi:2A9BZ9SUe6BatacSpvs1V5CdjHvLpQ7bEsi2Jb6LdHKnQxaN"
        }
    ]
}

coming soon

Selective Disclosure for JWTs (SD-JWT)
Verifiable Credentials Status List v2021
SSIKit
StatusList2021Entry
SimpleCredentialStatus2022
Verifiable Credential Data Model - Status
the issuance process
Setup section
DIDs section
Wallet
Intro and Demo for Verifiable Credentials with Status

Issue credentials with credentialStatus

In order to issue a verifiable credential with a credentialStatus, the statusType property of the proofConfig object should be provided (e.g. 'SimpleCredentialStatus2022', 'StatusList2021Entry', etc.). If no statusType is provided, the credential will be issued without any credentialStatus property.

Rest API interface

e.g. Issue a UniversityDegree credential having a StatusList2021Entry credentialStatus using the REST API interface issue endpoint: https://signatory.ssikit.walt.id/v1/credentials/issue. The request-body is presented below.

{
    "templateId": "UniversityDegree",
    "config":
    {
        "issuerDid": "did:key:z6MkiWE3zZaTkDYLBwrPeZ94bXC9CnDVVeRcX12tncBh9q2X>",
        "subjectDid": "did:key:z6MkoHRK9dK81gFrGzwo6kygHW8KRoECGhLk5QJgNPYdzCTK",
        "statusType": "StatusList2021Entry"
    }
}

Command-line interface

e.g. Issue a UniversityDegree credential having a StatusList2021Entry credentialStatus using the command-line interface issue command: ssikit vc issue -h

ssikit vc issue \ 
-t UniversityDegree \ 
-i did:key:z6MkiWE3zZaTkDYLBwrPeZ94bXC9CnDVVeRcX12tncBh9q2X \
-s did:key:z6MkoHRK9dK81gFrGzwo6kygHW8KRoECGhLk5QJgNPYdzCTK \
--status-type StatusList2021Entry
The blue boxes symbolise our products and their interfaces. The green boxes symbolise third party solutions that can be integrated via open APIs to avoid rip-and-replace and extend functionality to meet diverse customer requirements.
Each building block is available in different variations and can be put together in different ways. The result: different "SSI flavours".