§ WACI-DIDComm Interop Profile
A DIDComm v2.0 Profile for supporting the Wallet and Credential Interaction (WACI) Protocols for both Issuance and Presentation Exchange, colloqually known as:
WACI PEx [wak-ee pex]
Specification Status: Draft V1.0
Latest Draft: https://identity.foundation/waci-didcomm/
- Editors:
- Orie Steele (Transmute)
- Brent Zundel (Evernym)
- Contributors:
- Afshan Aman (Bloom)
- Eddie Hedges (Bloom)
- Jace Hensley (Bloom)
- Sam Curren (Indicio.tech)
- Brian Richter (Aviary Tech)
- Rolson Quadras (SecureKey)
- Juan Caballero (Centre.io)
- Participate:
- GitHub repo
- File a bug
- Commit history
§ Abstract
There are interactions between a “holder” and an “issuer”, or between a “holder” and a “verifier” that require passing verifiable information between the two. This specification provides an initial protocol definition for the two main interactions (issuance and presentation) required for verifiable credentials.
This document describes an interoperability profile which incorporates elements from a number of existing specifications and protocols, without assuming or requiring an implementer to understand all of them. It inherits its overall structure from the current pre-draft of WACI, but makes use of elements from the DIDComm v2.0 messaging protocol, along with Aries Present Proof message formats and DIF Presentation Exchange data objects. This version of the specification also restricts itself to Verifiable Credentials that make use of the JsonWebSignature2020 signature suite and Ed25519Signature2018 signature suite.
§ Status of This Document
WACI-DIDComm Interop Profile v1.0.0 is a WORKING GROUP APPROVED interoperability profile under development by the Claims and Credentials Working Group at DIF.
We feel that the specification is ready for publication as v1.0.0.
We encourage reviewers to submit issues on GitHub.
§ Introduction
The 32nd Internet Identity Workshop (IIW) hosted a series of sessions about designing an interoperable protocol for requesting and providing verifiable information. The sessions lasted many hours over the course of several days and resulted in interest among the participants in continuing to work out the details of such a protocol, as well as a rough consensus around a set of components that could be used in a layered approach for the design. The Claims and Credentials Working Group at DIF agreed to host a work item for continuing to work out the details. We outline some of the reasons for choosing each of the components below.
§ Verifiable Presentations
The starting point for most participants in determining which components to
select was the
Verifiable Credentials Data Model. It
describes a Verifiable Presentation
object that is designed for sharing
information from Verifiable Credentials
.
§ Credential Manifest
In issuance situations, the credentials on offer by a given issuer can be defined in objects that can be passed back and forth, in the “Presentation Exchange” data model/abstraction layering. These issuance-definition objects are defined for issuance flows. A “sister specification” of the Presentation Exchange work-item group defines those objects: Credential Manifest.
§ Presentation Exchange
The next component is a data model that provides a solution to the problem of
how to format a request that verifiable information be presented. The
Presentation Exchange specification
was recently published by the Decentralized Identity Foundation. It defines a
Presentation Definition
data object which may be used by a verifier (i.e., a
“relying party” in OIDC parlance) to request information, and a Presentation Submission
object which describes the relationship between the Presentation Definition
and the submitted verifiable information.
Since
Presentation Exchange
supports the use of Verifiable Presentations
as a response to a Presentation Definition
, while remaining agnostic to transport protocols, it is ideal for
our purposes.
§ Protocol Considerations
Before fixing the scope of this work item and settling on using elements of DIDComm v2.0 to securely communicate the data objects, there was a long and lively discussion about other options at IIW.
-
CHAPI is an API for exchanging data between websites and browsers. It was seen as too limited to a particular technology to be widely useful for wallet applications on smart phones and other devices without significant changes.
-
VC-API (fka VC-HTTP-API) was seen as promising, but in its current state lacked any API for a
Verifiable Credential
holder. A number of participants expressed a desire for the WACI specification to strive to be compatible with this API, and that remains a goal of this group. -
DIDComm v2.0 describes a method for securely communicating authenticated messages between entities that control Decentralized Identifiers along any transport layer. It allows for two parties to mutually authenticate and securely communicate. DIDComm has a large community interested in using it, and many have already implemented DIDComm v1.0.
-
OIDC-SIOP seeks to bridge existing federated identity capabilities on the internet with principles of self-sovereign identity, and may ultimately be a good fit for this protocol. It was not selected for this version of the specification primarily because v1 of the specification has been deprecated, and v2 of the specification was somewhat unstable at the time.
-
Aries Protocols, specifically the current stable drafts of present proof protocol V2 and issue credential V2. A draft of V3 resides in this work item’s repo as a stop-gap measure, pending its move to didcomm.org.
§ Presentation Exchange
Presentation Exchange objects support a large variety of possible content and signature types. Many of these are out of scope of this profile, but the presentation definitions is directly relevant and relied upon.
§ format property
A presentation definition
that complies with this specification MUST contain a
format
property. The value of the format
property MUST be an object with the
following property:
ldp_vp
: This property indicates that a W3C Verifiable Presentation will be submitted in the form of a JSON object. The value of this property MUST be an object with aproof_type
property that has a value of eitherJsonWebSignature2020
orEd25519Signature2018
.
Here is an abbreviated example (see the test vectors in the repository for more context):
{
"presentation_definition": {
"format": {
"ldp_vp": {
"proof_type": ["BbsBlsSignature2020", "JsonWebSignature2020", "Ed25519Signature2018"]
}
}
}
}
§ DIDComm Context
The exchange specified in the DIDComm v2 specification is presumed to take place between two subjects that control DIDs with certain properties, and can take place over many different transports. Having a connection means that each party in the relationship has a DID for the other parties, and parties can communicate securely using the keys and endpoints within each DID Document.
All parties MUST have a DID document
that complies with this specification.
§ service property
A DID document
that complies with this specification MUST have a service
property, consisting of a structured object as per the DIDComm v2 specification (see the DID Document section).
Here is an abbreviated example showing the service
section of a conformant DID Document (see the test vectors in the repository for more context):
{
"service": [{
"id": "did:example:123123123#someid",
"type": "DIDCommMessaging",
"serviceEndpoint": {
"uri": ["https://example.com/endpoint"],
"routingKeys": ["did:example:somemediator#somekey"]
}
}]
}
The value of the service
property MUST be an array of objects composed as
follows:
- a service object MUST have an
id
property and its value MUST be a string consisting of a unique identifier. - a service object MUST have a
type
property and its value MUST be the stringDIDCommMessaging
. - a service object MUST have a
serviceEndpoint
property, and its value MUST be an ordered list of valid DIDComm Service Endpoint objects, with the order signaling preference in receiving messages.
A DIDComm Service Endpoint object
- MUST contain a URI and its value MUST be a string consisting of a valid, resolvable URI
- MAY have a
routingKeys
property. If present its value MUST be an array of strings. Each string MUST be a URI designating a valid routing key. See below for more details.
§ Routing Keys
Routing Keys are used to enable message routing to agents unable to provide a
direct service endpoint. Routing is arranged by the message recipient and
communicated by the service
property as defined above.
Before preparing a routed message, the sender creates an encrypted package by
encrypting the message for the recipient. Then, for each routing key in the
routingKeys
array in order, take the encrypted package, wrap it in a forward
message (see below), and encrypt the forward message to the routing key to
create a new encrypted package.
The process of wrapping the encrypted package in a forward message and
encrypting it is repeated for each routing key in the array. The final encrypted
package is transmitted to the listed serviceEndpoint
.
Forward message structure:
{
"type": "https://didcomm.org/routing/2.0/forward",
"to": ["did:example:somemediator#somekey"], //the routing key URI
"body":{
"next": "did:example:123123123", //the recipient of the encrypted package
},
"attachments": [
{
"media_type": "application/didcomm-encrypted+json",
"data": {
"json": { } //json structure of the encrypted package
}
}
]
}
§ Encryption
Messages are sent encrypted. Each message described in this specification MUST be encrypted before transmission with the exception of the message encoded into a QR code.
JOSE Header:
{
"typ":"JWM",
"enc":"A256GCM"
}
The kid
used in the JWE recipients block MUST be the DID of the message
recipient.
The plaintext message to be encrypted is prepared by serializing the JSON to a string and removing the whitespace.
The encrypted message MUST be in JSON form. Compact JWEs are not supported.
Further details on JWE creation may be found in RFC 7516.
Encoded message example, with abbreviations and line breaks for clarity:
{
"protected": "eyJ0eXAiOi...19",
"recipients": [
{
"header": {
"kid": "did:example:recipient#key-agreement-key-1"
},
"encrypted_key": "J1Fs9JaD...PalQWWLg"
}
],
"iv": "u5kIzo0m_d2PjI4m",
"ciphertext": "qGuFFoHy...wa1C3T0QBes",
"tag": "doe...cduiw"
}
§ Establishing an HTTP(S) Connection
In order to establish a new connection, Simply exchange a new message between parties. Knowing the DID of the other parties does not indicate any level of trust.
Details of sending an encrypted message to a serviceEndpoint
via HTTP:
- Messages are transported via HTTP POST.
- The MIME Type for the POST request is set to the corresponding media type
defined in Media Types,
e.g.,
application/didcomm-encrypted+json
. - A successful message receipt MUST return a code in the 2xx HTTP Status Code
range. It is RECOMMENDED that a HTTP POST return a
202 Accepted
status code. - POST requests are transmit only. Messages are sent from the code that submitted the POST request.
- HTTP Redirects SHOULD be followed. Only Temporary Redirects (307) are acceptable. Permanent endpoint relocation SHOULD be managed with a DID document update.
- Using HTTPS with TLS 1.2 or greater with a forward secret cipher will provide Perfect Forward Secrecy (PFS) on the transmission leg.
§ Web Redirect
The DIDComm v2 supports web_redirect feature to redirect the receiver application back to the sender application. In the case of WACI, the Issuer/Verifier may ask the Wallet to redirect back using this property.
Example acknowledgement message containing web_redirect information:
{
"type":"https://didcomm.org/present-proof/3.0/ack",
"id":"e2f3747b-41e8-4e46-abab-ba51472ab1c3",
"pthid":"95e63a5f-73e1-46ac-b269-48bb22591bfa",
"from":"did:example:verifier",
"to":["did:example:prover"],
"web_redirect":{
"status":"OK",
"redirectUrl":"https://example.com/handle-success/51e63a5f-93e1-46ac-b269-66bb22591bfa"
}
}
Example problem-report message containing web_redirect information.
{
"type": "https://didcomm.org/report-problem/2.0/problem-report",
"id": "7c9de639-c51c-4d60-ab95-103fa613c805",
"pthid": "1e513ad4-48c9-444e-9e7e-5b8b45c5e325",
"web_redirect":{
"status":"FAIL",
"redirectUrl":"https://example.com/handle-error/99e80a9f-34e1-41ac-b277-91bb64481bxb"
},
"body": {
"code": "e.p.xfer.cant-use-endpoint",
"comment": "Unable to use the {1} endpoint for {2}.",
"args": [
"https://agents.r.us/inbox",
"did:example:123"
]
}
}
§ WACI Protocol Context
§ Issuance
The issuance flow uses DIF DIDComm v2 along with Issue Credential v3 and DIF Credential Manifest.
§ Presentation
The interactions, objects, and assumptions outlined in the WACI pre-draft specification are the basis for the following. Specifically, the profile describes the Request/Share flow.
As an overview, see this flow diagram:

§ Interoperability Profile
§ Issuance
§ Step 1 : Generate Out-Of-Band (OOB) message
The issuer generates a DIDComm v2 Out-Of-Band(OOB) invitation message with goal_code
as streamlined-vc
. This message can be encoded as a QR code or a redirect URL.
{
"type":"https://didcomm.org/out-of-band/2.0/invitation",
"id":"f137e0db-db7b-4776-9530-83c808a34a42",
"from":"did:example:issuer",
"body":{
"goal_code":"streamlined-vc",
"accept":[
"didcomm/v2"
]
}
}
§ Step 2 : Issue Credential - Propose Credential
The wallet (user agent) starts the credential issuance process by sending the Issue Credential - Propose Credential message.
{
"type":"https://didcomm.org/issue-credential/3.0/propose-credential",
"id":"7f62f655-9cac-4728-854a-775ba6944593",
"pthid":"f137e0db-db7b-4776-9530-83c808a34a42",
"from":"did:example:holder",
"to":[
"did:example:issuer"
]
}
The id
property MAY be any arbitrary string used to identify each message, such as a
UUID or a hash, but the id
of the initial message SHOULD be included as the
Thread ID (thid
) of subsequent messages.
If the Thread ID (thid
) is not present
in a message, it’s value is the same as the Message ID (id
), and indicates the
start of a new thread. Subsequent messages in the thread SHOULD use that id
as
the Thread ID (thid
).
The Parent Thread ID (pthid
) MUST be included for this
message only, and is set to the Message ID (id
) of the message encoded as a
QR code. The use of the Parent Thread ID matching the Message ID in the QR code of Step 1 allows the message recipient (and creator of the QR code) to
correlate this message with the QR code that was scanned. This can be used to link a specific session to the DIDComm messages used to present credentials.
§ Step 3 : Issue Credential - Offer Credential (Credential Manifest)
The Issuer sends a Issue Credential - Offer Credential message to Holder. The message attachment contains a Credential Manifest message from Credential Manifest Spec. The Credential Manifest message contains an output descriptor to display the Credential preview to the user and an optional presentation definition, in case the issuer needs any other credential before issuing the new credential.
In the following message structure, the issuer wants a Permanent Resident Card (PRC) in order to issue a Drivers License (DL).
{
"type":"https://didcomm.org/issue-credential/3.0/offer-credential",
"id":"07c44208-06a9-4f8a-a5ce-8ce953270d4b",
"thid":"7f62f655-9cac-4728-854a-775ba6944593",
"from":"did:example:issuer",
"to":[
"did:example:holder"
],
"body":{
},
"attachments":[
{
"id":"e00e11d4-906d-4c88-ba72-7c66c7113a78",
"media_type":"application/json",
"format":"dif/credential-manifest/[email protected]",
"data":{
"json":{
"options":{
"challenge":"508adef4-b8e0-4edf-a53d-a260371c1423",
"domain":"9rf25a28rs96"
},
"credential_manifest":{
"id":"dcc75a16-19f5-4273-84ce-4da69ee2b7fe",
"version":"0.1.0",
"issuer":{
"id":"did:example:123",
"name":"Washington State Government",
"styles":{
"thumbnail":{
"uri":"https://dol.wa.com/logo.png",
"alt":"Washington State Seal"
},
"hero":{
"uri":"https://dol.wa.com/happy-people-driving.png",
"alt":"Happy people driving"
},
"background":{
"color":"#ff0000"
},
"text":{
"color":"#d4d400"
}
}
},
"presentation_definition":{
"id":"8246867e-fdce-48de-a825-9d84ec16c6c9",
"frame":{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/citizenship/v1",
"https://w3id.org/security/suites/bls12381-2020/v1"
],
"type":[
"VerifiableCredential",
"PermanentResidentCard"
],
"credentialSubject":{
"@explicit":true,
"type":[
"PermanentResident"
],
"givenName":{
},
"familyName":{
},
"birthCountry":{
},
"birthDate":{
}
}
},
"input_descriptors":[
{
"id":"prc_input",
"name":"Permanent Resident Card",
"purpose":"We need PRC to verify your status.",
"constraints":{
"fields":[
{
"path":[
"$.credentialSchema.id", "$.vc.credentialSchema.id"
],
"filter":{
"type":"string",
"const": "https://w3id.org/vaccination/#VaccinationCertificate"
}
}, {
"path":[
"$.credentialSubject.givenName"
],
"filter":{
"type":"string"
}
},
{
"path":[
"$.credentialSubject.familyName"
],
"filter":{
"type":"string"
}
},
{
"path":[
"$.credentialSubject.birthCountry"
],
"filter":{
"type":"string"
}
},
{
"path":[
"$.credentialSubject.birthDate"
],
"filter":{
"type":"string"
}
}
]
}
}
]
},
"output_descriptors":[
{
"id":"driver_license_output",
"schema":"https://schema.org/EducationalOccupationalCredential",
"display":{
"title":{
"path":[
"$.name",
"$.vc.name"
],
"fallback":"Washington State Driver License"
},
"subtitle":{
"path":[
"$.class",
"$.vc.class"
],
"fallback":"Class A, Commercial"
},
"description":{
"text":"License to operate a vehicle with a gross combined weight rating (GCWR) of 26,001 or more pounds, as long as the GVWR of the vehicle(s) being towed is over 10,000 pounds."
},
"properties":[
{
"path":[
"$.donor",
"$.vc.donor"
],
"fallback":"Unknown",
"label":"Organ Donor"
}
]
},
"styles":{
"thumbnail":{
"uri":"https://dol.wa.com/logo.png",
"alt":"Washington State Seal"
},
"hero":{
"uri":"https://dol.wa.com/happy-people-driving.png",
"alt":"Happy people driving"
},
"background":{
"color":"#ff0000"
},
"text":{
"color":"#d4d400"
}
}
}
]
}
}
}
},
{
"id":"b55f39c1-a7e5-4d4f-8ba0-716a19ec013a",
"media_type":"application/json",
"format":"dif/credential-manifest/[email protected]",
"data":{
"json":{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://identity.foundation/credential-manifest/fulfillment/v1"
],
"type":[
"VerifiablePresentation",
"CredentialFulfillment"
],
"credential_fulfillment":{
"id":"a30e3b91-fb77-4d22-95fa-871689c322e2",
"manifest_id":"dcc75a16-19f5-4273-84ce-4da69ee2b7fe",
"descriptor_map":[
{
"id":"driver_license_output",
"format":"ldp_vc",
"path":"$.verifiableCredential[0]"
}
]
},
"verifiableCredential":[
{
"@context":"https://www.w3.org/2018/credentials/v1",
"id":"https://eu.com/claims/DriversLicense",
"type":[
"VerifiableCredential",
"EUDriversLicense"
],
"issuer":"did:foo:123",
"issuanceDate":"2010-01-01T19:23:24Z",
"credentialSubject":{
"id":"did:example:ebfeb1f712ebc6f1c276e12ec21",
"license":{
"number":"34DGE352",
"dob":"07/13/80"
}
}
}
]
}
}
}
]
}
§ Attachments
Credential Format | Format Value | Link to Attachment Format | Comment |
---|---|---|---|
DIF Credential Manifest Message | dif/credential-manifest/[email protected] |
DIF Credential Manifest Spec | |
DIF Credential Fullfilment Message (Unsigned) | dif/credential-manifest/[email protected] |
DIF Credential Manifest Spec |
§ Step 4 : Issue Credential - Request Credential (Credential Application)
The User sends a Credential Application message as an attachment in Issue Credential - Request Credential.
{
"type":"https://didcomm.org/issue-credential/3.0/request-credential",
"id":"c6686159-ef49-45b2-938f-51818da14723",
"thid":"7f62f655-9cac-4728-854a-775ba6944593",
"from":"did:example:holder",
"to":[
"did:example:issuer"
],
"body":{
},
"attachments":[
{
"id":"e00e11d4-906d-4c88-ba72-7c66c7113a78",
"media_type":"application/json",
"format":"dif/credential-manifest/[email protected]",
"data":{
"json":{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://identity.foundation/credential-manifest/application/v1"
],
"type":[
"VerifiablePresentation",
"CredentialApplication"
],
"credential_application":{
"id":"9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"manifest_id":"dcc75a16-19f5-4273-84ce-4da69ee2b7fe",
"format":{
"ldp_vc":{
"proof_type":[
"JsonWebSignature2020",
"EcdsaSecp256k1Signature2019"
]
}
}
},
"presentation_submission":{
"id":"2e161b2c-606b-416f-b04f-7f06edac55a1",
"definition_id":"8246867e-fdce-48de-a825-9d84ec16c6c9",
"descriptor_map":[
{
"id":"prc_input",
"format":"ldp_vp",
"path":"$.verifiableCredential[0]"
}
]
},
"verifiableCredential":[
{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/citizenship/v1",
"https://w3id.org/security/bbs/v1"
],
"id":"urn:uvci:af5vshde843jf831j128fj",
"type":[
"VerifiableCredential",
"VaccinationCertificate",
"PermanentResidentCard"
],
"name":"Permanent Resident Card",
"description":"Permanent Resident Card of Mr.Louis Pasteu",
"expirationDate":"2029-12-03T12:19:52Z",
"issuanceDate":"2019-12-03T12:19:52Z",
"issuer":"did:example:456",
"credentialSubject":{
"id":"did:example:ebfeb1f712ebc6f1c276e12ec21",
"givenName":"Louis",
"familyName":"Pasteur",
"birthCountry":"Bahamas",
"birthDate":"1958-07-17"
},
"proof":{
"type":"BbsBlsSignatureProof2020",
"created":"2021-02-18T23:04:28Z",
"nonce":"JNGovx4GGoi341v/YCTcZq7aLWtBtz8UhoxEeCxZFevEGzfh94WUSg8Ly/q+2jLqzzY=",
"proofPurpose":"assertionMethod",
"proofValue":"AB0GQA//jbDwMgaIIJeqP3fRyMYi6WDGhk0JlGJc/sk4ycuYGmyN7CbO4bA7yhIW/YQbHEkOgeMy0QM+usBgZad8x5FRePxfo4v1dSzAbJwWjx87G9F1lAIRgijlD4sYni1LhSo6svptDUmIrCAOwS2raV3G02mVejbwltMOo4+cyKcGlj9CzfjCgCuS1SqAxveDiMKGAAAAdJJF1pO6hBUGkebu/SMmiFafVdLvFgpMFUFEHTvElUQhwNSp6vxJp6Rs7pOVc9zHqAAAAAI7TJuDCf7ramzTo+syb7Njf6ExD11UKNcChaeblzegRBIkg3HoWgwR0hhd4z4D5/obSjGPKpGuD+1DoyTZhC/wqOjUZ03J1EtryZrC+y1DD14b4+khQVLgOBJ9+uvshrGDbu8+7anGezOa+qWT0FopAAAAEG6p07ghODpi8DVeDQyPwMY/iu2Lh7x3JShWniQrewY2GbsACBYOPlkNNm/qSExPRMe2X7UPpdsxpUDwqbObye4EXfAabgKd9gCmj2PNdvcOQAi5rIuJSGa4Vj7AtKoW/2vpmboPoOu4IEM1YviupomCKOzhjEuOof2/y5Adfb8JUVidWqf9Ye/HtxnzTu0HbaXL7jbwsMNn5wYfZuzpmVQgEXss2KePMSkHcfScAQNglnI90YgugHGuU+/DQcfMoA0+JviFcJy13yERAueVuzrDemzc+wJaEuNDn8UiTjAdVhLcgnHqUai+4F6ONbCfH2B3ohB3hSiGB6C7hDnEyXFOO9BijCTHrxPv3yKWNkks+3JfY28m+3NO0e2tlyH71yDX0+F6U388/bvWod/u5s3MpaCibTZEYoAc4sm4jW03HFYMmvYBuWOY6rGGOgIrXxQjx98D0macJJR7Hkh7KJhMkwvtyI4MaTPJsdJGfv8I+RFROxtRM7RcFpa4J5wF/wQnpyorqchwo6xAOKYFqCqKvI9B6Y7Da7/0iOiWsjs8a4zDiYynfYavnz6SdxCMpHLgplEQlnntqCb8C3qly2s5Ko3PGWu4M8Dlfcn4TT8YenkJDJicA91nlLaE8TJbBgsvgyT+zlTsRSXlFzQc+3KfWoODKZIZqTBaRZMft3S/",
"verificationMethod":"did:example:123#key-1"
}
}
],
"proof":{
"type":"Ed25519Signature2018",
"verificationMethod":"did:example:123#key-0",
"created":"2021-05-14T20:16:29.565377",
"proofPurpose":"authentication",
"challenge":"3fa85f64-5717-4562-b3fc-2c963f66afa7",
"jws":"eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..7M9LwdJR1_SQayHIWVHF5eSSRhbVsrjQHKUrfRhRRrlbuKlggm8mm_4EI_kTPeBpalQWiGiyCb_0OWFPtn2wAQ"
}
}
}
}
]
}
§ Step 5 : Issue Credential - Issue Credential (Credential Fulfilment)
The Issuer sends a Credential Fulfilment message as an attachment in Issue Credential - Issue Credential, which will contain the Verifiable Credentials.
{
"type":"https://didcomm.org/issue-credential/3.0/issue-credential",
"id":"7a476bd8-cc3f-4d80-b784-caeb2ff265da",
"thid":"7f62f655-9cac-4728-854a-775ba6944593",
"from":"did:example:issuer",
"to":[
"did:example:holder"
],
"body":{
},
"attachments":[
{
"id":"e00e11d4-906d-4c88-ba72-7c66c7113a78",
"media_type":"application/json",
"format":"dif/credential-manifest/[email protected]",
"data":{
"json":{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://identity.foundation/credential-manifest/fulfillment/v1"
],
"type":[
"VerifiablePresentation",
"CredentialFulfillment"
],
"credential_fulfillment":{
"id":"a30e3b91-fb77-4d22-95fa-871689c322e2",
"manifest_id":"dcc75a16-19f5-4273-84ce-4da69ee2b7fe",
"descriptor_map":[
{
"id":"driver_license_output",
"format":"ldp_vc",
"path":"$.verifiableCredential[0]"
}
]
},
"verifiableCredential":[
{
"@context":"https://www.w3.org/2018/credentials/v1",
"id":"https://eu.com/claims/DriversLicense",
"type":[
"VerifiableCredential",
"EUDriversLicense"
],
"issuer":"did:foo:123",
"issuanceDate":"2010-01-01T19:23:24Z",
"credentialSubject":{
"id":"did:example:ebfeb1f712ebc6f1c276e12ec21",
"license":{
"number":"34DGE352",
"dob":"07/13/80"
}
},
"proof":{
"created":"2021-06-07T20:02:44.730614315Z",
"jws":"eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..NVum9BeYkhzwslZXm2cDOveQB9njlrCRSrdMZgwV3zZfLRXmZQ1AXdKLLmo4ClTYXFX_TWNyB8aFt9cN6sSvCg",
"proofPurpose":"assertionMethod",
"type":"Ed25519Signature2018",
"verificationMethod":"did:orb:EiA3Xmv8A8vUH5lRRZeKakd-cjAxGC2A4aoPDjLysjghow#tMIstfHSzXfBUF7O0m2FiBEfTb93_j_4ron47IXPgEo"
}
}
],
"proof":{
"created":"2021-06-07T20:02:44.730614315Z",
"jws":"eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..NVum9BeYkhzwslZXm2cDOveQB9njlrCRSrdMZgwV3zZfLRXmZQ1AXdKLLmo4ClTYXFX_TWNyB8aFt9cN6sSvCg",
"proofPurpose":"authentication",
"type":"Ed25519Signature2018",
"verificationMethod":"did:orb:EiA3Xmv8A8vUH5lRRZeKakd-cjAxGC2A4aoPDjLysjghow#tMIstfHSzXfBUF7O0m2FiBEfTb93_j_4ron47IXPgEo"
}
}
}
}
]
}
§ Step 6 : Issue Credential - Ack
The wallet sends an acknolowledgement message to the issuer.
{
"type":"https://didcomm.org/issue-credential/3.0/ack",
"id":"d1fb78ad-c452-4c52-a7a0-b68b3e82cdd3",
"thid":"7f62f655-9cac-4728-854a-775ba6944593",
"from":"did:example:holder",
"to":[
"did:example:issuer"
],
"body":{
}
}
§ Presentation
§ Step 1 - Generate QR Code
The QR code used to start a presentation is constructed by encoding a json based message into a URI, then encoding that URI into a QR code.
§ JSON message
The contents of the QR code to be generated are described in the following JSON block, which DIDComm v2 calls an “out of band invitation.”
{
"type": "https://didcomm.org/out-of-band/2.0/invitation",
"id": "599f3638-b563-4937-9487-dfe55099d900",
"from": "did:example:verifier",
"body": {
"goal_code": "streamlined-vp",
"accept": ["didcomm/v2"]
}
}
§ Encoding
To encode this message, remove all json whitespace and Base 64 URL encode. The result should look like this, for the example above:
eyJ0eXBlIjoiaHR0cHM6Ly9kaWRjb21tLm9yZy9vdXQtb2YtYmFuZC8yLjAvaW52aXRhdGlvbiIsImlkIjoiNTk5ZjM2MzgtYjU2My00OTM3LTk0ODctZGZlNTUwOTlkOTAwIiwiZnJvbSI6ImRpZDpleGFtcGxlOnZlcmlmaWVyIiwiYm9keSI6eyJnb2FsX2NvZGUiOiJzdHJlYW1saW5lZC12cCIsImFjY2VwdCI6WyJkaWRjb21tL3YyIl19fQ==
Prepend this encoded string with a domain and path, and a query parameter of
_oob
set to the encoded message.
https://example.com/some/path?_oob=eyJ0eXBlIjoiaHR0cHM6Ly9kaWRjb21tLm9yZy9vdXQtb2YtYmFuZC8yLjAvaW52aXRhdGlvbiIsImlkIjoiNTk5ZjM2MzgtYjU2My00OTM3LTk0ODctZGZlNTUwOTlkOTAwIiwiZnJvbSI6ImRpZDpleGFtcGxlOnZlcmlmaWVyIiwiYm9keSI6eyJnb2FsX2NvZGUiOiJzdHJlYW1saW5lZC12cCIsImFjY2VwdCI6WyJkaWRjb21tL3YyIl19fQ==
§ QR Code generated
Present as a link, or as a QR code.
§ QR Code scanning and processing
The URI, if loaded into a browser SHOULD display instructions on how to download
and use a mobile application. If scanned inside an app that understands this
protocol, the message SHOULD be extracted from the URI’s _oob
query parameter
and processed without resolving the URI. This behavior allows for a better
fallback user experience should a user encounter a QR code without having a
suitable app.
§ Step 2 - Send Message Proposing Presentation
A “Propose Presentation” message is defined in Aries RFC 0454 and its Presentation Exchange “attachment” defined in RFC 0510. It either initiates a Request/Share interaction or answers an earlier invitation to do so. In the context of this flow, this response to the invitation establishes the same kind of connection that the WACI specification establishes in can be functionally equivalent to the two-step request for a challenge token & callback URL described in the challenge token section.
The response to the invite QR with presentation-proposal attached looks like this:
{
"type": "https://didcomm.org/present-proof/3.0/propose-presentation",
"id": "95e63a5f-73e1-46ac-b269-48bb22591bfa",
"pthid": "599f3638-b563-4937-9487-dfe55099d900",
"from": "did:example:prover",
"to": ["did:example:verifier"]
}
The id
property MAY be any arbitrary string used to identify each message, such as a
UUID or a hash, but the id
of the initial message SHOULD be included as the
Thread ID (thid
) of subsequent messages.
If the Thread ID (thid
) is not present
in a message, it’s value is the same as the Message ID (id
), and indicates the
start of a new thread. Subsequent messages in the thread SHOULD use that id
as
the Thread ID (thid
).
The Parent Thread ID (pthid
) MUST be included for this
message only, and is set to the Message ID (id
) of the message encoded as a
QR code. The use of the Parent Thread ID matching the Message ID in the QR code of Step 1 allows the message recipient (and creator of the QR code) to
correlate this message with the QR code that was scanned. This can be used to link a specific session to the DIDComm messages used to present credentials.
§ Step 3 - Send Message Requesting Presentation
The request for a Verifiable Presentation is defined in the “request presentation” section of Aries RFC 0454 and the attachment format for Presentation Exchange objects is defined in Aries RFC 0510.
The challenge
and domain
properties are used to specify a nonce and an
operational domain, similar to the functionality provided by the JWT jti
and
aud
claims.
The options
object MUST contain a challenge
property. The value of this
property MUST be a string as described in
Aries RFC-510
The options
object MAY contain a domain
property. If present, the value of
this property MUST be a string as described in
Aries RFC-510
{
"type": "https://didcomm.org/present-proof/3.0/request-presentation",
"id": "0ac534c8-98ed-4fe3-8a41-3600775e1e92",
"thid": "95e63a5f-73e1-46ac-b269-48bb22591bfa",
"from": "did:example:verifier",
"to": [
"did:example:prover"
],
"body": {},
"attachments": [
{
"id": "ed7d9b1f-9eed-4bde-b81c-3aa7485cf947",
"media_type": "application/json",
"format": "dif/presentation-exchange/[email protected]",
"data": {
"json": {
"options": {
"challenge": "3fa85f64-5717-4562-b3fc-2c963f66afa7",
"domain": "4jt78h47fh47"
},
"presentation_definition": {
"id": "32f54163-7166-48f1-93d8-ff217bdb0654",
"frame": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/vaccination/v1",
"https://w3id.org/security/suites/bls12381-2020/v1"
],
"type": [
"VerifiableCredential",
"VaccinationCertificate"
],
"credentialSubject": {
"@explicit": true,
"type": [
"VaccinationEvent"
],
"batchNumber": {},
"countryOfVaccination": {}
}
},
"input_descriptors": [
{
"id": "vaccination_input",
"name": "Vaccination Certificate",
"constraints": {
"fields": [
{
"path": [
"$.credentialSchema.id", "$.vc.credentialSchema.id"
],
"filter": {
"type": "string",
"const": "https://w3id.org/vaccination/#VaccinationCertificate"
}
},
{
"path": [
"$.credentialSubject.batchNumber"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.credentialSubject.countryOfVaccination"
],
"filter": {
"type": "string"
}
}
]
}
}
]
}
}
}
}
]
}
For context on the Vaccination object passed, see the W3C-CCG Vaccination Vocabulary, from which the example is drawn.
§ Step 4 - Present Proof
The Verifiable Presentation is again returned as an attachment (defined by
RFC 0510)
to a DIDComm
present-proof
message. Note the challenge
from the previous message is given in the proof
object for the VP and used to generate the signature there.
{
"type": "https://didcomm.org/present-proof/3.0/presentation",
"id": "f1ca8245-ab2d-4d9c-8d7d-94bf310314ef",
"thid": "95e63a5f-73e1-46ac-b269-48bb22591bfa",
"from": "did:example:prover",
"to": [
"did:example:verifier"
],
"body": {},
"attachments": [
{
"id": "2a3f1c4c-623c-44e6-b159-179048c51260",
"media_type": "application/ld+json",
"format": "dif/presentation-exchange/[email protected]",
"data": {
"json": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://identity.foundation/presentation-exchange/submission/v1"
],
"type": [
"VerifiablePresentation",
"PresentationSubmission"
],
"holder": "did:example:123",
"verifiableCredential": [
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/vaccination/v1",
"https://w3id.org/security/bbs/v1"
],
"id": "urn:uvci:af5vshde843jf831j128fj",
"type": [
"VerifiableCredential",
"VaccinationCertificate"
],
"description": "COVID-19 Vaccination Certificate",
"name": "COVID-19 Vaccination Certificate",
"expirationDate": "2029-12-03T12:19:52Z",
"issuanceDate": "2019-12-03T12:19:52Z",
"issuer": "did:example:456",
"credentialSubject": {
"id": "urn:bnid:_:c14n2",
"type": "VaccinationEvent",
"batchNumber": "1183738569",
"countryOfVaccination": "NZ"
},
"proof": {
"type": "BbsBlsSignatureProof2020",
"created": "2021-02-18T23:04:28Z",
"nonce": "JNGovx4GGoi341v/YCTcZq7aLWtBtz8UhoxEeCxZFevEGzfh94WUSg8Ly/q+2jLqzzY=",
"proofPurpose": "assertionMethod",
"proofValue": "AB0GQA//jbDwMgaIIJeqP3fRyMYi6WDGhk0JlGJc/sk4ycuYGmyN7CbO4bA7yhIW/YQbHEkOgeMy0QM+usBgZad8x5FRePxfo4v1dSzAbJwWjx87G9F1lAIRgijlD4sYni1LhSo6svptDUmIrCAOwS2raV3G02mVejbwltMOo4+cyKcGlj9CzfjCgCuS1SqAxveDiMKGAAAAdJJF1pO6hBUGkebu/SMmiFafVdLvFgpMFUFEHTvElUQhwNSp6vxJp6Rs7pOVc9zHqAAAAAI7TJuDCf7ramzTo+syb7Njf6ExD11UKNcChaeblzegRBIkg3HoWgwR0hhd4z4D5/obSjGPKpGuD+1DoyTZhC/wqOjUZ03J1EtryZrC+y1DD14b4+khQVLgOBJ9+uvshrGDbu8+7anGezOa+qWT0FopAAAAEG6p07ghODpi8DVeDQyPwMY/iu2Lh7x3JShWniQrewY2GbsACBYOPlkNNm/qSExPRMe2X7UPpdsxpUDwqbObye4EXfAabgKd9gCmj2PNdvcOQAi5rIuJSGa4Vj7AtKoW/2vpmboPoOu4IEM1YviupomCKOzhjEuOof2/y5Adfb8JUVidWqf9Ye/HtxnzTu0HbaXL7jbwsMNn5wYfZuzpmVQgEXss2KePMSkHcfScAQNglnI90YgugHGuU+/DQcfMoA0+JviFcJy13yERAueVuzrDemzc+wJaEuNDn8UiTjAdVhLcgnHqUai+4F6ONbCfH2B3ohB3hSiGB6C7hDnEyXFOO9BijCTHrxPv3yKWNkks+3JfY28m+3NO0e2tlyH71yDX0+F6U388/bvWod/u5s3MpaCibTZEYoAc4sm4jW03HFYMmvYBuWOY6rGGOgIrXxQjx98D0macJJR7Hkh7KJhMkwvtyI4MaTPJsdJGfv8I+RFROxtRM7RcFpa4J5wF/wQnpyorqchwo6xAOKYFqCqKvI9B6Y7Da7/0iOiWsjs8a4zDiYynfYavnz6SdxCMpHLgplEQlnntqCb8C3qly2s5Ko3PGWu4M8Dlfcn4TT8YenkJDJicA91nlLaE8TJbBgsvgyT+zlTsRSXlFzQc+3KfWoODKZIZqTBaRZMft3S/",
"verificationMethod": "did:example:123#key-1"
}
}
],
"presentation_submission": {
"id": "1d257c50-454f-4c96-a273-c5368e01fe63",
"definition_id": "32f54163-7166-48f1-93d8-ff217bdb0654",
"descriptor_map": [
{
"id": "vaccination_input",
"format": "ldp_vp",
"path": "$.verifiableCredential[0]"
}
]
},
"proof": {
"type": "Ed25519Signature2018",
"verificationMethod": "did:example:123#key-0",
"created": "2021-05-14T20:16:29.565377",
"proofPurpose": "authentication",
"challenge": "3fa85f64-5717-4562-b3fc-2c963f66afa7",
"jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..7M9LwdJR1_SQayHIWVHF5eSSRhbVsrjQHKUrfRhRRrlbuKlggm8mm_4EI_kTPeBpalQWiGiyCb_0OWFPtn2wAQ"
}
}
}
}
]
}
For context on the Vaccination object passed, see the W3C-CCG Vaccination Vocabulary, from which the example is drawn.
§ Step 5 - Ack Presentation
Once the verifier validates the presentation, it MAY send an Acknowledgement message back to the prover.
{
"type":"https://didcomm.org/present-proof/3.0/ack",
"id":"e2f3747b-41e8-4e46-abab-ba51472ab1c3",
"pthid":"95e63a5f-73e1-46ac-b269-48bb22591bfa",
"from":"did:example:verifier",
"to":["did:example:prover"],
"body":{
"status":"OK"
}
}
The body
property of an Acknowledgement
message MUST contain a status
property. The value of this property MUST be one of the statuses defined
here.
§ Appendix
§ Out of Scope
The following are items that were considered “out of scope” for v0.1, but which may be considered for future versions:
§ Deterministic rendering of the JSON-LD frame object
Within the presentation_definition
object the input_descriptor
describes
specifically which data elements are requested by the verifier. There may be a
deterministic process that can be applied to input_descriptors
to generate the
frame
object, however that work is out of scope and not required at this
stage. The input_descriptors
describe where the properties in the selective
disclosure credential are and the frame
describes how to derive that selective
disclosure credential.
§ Additional transport layers
It is anticipated that future versions of this specification will describe how to exchange presentations using a number of different transport protocols. For this version, anything other than the subset of DIDComm V2 that is described here is out of scope.
§ Linked Data Signature Suite Definitions
The specific cryptographic operations, and suite definitions are out of scope for this spec. Please consider contributing to them here.
§ DIDComm ECDH-1PU and authenticated encryption
Defining authenticated encryption is out of scope for this specification. This specification currently relies on elements of DIDComm V2, which is currently being drafted. Due to instability in some of the specifications relied on by DIDComm V2, there is currently no support in DIDComm for authenticated encryption of messages, specifically the ECDH-1PU methodology. We anticipate that this capability will be introduced in DIDComm V2 as it reaches maturity and we advise those interested in the topic to follow the progress there.