§ DIDComm Messaging

Specification Status: Editor’s Draft

Latest published version: identity.foundation/didcomm-messaging/spec

Editors: Sam Curren (Indicio), Tobias Looker (Mattr), Oliver Terbu (ConsenSys)

Contributors: Sam Curren (Indicio), Tobias Looker (MATTR), Oliver Terbu (ConsenSys), Kyle Den Hartog (MATTR), Baha Shaaban (SecureKey), Drummond Reed (Evernym), Steve McCown (Anonyome Labs), Troy Ronda (SecureKey), George Aristy (SecureKey), Vyacheslav Gudkov (DSR), Alexander Shcherbakov (DSR), Alexander Martynov (DSR), Daniel Buchner (Microsoft), Devin Fisher (Evernym), Orie Steele (Transmute), Brian Richter (Aviary Tech), Juan Caballero (Spruce), @liormargalit, Timo Glastra (Animo Solutions), Andrew Whitehead (Government of British Columbia), Nader Helmy (MATTR), Markus Sabadello (Danube Tech), Patrick McClurg (SICPA), Stephen Curran (Government of British Columbia), Daniel Hardman (SICPA)

Participate:
GitHub repo
File a bug
Commit history

§ Purpose and Scope

The purpose of DIDComm Messaging is to provide a secure, private communication methodology built atop the decentralized design of DIDs.

Other robust mechanisms for secure communication already exist. However, most rely on key registries, identity providers, certificate authorities, browser or app vendors, or similarly centralized assumptions. They also tend to be tied to a single transport, making it difficult to use the same solution for human and machine conversations, online and offline, simplex and duplex, across a broad set of modalities. The net result is that they perpetuate an asymmetry between institutions and ordinary people. The former maintain certificates and always-connected servers, and publish APIs under terms and conditions they dictate; the latter suffer with usernames and passwords, poor interoperability, and a Hobson’s choice between privacy and convenience.

DIDComm Messaging can fix this. Using DIDComm Messaging, individuals on semi-connected mobile devices become full peers of highly available web servers operated by IT experts. Registration is self-service, intermediaries require little trust, and no terms and conditions apply.

DIDComm Messaging enables higher-order protocols that inherit its security, privacy, decentralization, and transport independence. Examples include exchanging verifiable credentials, creating and maintaining relationships, buying and selling, scheduling events, negotiating contracts, voting, presenting tickets for travel, applying to employers or schools or banks, arranging healthcare, and playing games. Like web services atop HTTP, the possibilities are endless; unlike web services atop HTTP, many parties can participate without being clients of a central server, and they can use a mixture of connectivity models and technologies.

§ Overview

To understand how DIDComm Messaging works, consider a situation where Alice wants to negotiate with Bob to sell something online. Because DIDComm Messaging, not direct human communication, is the methodology in this example, Alice’s software agent and Bob’s software agent are going to exchange a series of messages.

Alice may just press a button and be unaware of details, but underneath, her agent begins by preparing a plaintext JSON message about the proposed sale. The particulars are irrelevant here, but would be described in the spec for a higher-level “sell something” protocol that takes DIDComm Messaging as its foundation. Alice’s agent then looks up Bob’s DID Doc to access two key pieces of information:

Now Alice’s agent uses Bob’s public key to encrypt the plaintext so that only Bob’s agent can read it, adding authentication with its own private key. The agent arranges delivery to Bob. This “arranging” can involve various hops and intermediaries. It can be complex. (See Routing in the Implementers Guide.)

Bob’s agent eventually receives and decrypts the message, authenticating its origin as Alice using her public key. It prepares its response and routes it back using a reciprocal process (plaintext → lookup endpoint and public key for Alice → encrypt with authentication → arrange delivery).

That’s the essence, in the most common scenarios. However, it does not fit all DIDComm Messaging interactions:

Before we provide more details, let’s explore what drives the design of DIDComm Messaging.

§ Specific Requirements

The DIDComm Messaging design attempts to be:

  1. Secure (tamper-proof; uses best-of-breed crypto; allows parties to talk both on and off the record.)
  2. Private (third parties can’t learn who’s communicating about what, when; lets sender be anonymous to recipient)
  3. Decentralized (derives trust for encryption, signing, authn, and authz from control of DIDs rather than oracles like CAs, IDPs, etc; usable at the edge)
  4. Transport-agnostic (usable over HTTPS 1.x and 2.0, WebSockets, BlueTooth, chat, push notifications, libp2p, AMQP, SMTP, NFC, sneakernet, snail mail; supports both simplex and duplex; works offline; doesn’t assume client-server or synchronous or real-time; allows paired or n-wise or public broadcast usage)
  5. Routable (like email, Alice can talk to Bob without a direct connection to Bob; allows mixed and dynamic transports; passes through mix networks and other generic infrastructure that sees only payload BLOBs)
  6. Interoperable (works across programming languages, blockchains, vendors, OS/platforms, networks, legal jurisdictions, geos, cryptographies, and hardware–as well as across time; avoids vendor lock-in)
  7. Extensible (lets developers start simple without heavy learning or dependencies; customize easily; facilitates higher-level protocols that inherit DIDComm Messaging’s guarantees)
  8. Efficient (doesn’t waste bandwidth, battery, storage space, or CPU)

§ Ramifications

As a list of buzz words, this may elicit nods rather than surprise. However, design tradeoffs are inevitable, and several of these items have noteworthy ramifications.

§ Message-Based, Asynchronous, and Simplex

The dominant paradigm in mobile and web development today is duplex request-response. You call an API with certain inputs, and you get back a response with certain outputs over the same channel, shortly thereafter. This is the world of OpenAPI (Swagger), and it has many virtues.

Unfortunately, many agents are not good analogs to web servers. They may be mobile devices that turn off at unpredictable intervals and that lack a stable connection to the network. They may need to work peer-to-peer, when the internet is not available. They may need to interact in time frames of hours or days, not with 30-second timeouts. They may not listen over the same channel that they use to talk.

Because of this, the fundamental paradigm for DIDComm Messaging is message-based, asynchronous, and simplex. Alice’s Agent sends a message over channel A. Sometime later, it may receive a response from Bob’s Agent over channel B. This is much closer to an email paradigm than a web paradigm.

On top of this foundation, it is possible to build elegant, synchronous request-response interactions. All of us have interacted with a friend who’s emailing or texting us in near-realtime. However, interoperability begins with a least-common-denominator assumption that’s simpler.

§ Message-Level Security, Reciprocal Authentication

The security and privacy goals, and the asynchronous+simplex design decision, break familiar web assumptions in another way. Servers are commonly run by institutions, and we authenticate them with certificates. People and things are usually authenticated to servers by some sort of login process quite different from certificates, and this authentication is cached in a session object that expires. Furthermore, web security is provided at the transport level (TLS); it is not an independent attribute of the messages themselves.

In a partially disconnected world where a communication channel is not assumed to support duplex request-response, and where the security can’t be ignored as a transport problem, traditional TLS, login, and expiring sessions are impractical. Furthermore, centralized servers and certificate authorities perpetuate a power and UX imbalance between servers and clients that doesn’t fit with the peer-oriented DIDComm Messaging.

DIDComm Messaging uses public key cryptography, not certificates from some parties and passwords from others. Its security guarantees are independent of the transport over which it flows. It is sessionless (though sessions can easily be built atop it). When authentication is required, all parties do it the same way.

§ Message Types

This specification discusses messages in three different formats. The casual phrase DIDComm Messaging is ambiguous, but usually refers to DIDComm Messaging encrypted messages (the outermost box in the diagram below). These will constitute the vast majority of network traffic in most DIDComm Messaging deployments, and they are responsible for security guarantees in the system. However, the role of encrypted messages cannot be understood without reference to the simpler formats they contain.

DIDComm envelopes

§ Media Types

Media types are based on the conventions of RFC6838. Similar to RFC7515, the application/ prefix MAY be omitted and the recipient MUST treat media types not containing / as having the application/ prefix present.

§ DIDComm Plaintext Messages

A DIDComm Messaging message in its plaintext form, not packaged into any protective envelope, is known as a DIDComm plaintext message. Plaintext messages lack confidentiality and integrity guarantees, and are repudiable. They are therefore not normally transported across security boundaries. However, this may be a helpful format to inspect in debuggers, since it exposes underlying semantics, and it is the format used in this specification to give examples of headers and other internals. Depending on ambient security, plaintext may or may not be an appropriate format for DIDComm Messaging data at rest.

When higher-level protocols are built atop DIDComm Messaging, applications remove the protective envelope(s) and process the plaintext that’s inside. Specifications for higher-level protocols typically document message structure and provide examples in this format; protective envelopes are assumed but ignored as a low-level detail.

The media type for a generic DIDComm plaintext message MUST be application/didcomm-plain+json. DIDComm plaintext messages are also correctly understood as JWM content (see Plaintext Message Structure, below) and the media type MUST be set in the typ property of the DIDComm plaintext message header.

When persisted as a file or attached as a payload in other contexts, the file extension for DIDComm plaintext messages SHOULD be dcpm, giving a globbing pattern of *.dcpm; this SHOULD be be read as “Star Dot D C P M” or as “D C P M” files. We imagine people will reference this media type by saying, “I am looking at a DIDComm Plaintext Message file”, or “This database record is in DIDComm Plaintext format”, or “Does my editor have a DIDComm Plaintext Message plugin?” A possible icon for this file format depicts green JSON text in a message bubble (svg | 256x256 | 128x128 | 64x64):

DIDComm Plaintext Message Icon

§ DIDComm Signed Message

A DIDComm signed message is a signed JWM (JSON Web Messages) envelope that associates a non-repudiable signature with the plaintext message inside it.

DIDComm signed messages are not necessary to provide message integrity (tamper evidence), or to prove the sender to the recipient. Both of these guarantees automatically occur with the authenticated encryption in DIDComm encrypted messages. DIDComm signed messages are only necessary when the origin of plaintext has to be provable to third parties, or when the sender can’t be proven to the recipient by authenticated encryption because the recipient is not known in advance (e.g., in a broadcast scenario). Adding a signature when one is not needed can degrade rather than enhance security because it relinquishes the sender’s ability to speak off the record. We therefore expect DIDComm signed messages to be used in a few cases, but not as a matter of course.

When a message is both signed and encrypted, the plaintext is signed, and then the signed envelope is encrypted. The opposite order is not used, since it would imply that the signer committed to opaque data (which is unsafe and undermines non-repudiation).

The media type of a DIDComm signed message MUST be application/didcomm-signed+json.

The media type of the envelope MUST be set in the typ property of the JWS.

When persisted as a file or attached as a payload in other contexts, the file extension for DIDComm signed messages SHOULD be dcsm, giving a globbing pattern of *.dcsm; this SHOULD be be read as “Star Dot D C S M” or as “D C S M” files. A possible icon for this media type depicts a signed envelope (svg | 256x256 | 128x128 | 64x64):

DIDComm Signed Message Icon

§ DIDComm Encrypted Message

A DIDComm encrypted message is an encrypted JWM (JSON Web Messages) and hides its content from all but authorized recipients, discloses and proves the sender to exactly and only those recipients, and provides integrity guarantees. It is important in privacy-preserving routing. It is what normally moves over network transports in DIDComm Messaging applications, and is the safest format for storing DIDComm Messaging data at rest.

The media type of a non-nested DIDComm encrypted message MUST be application/didcomm-encrypted+json.

Note: If future versions of this spec allow binary encodings, variations like application/didcomm-encrypted+cbor (see CBOR RFC 7049, section 7.5), application/didcomm-encrypted+msgpack, or application/didcomm-encrypted+protobuf may become reasonable. In the future, specifications that encompass communications patterns other than messaging — DIDComm Multicast or DIDComm Streaming, for example — might use a suffix: application/didcomm-encrypted-multicast or similar.

The media type of the envelope MUST be set in the typ property of the JWE.

When persisted as a file or attached as a payload in other contexts, the file extension for DIDComm encrypted messages SHOULD be dcem, giving a globbing pattern of *.dcem; this SHOULD be read as “Star Dot D C E M” or as “D C E M” files. A possible icon for this file format depicts an envelope with binary overlay, protected by a lock (svg | 256x256 | 128x128 | 64x64):

DIDComm Encrypted Message Icon

§ Plaintext Message Structure

DIDComm plaintext messages are based on JWM (JSON Web Messages). A message has a basic structure that specifies the message type, id, and other attributes common to all messages. These common attributes appear at the top level of a DIDComm plaintext message, and are called headers. A DIDComm plaintext message also includes attributes specific to the message type. Type specific message attributes are contained within the body attribute of a DIDComm plaintext message.

Prior to being sent to a recipient, the JWM is usually encrypted into a JWE according to the JWM specification.

The following example shows common elements of a DIDComm plaintext message. Further details and advanced usage are covered elsewhere in this spec.

{
  "typ": "application/didcomm-plain+json",
  "id": "1234567890",
  "type": "<message-type-uri>",
  "from": "did:example:alice",
  "to": ["did:example:bob"],
  "created_time": 1516269022,
  "expires_time": 1516385931,
  "body": {
    "messagespecificattribute": "and its value"
  }
}

§ Message Headers

A DIDComm plaintext message conveys most of its application-level data inside a JSON body object that is a direct child of the message root. The structure inside body is predicted by the value of the message’s type attribute, and varies according to the definition of the protocol-specific message in question. Each type of message will have its own body.

However, some attributes are common to many different message types. When metadata about a message means the same thing regardless of context, and when it is susceptible to generic rather than message-specific handling, that metadata can be placed in headers. Headers are siblings of body and may be added to any message type. They are encrypted and decrypted along with body and therefore have an identical audience.

Headers in DIDComm Messaging are intended to be extensible in much the same way that headers in HTTP or SMTP are extensible. A few headers are predefined:

The following table provides an overview of using the media type properties in supported DIDComm Messaging messages:

Envelope typ
Authcrypted and/or anoncrypted application/didcomm-encrypted+json
Signed and anoncrypted application/didcomm-encrypted+json
Signed application/didcomm-signed+json
Plaintext application/didcomm-plain+json

When Alice sends the same message to Bob and Carol, it is by inspecting this header that Bob and Carol learn that the message was sent to both of them. If the header is omitted, each recipient can only assume they are the only recipient (much like an email sent only to BCC: addresses).

The to header cannot be used for routing, since it is encrypted at every intermediate point in a route. Instead, the forward message contains a next attribute in its body that specifies the target for the next routing operation.

With respect to headers, DIDComm Messaging follows the extensibility pattern established by the JW* family of standards. A modest inventory of predefined “header” fields is specified, as shown above. Additional fields with unreserved names can be added at the discretion of producers and consumers of messages; any software that doesn’t understand such fields SHOULD ignore them and MUST NOT fail because of their inclusion in a message. This is appropriate for a simple, flat data model.

Aligning with RFC 6648, DIDComm Messaging explicitly rejects the X-* headers convention that creates divergent pseudo-standards; if a new header needs broad support, proper standardization is required. Since we expect header fields to be small in number and modest in complexity, we expect this sort of powerful extensibility to be unnecessary in most cases.

§ Simple vs. Structured

Headers can be simple (mapping a header name to an integer or a string) or structured (mapping a header name to JSON substructure – an array or JSON object). When defining a new header type, the following guidelines apply:

§ Relationship to JSON-LD

The problem domain of DIDComm Messaging intersects with other aspects of decentralized identity, where JSON-LD plays a role in some standards. Thus it may be natural to wonder about DIDComm Messaging’s relationship to JSON-LD and to the rich semantics and extensibility features it offers. The short answer is that DIDComm Messaging is not dependent on JSON-LD, but it is compatible with it. We expect these two technologies to remain mostly orthogonal.

The body of a message – everything inside the body object – is different. Here, there is substantial variety and complexity. Structures may be sophisticated graphs, represented with nested objects and arrays. JSON-LD is not required at this level, either. However, it is available, and may be appropriate for certain use cases where extensibility is an important feature. JSON-LD usage, if it occurs, SHOULD be a declared feature of a protocol as a whole, not an ad hoc extension to arbitrary individual messages, and MUST be signalled by the inclusion of a @context inside body. Unless a protocol declares a JSON-LD dependency, the same rules apply to JSON-LD-isms as apply to any other unrecognized structure in a DIDComm Messaging message: additional fields can be added to any part of message structure, SHOULD be ignored if not understood, and MUST NOT be the basis of failure by recipients.

§ DID Rotation

DIDComm Messaging is based on DIDs and their associated DID Documents. Changes to keys and endpoints are the concern of each DID method and are utilized but not managed by DIDComm Messaging. DID Rotation serves a very specific and narrow need to switch from one DID method to another. This is very common at the beginning of a new DIDComm Messaging relationship when a public DID or a temporary DID passed unencrypted is rotated out for a DID chosen for the relationship. As rotation between one DID and another is outside the scope of any DID method, the details of DID Rotation are handled within DIDComm Messaging itself.

When a DID is rotated, the new DID is put into immediate use encrypting the message, and one additional attribute MUST be included as a message header:

When a message is received from an unknown DID, the recipient SHOULD check for existence of the from_prior header. The JWT in thefrom_prior attribute is used to extract the prior DID (iss) and is checked to verify the validity of the rotation. The recipient then associates the message with context related to the known sender. The new DID and associated DID Document information SHOULD be used for further communication.

The validity of the DID Rotation is verified by checking the JWT signature against the key indicated in the kid header parameter. The indicated key MUST be authorized in the DID Document of the prior DID (iss).

The from_prior attribute MUST be included in messages sent until the party rotating receives a message sent to the new DID. If multiple messages are received to containing the rotation headers after being processed by the recipient, they MAY be ignored.

§ JWT Details

The JWT is constructed as follows, with appropriate values changed.

Header:

{
  "typ": "JWT",
  "alg": "EdDSA",
  "crv": "ED25519",
  "kid": "<key id authorized in prior DID>"
}

Payload:

{
  "sub": "<new DID URI>",
  "iss": "<prior DID URI>",
  "iat": 1516239022 //datetime of the rotation, not message
}

§ Example Message Rotating DID

{
  "typ": "application/didcomm-plain+json",
  "id": "1234567890",
  "type": "<message-type-uri>",
  "from": "did:example:alice2",
  "from_prior": "<JWT with sub:did:example:alice2 and iss:did:example:alice>",
  "to": ["did:example:bob"],
  "created_time": 1516269022,
  "expires_time": 1516385931,
  "body": {
    "messagespecificattribute": "and its value"
  }
}

§ Rotation Limitations

§ Negotiating Compatibility

When parties want to communicate via DIDComm, a number of mechanisms must align. These include:

  1. The type of service endpoint used by each party
  2. The key types used for encryption and/or signing
  3. The format of the encryption and/or signing envelopes
  4. The encoding of plaintext messages
  5. The protocol used to forward and route
  6. The protocol embodied in the plaintext messages

Although DIDComm allows flexibility in each of these choices, it is not expected that a given DIDComm implementation will support many permutations. Rather, we expect a few sets of choices that commonly go together. We call a set of choices that work well together a profile. Profiles are identified by a string that matches the conventions of IANA media types, but they express choices about plaintext, encryption, signing, and routing in a single value. The following profile identifiers are defined in this version of the spec:

§ Defined Profiles

Profiles are named in the accept section of a DIDComm service endpoint and in an out-of-band message. When Alice declares that she accepts didcomm/v2, she is making a declaration about more than her own endpoint. She is saying that all publicly visible steps in an inbound route to her will use the didcomm/v2 profile, such that a sender only has to use didcomm/v2 choices to get the message from Alice’s outermost mediator to Alice’s edge. It is up to Alice to select and configure mediators and internal routing in such a way that this is true for the sender.

§ Message Encryption

DIDComm supports two types of message encryption: Authenticated Sender Encryption and Anonymous Sender Encryption. Both forms are encrypted to the recipient, but only Authenticated Sender Encryption provides assurances of who the sender is.

The encrypted form of a JWM is a JWE. The JOSE family defines JSON Web Algorithms (JWAs) which standardize certain cryptographic operations that are related to preparing JOSE structures. For the purposes of interoperability, DIDComm messaging does not support all JWAs, rather it takes a subset of the supported algorithms that are applicable for the following cases around secure messaging. These supported algorithms are listed here.

§ Sender Authenticated Encryption

For an encrypted DIDComm Message, the JWA of ECDH-1PU defined by draft MUST be used within the structure of a JWE.

§ Anonymous Encryption

When a sender would like to encrypt a message for a recipient or multiple recipients but not be authenticated by the recipients as the party who encrypted the message, the JWA of ECDH-ES defined by RFC 7518 SHOULD be used within the structure of a JWE.

Anonymous Encryption removes authenticated encryption, a significant benefit of the DIDComm specification. Use of Anonymous Encryption SHOULD NOT be paired with a method of message authentication other than Authenticated Encryption as defined in this specification. Further discussion of message authentication can be found in the Implementation Guide.

§ Curves and Content Encryption Algorithms

For the keys involved in key agreement, the following elliptic curves MUST be supported.

Curve Description
X25519 The underlying curve is actually Curve25519, however when used in the context of Diffie-Hellman the identifier of X25519 is used
P-384 NIST defined P-384 elliptic curve
P-256 NIST defined P-256 elliptic curve - deprecated in favor of P-384

For content encryption of the message, the following algorithms MUST be supported.

Algorithm(JWA) Description Authcrypt/Anoncrypt
XC20P XChaCha20Poly1305 with a 256 bit key Anoncrypt
A256GCM AES256-GCM with a 256 bit key Anoncrypt
A256CBC-HS512 AES256-CBC + HMAC-SHA512 with a 512 bit key Authcrypt/Anoncrypt

TODO: Include language about safe nonce considerations.

§ Key Wrapping Algorithms

KW Algorithm Curve (epk crv) key type (epk kty) Description
ECDH-ES+A256KW P-256 EC ECDH-ES key wrapping using key with NIST defined P-256 elliptic curve to create a 256 bits key as defined in 7518
ECDH-ES+A256KW P-384 EC ECDH-ES key wrapping using key with NIST defined P-384 elliptic curve to create a 256 bits key as defined in 7518
ECDH-ES+A256KW P-521 EC ECDH-ES key wrapping using key with NIST defined P-521 elliptic curve to create a 256 bits key as defined in 7518
ECDH-ES+A256KW X25519 OKP ECDH-ES with X25519 (RFC7748 section 5) to create a 256 bits key. The underlying curve is actually Curve25519, however when used in the context of Diffie-Hellman the identifier of X25519 is used
ECDH-1PU+A256KW P-256 EC ECDH-1PU key wrapping using key with NIST defined P-256 elliptic curve to create a 256 bits key as defined in ecdh-1pu
ECDH-1PU+A256KW P-384 EC ECDH-1PU key wrapping using key with NIST defined P-384 elliptic curve to create a 256 bits key as defined in ecdh-1pu
ECDH-1PU+A256KW P-521 EC ECDH-1PU key wrapping using key with NIST defined P-521 elliptic curve to create a 256 bits key as defined in ecdh-1pu
ECDH-1PU+A256KW X25519 OKP ECDH-1PU X25519 (RFC7748 section 5) to create a 256 bits key as defined in ecdh-1pu

§ Perfect Forward Secrecy

The mapping of the Perfect Forward Secrecy concepts to DIDComm requires some discussion. Please refer to the Implementers Guide for more details.

§ Man in the middle

DIDComm’s profile with respect to man-in-the-middle attacks is easily misunderstood. Please refer to the Implementers Guide for more details.

§ Key IDs kid and skid headers references in the DID document

Keys used by DIDComm envelopes MUST be sourced from the DIDs exchanged between two agents. Specifically, both sender and recipients keys MUST be retrieved from the DID document’s KeyAgreement verification section as per the DID Document Keys definition.

When Alice is preparing an envelope intended for Bob, the packing process should use a key from both hers and Bob’s DID document’s KeyAgreement section.

Assuming Alice has a DID Doc with the following KeyAgreement definition (source: DID V1 Example 17):

{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:example:123456789abcdefghi",
  ...
  "keyAgreement": [
    // this method can be used to perform key agreement as did:...fghi
    "did:example:123456789abcdefghi#keys-1",
    // this method is *only* approved for key agreement usage, it will not
    // be used for any other verification relationship, so its full description is
    // embedded here rather than using only a reference
    {
      "id": "did:example:123#zC9ByQ8aJs8vrNXyDhPHHNNMSHPcaSgNpjjsBYpMMjsTdS",
      "type": "X25519KeyAgreementKey2019", // external (property value)
      "controller": "did:example:123",
      "publicKeyBase58": "9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE"
    }
  ],
  ...
}

The envelope packing process MUST set the skid header with value did:example:123456789abcdefghi#keys-1 in the envelope’s protected headers and fetch the underlying key to execute ECDH-1PU key derivation for content key wrapping.

Assuming she also has Bob’s DID document which happens to include the following KeyAgreement section:

{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:example:jklmnopqrstuvwxyz1",
  ...
  "keyAgreement": [
    {
      "id": "did:example:jklmnopqrstuvwxyz1#key-1",
      "type": "X25519KeyAgreementKey2019", // external (property value)
      "controller": "did:example:jklmnopqrstuvwxyz1",
      "publicKeyBase58": "9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE"
    }
  ],
  ...
}

Unless previously coordinated in a layer above DIDComm, the default recipients of the envelope MUST include all the KeyAgreement entries, representing Bob. The corresponding kid header for this recipient MUST have a DID URL pointing to a corresponding verification method in the DID document. This verification method MUST be associated with the KeyAgreement verification relationship and the verification material MUST be retrieved from the DID document to execute the ECDH-1PU key derivation for content key wrapping.

When Bob receives the envelope, the unpacking process on his end MUST resolve the skid protected header value using Alice’s DID doc’s KeyAgreement[0] in order to extract her public key. In Alice’s DID Doc example above, KeyAgreement[0] is a reference id, it MUST be resolved from the main VerificationMethod[] of Alice’s DID document (not shown in the example).

Once resolved, the unpacker will then execute ECDH-1PU key derivation using this key and Bob’s own recipient key found in the envelope’s recipients[0] to unwrap the content encryption key.

§ Protecting the Sender Identity

When employing authenticated encryption, the header of the encrypted message envelope must necessarily reveal the key identifier used by the sender of the message (the skid). This is used by recipients to resolve the sender’s public key material in order to decrypt the message. In the case of communication between two public DIDs, this may allow outside parties to directly correlate the sender of an encrypted message to a known identity.

If two communicating parties establish single-purpose DIDs (peer DIDs) for secure communication, then the correlation to any publicly known identities may be limited, although multiple messages referencing the same DIDs will still provide an opportunity for correlation.

A layer of anonymous encryption (employing ECDH-ES) may be applied around an authenticated encryption envelope (employing ECDH-1PU), obscuring the sender’s identity for all but the recipient of the inner envelope. In the case of a message forwarded via mediators, anonymous encryption is automatic.

§ ECDH-1PU key wrapping and common protected headers

When using authcrypt, the 1PU draft requires mandates the use of AES_CBC_HMAC_SHA family of content encryption algorithms. To meet this requirement, JWE messages MUST use common epk, apu, apv and alg headers for all recipients. They MUST be set in the protected headers JWE section.

As per this requirement, the JWE building must first encrypt the payload then use the resulting tag as part of the key derivation process when wrapping the cek.

To meet this requirement, the above headers must be defined as follows:

A final note about skid header: since the 1PU draft does not require this header, authcrypt implementations MUST be able to resolve the sender kid from the APU header if skid is not set.

§ Examples

While the details of encrypting a JWM into a JWE are included in the JWM spec, a few examples are included here for clarity.

See section Appendix C.3 for examples.

§ Message Signing

A DIDComm message can be signed, either in conjunction with encryption or independently if the message will remain unencrypted.

If a message is signed and encrypted to add non-repudiation, it must be signed prior to encryption. This is known as a nested JWM.

§ Algorithms

When a sender would like for a message to feature a non-repudiable digital signature the JWA’s defined below can be used within the structure of a JWS.

Implementations MUST be able to verify all of the following algorithms and MUST support signing with at least one.

Algorithm(JWA) Description
EdDSA (with crv=Ed25519) Elliptic curve digital signature with edwards curves and SHA-512
ES256 Elliptic curve digital signature with NIST p-256 curve and SHA-256
ES256K Elliptic curve digital signature with Secp256k1 keys.

§ Construction

Construct a JWS with the following header:

   {"typ":"JWM",
    "kid":"Ef1sFuyOozYm3CEY4iCdwqxiSyXZ5Br-eUDdQXk6jaQ",
    "alg":"ES256"}

The JWS payload is the Base64url encoded JWM.

When transmitted in a normal JWM fashion, the JSON Serialization MUST be used.

§ Verification

When verifying the signature, an additional check must be performed after verifying the JWS. The key used in the signature must be authorized to do so in the Document resolved from the DID in the from attribute. If the key is not authorized for the signature, the signature is invalid.

§ Application

§ Non-Repudiation

DIDComm Encrypted messages are repudiable. If non-repudiation is required for a particular protocol message, the message MUST be signed before encryption.

§ Tamper Resistant OOB Messages

Out of Band Messages may be signed to provide tamper resistance.

§ DID Anchoring

Signing can allow DIDs to be anchored via keys not usable for encrypting DIDComm messages.

§ Examples

See section Appendix C.2. for examples.

§ When Problems Happen

Detecting, reporting, and handling problems is a challenge in any system. The challenge deepens when systems are decentralized, consist of components written by independent teams, and communicate asynchronously. This is the landscape over which DIDComm operates.

To the extent that it is practical, DIDComm must surface problems, and their supporting contexts, to people and/or automated systems that want to know about them (and perhaps separately, to entities that can actually fix them). (“Practical” here means that it can be done with reasonable effort and without undermining DIDComm’s security, privacy, or other technical goals.)

DIDComm offers several tools to deal with these issues. Individually they are easy to use; collectively they offer attractive robustness and clarity.

§ Low-level tools

§ Timeouts

In many cases, a DIDComm message SHOULD use the expires_time header to announce when its sender will consider the message invalid. This allows for state to be reset in a predictable way. The expires_time header is so common that it is discussed in the general Message Headers section of the spec. Best practice with timeouts is discussed in the Implementers Guide.

§ ACKs

Any DIDComm message MAY use the please_ack header to request a read receipt from a recipient. Cooperative parties who wish to honor this request MUST include an ack header on a subsequent message, where the value of the header is an array that contains the id of one or more messages being acknowledged.

§ Threads

Any DIDComm message that continues a previously begun application-level protocol MUST use a thid property that associates it with the prior context. This context is vital for error handling. See Threading.

In addition, messages MAY use the Advanced Sequencing extension to detect gaps in delivery or messages arriving out of order.

§ Problem reports

DIDComm features a standard mechanism for reporting problems to other entities. These could be parties in the active protocol, or logging products, or internal health monitors, or human tech support staff. Reporting problems remotely is not always possible (e.g., when a sender lacks a route to the other party, or when a recipient’s crypto is incompatible with a sender’s). Using this mechanism is therefore not a general requirement of DIDComm, but it is a best practice because it improves robustness and human experience. (But be aware of some cybersecurity considerations.)

Other entities are notified of problems by sending a simple message called a problem report that looks like this:

{
  "type": "https://didcomm.org/report-problem/2.0/problem-report",
  "id": "7c9de639-c51c-4d60-ab95-103fa613c805",
  "pthid": "1e513ad4-48c9-444e-9e7e-5b8b45c5e325",
  "body": {
    "code": "e.p.xfer.cant-use-endpoint",
    "comment": "Unable to use the {1} endpoint for {2}.",
    "args": [
      "https://agents.r.us/inbox",
      "did:sov:C805sNYhMrjHiqZDTUASHg"
    ],
    "escalate_to": "mailto:[email protected]"
  }
}

The pthid header MUST be included with problem reports. Its value is the thid of the thread in which the problem occurred. (Thus, the problem report begins a new child thread, of which the triggering context is the parent. The parent context can react immediately to the problem, or can suspend progress while troubleshooting occurs.)

The code field is worthy of its own section; see below.

The optional comment field contains human-friendly text describing the problem. The text MUST be statically associated with code, meaning that each time circumstances trigger a problem with the same code, the value of comment will be the same. This enables localization and cached lookups, and it has some cybersecurity benefits. The value of comment supports simple interopolation with args (see next), where args are referenced as {1}, {2}, and so forth.

The optional args field contains situation-specific values that are interpolated into the value of comment, providing extra detail for human readers. Each unique problem code has a definition for the args it takes. In this example, e.p.xfer.cant-use-endpoint apparently expects two values in args: the first is a URL and the second is a DID. Missing or null args MUST be replaced with a question mark character (?) during interpolation; extra args MUST be appended to the main text as comma-separated values.

The optional escalate_to field provides a URI where additional help on the issue can be received.

§ Problem Codes

Perhaps the most important feature of each problem report message is its code field. This required value is the main piece of data that recipient software uses to automate reactions. It categorizes what went wrong.

Problem codes are lower kabob-case. They are structured as a sequence of tokens delimited by the dot character ., with the tokens being more general to the left, and more specific to the right. Because recipients can do matching by prefix instead of full string, a recipient can recognize and handle broad semantics even if the trailing tokens of the string contain unfamiliar details. In the example below, for example, relatively sophisticated handling is possible even if a recipient only recognizes the e.p.xfer. portion of the code.

problem code structure

§ Sorter

The leftmost component of a problem code is its sorter. This is a single character that tells whether the consequence of the problem are fully understood. Two values are defined:

Note: What distinguishes an error from a warning is clarity about its consequences, not its severity. This clarity is inherently contextual. A warning might prove to be just as problematic as an error, once it’s fully evaluated. This implies that the same problem can be an error in some contexts, and a warning in others. In our example above, we imagined a payment failure as an error. But if this problem occurs in a context where retries are expected, and there’s a good chance of future success, perhaps the problem is a warning the first three times it’s reported — then becomes an error when all hope is lost.

§ Scope

Reading left to right, the next token in a problem code is called the scope. This gives the sender’s opinion about how much context should be undone if the problem is deemed an error.

Note: A problem always sorts according to the most pessimistic view that is taken by participants in the protocol. If the sender of a problem report deems it an error, then it is. If the sender deems it a warning, but a recipient with greater context decides that it clearly frustrates their goals, then it becomes an error; see Replying to Warnings. Thus, scope is relevant even if the sender chooses a problem code that starts with w.)

The possible values of scope are:

§ Descriptors

After the sorter and the scope, problem codes consist of one or more descriptors. These are kabob-case tokens separated by the . character, where the semantics get progressively more detailed reading left to right. Senders of problem reports SHOULD include at least one descriptor in their problem code, and SHOULD use the most specific descriptor they can. Recipients MAY specialize their reactions to problems in a very granular way, or MAY examine only a prefix of a problem code.

The following descriptor tokens are defined. They can be used by themselves, or as prefixes to more specific descriptors. Additional descriptors — particularly more granular ones — may be defined in individual protocols.

Token Value of comment string Notes
trust Failed to achieve required trust. Typically this code indicates incorrect or suboptimal behavior by the sender of a previous message in a protocol. For example, a protocol required a known sender but a message arrived anoncrypted instead — or the encryption is well formed and usable, but is considered weak. Problems with this descriptor are similar to those reported by HTTP’s 401, 403, or 407 status codes.
trust.crypto Cryptographic operation failed. A cryptographic operation cannot be performed, or it gives results that indicate tampering or incorrectness. For example, a key is invalid — or the key types used by another party are not supported — or a signature doesn’t verify — or a message won’t decrypt with the specified key.
xfer Unable to transport data. The problem is with the mechanics of moving messages or associated data over a transport. For example, the sender failed to download an external attachment — or attempted to contact an endpoint, but found nobody listening on the specified port.
did DID is unusable. A DID is unusable because its method is unsupported — or because its DID doc cannot be parsed — or because its DID doc lacks required data.
msg Bad message. Something is wrong with content as seen by application-level protocols (i.e., in a plaintext message). For example, the message might lack a required field, use an unsupported version, or hold data with logical contradictions. Problems in this category resemble HTTP’s 400 status code.
me Internal error. The problem is with conditions inside the sender’s system. For example, the sender is too busy to do the work entailed by the next step in the active protocol. Problems in this category resemble HTTP’s 5xx status codes.
me.res A required resource is inadequate or unavailable. The following subdescriptors are also defined: me.res.net, me.res.memory, me.res.storage, me.res.compute, me.res.money
req Circumstances don’t satisfy requirements. A behavior occurred out of order or without satisfying certain preconditions — or circumstances changed in a way that violates constraints. For example, a protocol that books plane tickets fails because, halfway through, it is discovered that all tickets on the flight have been sold.
req.time Failed to satisfy timing constraints. A message has expired — or a protocol has timed out — or it is the wrong time of day/day of week.
legal Failed for legal reasons. An injunction or a regulatory requirement prevents progress on the workflow. Compare HTTP status code 451.

§ Replying to Warnings

When Alice sends a w.* problem report to Bob, and Bob decides that the warning is actually an error, he SHOULD reply to Alice to let her know about the consequences of his evaluation. Bob’s reply is another problem-report message. It looks very similar to Alice’s original, except:

§ Cascading Problems

Many problems may be experienced during a long-running or complex protocol. Implementers must have the option of tolerating and recovering from them, if we want robustness; perhaps several network retries will be followed by eventual success. However, care must be exercised to prevent situations where malformed or careless problem reports trigger infinite recursion or vicious cycles:

  1. Implementations SHOULD consider implementing a circuit breaker design pattern to prevent this problem.
  2. Timeouts SHOULD be used judiciously.
  3. Implementations SHOULD use their own configuration or judgment to establish some type of max error count as they begin a protocol instance. This limit could be protocol-specific, and could be evaluated per unit time (e.g., in a human chat protocol of infinite duration, perhaps the limit is max errors per hour rather than max errors across all time). If implementations establish such a limit, they SHOULD check to see whether this count has been exceeded, both when they receive and when they emit errors. If the limit is crossed as a result of a problem report they receive, they SHOULD send back a problem report with "code": "e.p.req.max-errors-exceeded" to abort the protocol. If the limit is crossed as a result of an error they are emitting, they MUST NOT emit the problem report for the triggering error; instead, they MUST emit a problem report with "code": "e.p.req.max-errors-exceeded" to abort the protocol. In either case, they MUST cease responding to messages that use the thid of that protocol instance, once this limit has been crossed.

§ Route Tracing

To troubleshoot routing issues, DIDComm offers a header, trace. Any party that processes a DIDComm plaintext message containing this header MAY do an HTTP POST of a route trace report to the URI in the header’s value.

Note: This mechanism is not intended to profile timing or performance, and thus does not cover the same problem space as technologies like OpenTracing. It also spans trust domains (paralleling a message’s journey from Alice to a web service hosting Bob’s endpoint, to Bob himself) – and thus differs in scope from in-house logging and monitoring technolgies like Splunk and Kibana. Although DIDComm tracing could be integrated with these other technologies, doing so in a methodical way is probably an antipattern; it may indicate a misunderstanding about its purpose as a tool for ad hoc debugging or troubleshooting between unrelated parties.

[TODO: describe the trace report.] For example, in a message for Bob that is double-wrapped (once for his external mediator and once for his cloud agent), three plaintext messages might contain trace headers:

  1. The outermost message, decrypted by Bob’s external mediator, containing forwarding instructions to Bob’s cloud agent.
  2. The center message, decrypted by Bob’s cloud agent, containing an inner encrypted payload and instructions to forward it to Bob’s DID.
  3. The inner message, seen by Bob’s iPhone.

If Alice, the sender of this message, includes a trace header on each one, and if handlers of this message along the route cooperate with her request to trace, then Alice can learn where in a route a message delivery is failing.

Tracing has security, privacy, and performance implications. Support for tracing is not required of DIDComm implementations, but it is recommended for parties that need sophisticated debugging. Parties that implement tracing MUST decide whether or not to honor trace requests based upon a policy that ensures accountability and transparency, and MUST default to reject tracing requests unless they have independent reason to believe that appropriate safeguards are in place.

§ Threading

DIDComm provides threading as foundation for extremely powerful protocol features. For background on the intent and best practices for threading, please see the Implementers Guide.

§ Message IDs

All plaintext DIDComm messages MUST have an id property, declared in the JWM header. A message without an id property SHOULD be considered invalid and SHOULD be rejected; it MUST NOT be interpreted as part of a multi-message interaction.

The value of id is a short (<=32 bytes) string consisting entirely of unreserved URI characters – meaning that it is not necessary to percent encode the value to incorporate it in a URI. Beyond this requirement, its format is not strongly constrained, but use of UUIDs (RFC 4122) is recommended. Because of the affinity for UUIDs, this field inherits UUID case-sensitivity semantics: it SHOULD be written in lower case but MUST be compared case-insensitively.

The value of an id property SHOULD be globally, universally unique; at the very least, it MUST be unique across all interactions visible to the set of parties that see a given set of interactions.

§ Threads

A thread is uniquely identified by a thread ID. The thread ID is communicated by including a thid header in the JWM plaintext of the message. The value of thid MUST conform to the same constraints as the value of id. The DIDComm plaintext message that begins a thread MAY declare this property for the new thread. If no thid property is declared in the first message of an interaction, the id property of the message MUST be treated as the value of the thid as well; that is, the message is interpreted as if both id and thid were present, containing the same value.

All subsequent messages in a thread MUST include a thid header that contains the same value as the thid set in the first message of the thread. Messages that do not share the same thid MUST NOT be considered a part of the same thread.

§ Parent Threads

When one interaction triggers another, the first interaction is called the parent of the second. This MAY be modeled by incorporating a pthid header in the JWM plaintext of the child. The value of the child’s pthid header MUST obey the same constraints as thid and id values.

Suppose a DIDComm-based protocol (and therefore, a thread of messages) is underway in which an issuer wants to give a credential to a holder. At a particular stage in this interaction, perhaps the issuer asks the prospective holder of the credential to pay for what they’re about to receive. For composability, encapsulation, reusability, and versioning reasons, negotiating and consummating payment is best modeled as a separable interaction from credential exchange — so a new sequence of messages (dedicated to payment) begins. In this example, the credential issuance interaction (message thread 1) is the parent of the payment interaction (message thread 2). The first message in thread 2 MUST contain a pthid header that references the thid from thread 1:

{
  "id": "new-uuid-for-payment-thread",
  "pthid": "id-of-old-credential-issuance-thread"
  // ...more headers and message content...
}

When a child protocol is a simple two-party interaction, mentioning the pthid in the first message of the child interaction is enough to establish context. However, in protocols involving more than two parties, the first message of the child protocol may not be seen by everyone, so simply mentioning pthid once may not provide enough context. Therefore, the rule is that each party in a child protocol MUST learn the identity of the parent thread via the first child protocol message they see. The simplest way to ensure this is to mention the pthid with every message in the child protocol.

§ DIDComm Message URIs

The id, thid, and pthid properties of any DIDComm message may be combined to form a URI that uniquely identifies the message (e.g., in debuggers, in log files, in archives). Such a scheme is out of scope for this spec, and support for it is OPTIONAL for implementers. This spec reserves the didcomm:// URI prefix for future work with semantics like these; it SHALL NOT be used for other purposes.

§ Gaps, Resends, and Sophisticated Ordering

Message IDs and threads can be used to build very powerful features for detecting missing and out-of-order messages — and to recovery from them. For more information, see the Implementers Guide.

§ Routing

§ Routing Protocol

§ Name and Version

The name of this protocol is “Routing Protocol”, and its version is “2.0”. It is uniquely identified by the PIURI:

https://didcomm.org/routing/2.0

§ Roles

There are 3 roles in the protocol: sender, mediator, and recipient. The sender emits messages of type forward to the mediator. The mediator unpacks (decrypts) the payload of an encrypted forward message and passes on the result (an opaque blob that probably contains a differently encrypted payload) to the recipient.

ordinary sequence

Note: the protocol is one-way; the return route for communication might not exist at all, or if it did, it could invert the roles of sender and receiver and use the same mediator, or it could use one or more different mediators, or it could use no mediator at all. This is a separate concern partly specified by the service endpoints in the DID docs of the sender and receiver, and partly explored in RFC 0092: Transports Return Route.

Note: When the mediator is the routing agent of a single identity subject like Alice, the logical receiver is Alice herself, but the physical receiver may manifest as multiple edge devices (a phone, a laptop, a tablet). From the perspective of this protocol, multiplexing the send from mediator to receiver is out of scope for interoperability–compatible and fully supported, but not required or specified in any way.

In this protocol, the sender and the receiver never interact directly; they only interact via the mediator.

The sender can decorate the forward message in standard DIDComm ways: using ~timing.expires_time, ~timing.delay_milli and ~timing.wait_until_time to introduce timeouts and delays, and so forth. However, the mediator is NOT required to support or implement any of these mixin semantics; only the core forwarding behavior is indispensable. If a mediator sees a decorator that requests behavior it doesn’t support, it MAY return a problem-report to the sender identifying the unsupported feature, but it is not required to do so, any more than other recipients of DIDComm messages would be required to complain about unsupported decorators in messages they receive.

[[TODO: needs revision when we decide how ACKs will work and whether explicit requests for an ACK will be conveyed via headers.]] One particular decorator is worth special mention here: ~please_ack. This decorator is intended to be processed by ultimate recipients, not mediators. If it were used with forward messages, it would impose a burden of backward-facing communication that mediators should not have. Furthermore, it could probe a delivery chain in a way that risks privacy for the receiver. Therefore, senders SHOULD NOT use this on forward messages, and mediators SHOULD NOT honor it if present. If a sender wishes to troubleshoot, the message tracing mechanism is recommended.

§ States

Since data flow is normally one-way, and since the scope of the protocol is a single message delivery, a simplistic way to understand it might be as two instances of the stateless notification pattern, unfolding in sequence.

However, this doesn’t quite work on close inspection, because the mediator is at least potentially stateful with respect to any particular message; it needs to be if it wants to implement delayed delivery or retry logic. (Or, as noted earlier, the possibility of sending to multiple physical receivers. Mediators are not required to implement any of these features, but the state machine needs to account for their possibility.) Plus, the notification terminology obscures the sender and receiver roles. So we use the following formalization:

] Src: state machine diagram on gdocs

§ Messages

The only message in this protocol is the forward message. A simple and common version of a forward message might look like this:

{
    "type": "https://didcomm.org/routing/2.0/forward",
    "to": ["did:example:mediator"],
    "expires_time": 1516385931,
    "body":{
        "next": "did:foo:1234abcd",
    },
    "attachments": [
        // One payload?
    ]
}

When the internal message expires, it’s a good idea to also include an expiration for forward message requests. Include the expires_time header with the appropriate value.

[TODO: describe use of the attn field, and explain why it’s an important construct that allows us to encrypt to all (cryptographic route) but deliver just to the agent most likely to be interested (network route).

[TODO: further revise the following paragraph to clarify that either a key or a DID might be used. Each possibility makes certain tradeoffs, and may be appropriate in certain cases. Keys may be fragile in the face of rotation, and they require a lot of knowledge/maintenance cost for the external mediator. However, DID key references and DIDs may introduce some complications in how the recipient proves control of a DID (a requirement for security, but also a privacy eroder).]

For most external mediators, the value of the next field is likely to be a DID, not a key. However… (see previous TODO note). This hides details about the internals of a sovereign domain from external parties. The sender will have had to multiplex encrypt for all relevant recipient keys, but doesn’t need to know how routing happens to those keys. The mediator and the receiver may have coordinated about how distribution to individual keys takes place (see RFC 0211: Route Coordination), but that is outside the scope of concerns of this protocol.

The attachment(s) in the attachments field are able to use the full power of DIDComm attachments, including features like instructing the receiver to download the payload content from a CDN.

§ Rewrapping

Normally, the payload attached to the forward message received by the mediator is transmitted directly to the receiver with no further packaging. However, optionally, the mediator can attach the opaque payload to a new forward message (appropriately anoncrypted), which then acts as a fresh outer envelope for the second half of the delivery. This rewrapping means that the “onion” of packed messages stays the same size rather than getting smaller as a result of the forward operation:

re-wrapped sequence

Rewrapping mode is invisible to senders, but mediators need to know about it, since they change their behavior as a result. Receivers also need to know about it, because it causes them to receive a double-packaged message instead of a singly-packaged one. The outer envelope is a forward message where to is the receiver itself.

Why is such indirection useful?

These last two characteristics are the foundation of mix networking feature for DIDComm. That feature is the subject of a different RFC; here we only note the existence of the optional feature.

§ Sender Forward Process

  1. Sender Constructs Message.
  2. Sender Encrypts Message to recipient(s).
  3. Wrap Encrypted Message in Forward Message for each Routing Key.
  4. Transmit to serviceEndpoint in the manner specified in the [transports] section.

§ Mediator Process

Prior to using a Mediator, it is the recipient’s responsibility to coordinate with the mediator. Part of this coordination informs them of the next address(es) expected, the endpoint, and any Routing Keys to be used when forwarding messages. That coordination is out of the scope of this spec.

  1. Receives Forward Message.
  2. Retrieves Service Endpoint pre-configured by recipient (next attribute).
  3. Transmit payload message to Service Endpoint in the manner specified in the [transports] section.

The recipient (next attribute of Forward Message) may have pre-configured additional routing keys with the mediator that were not present in the DID Document and therefore unknown to the original sender. If this is the case, the mediator should wrap the attached payload message into an additional Forward message once per routing key. This step is performed between (2) and (3).

§ DID Document Keys

All keys declared in the DID Document’s keyAgreement section should be used as recipients when encrypting a message. The details of key representation are described in the Public Keys section of the DID Core Spec.

Keys used in a signed JWM are declared in the DID Document’s authentication section.

TODO: include details about how DIDComm keys are represented/identified in the DID Document. The DID Core Spec appears light on details and examples of keyAgreement keys. Clarifying language should be included here or there.

§ DID Document Service Endpoint

DIDComm DID Document endpoints have the following format:

{
    "id": "did:example:123456789abcdefghi#didcomm-1",
    "type": "DIDCommMessaging",
    "serviceEndpoint": "http://example.com/path",
    "accept": [
       "didcomm/v2",
       "didcomm/aip2;env=rfc587"
     ],
     "routingKeys": ["did:example:somemediator#somekey"]
}

id: must be unique, as required in DID Core. No special meaning should be inferred from the id chosen.

type: MUST be DIDCommMessaging.

serviceEndpoint: MUST contain a URI for a transport specified in the [transports] section of this spec, or a URI from Alternative Endpoints. It MAY be desirable to constraint endpoints from the [transports] section so that they are used only for the reception of DIDComm messages. This can be particularly helpful in cases where auto-detecting message types is inefficient or undesirable.

accept*: An optional array of media types in the order of preference for sending a message to the endpoint. If accept is not specified, the sender uses its preferred choice for sending a message to the endpoint. Please see Message Types for details about media types.

routingKeys: An optional ordered array of strings referencing keys to be used when preparing the message for transmission as specified in the [Routing] section of this spec.

§ Multiple Endpoints

A DID Document may contain multiple service entries of type DIDCommMessaging. Entries are SHOULD be specified in order of receiver preference, but any endpoint MAY be selected by the sender, typically by protocol availability or preference.

§ Alternative Endpoints

In addition to the URIs for [transports], some alternative forms are available.

§ DID

Using a DID for the serviceEndpoint is useful when using a mediator. The DID should be resolved, and services with type of “DIDComm” will contain valid serviceEndpoints. The keyAgreement keys of that DID Document should be implicitly appended at the end of the routingKeys section from the message recipient’s DID Document as per the process in [Sender Forward Process]. The advantage with this approach is that a mediator can rotate keys and update serviceEndpoints without any updates needed to dependent recipients` DID Documents.

A DID representing a mediator SHOULD NOT use alternative endpoints in it’s own DID Document to avoid recursive endpoint resolution. Using only the URIs described in [transports] will prevent such recursion.

Example 1: Mediator

{
    "id": "did:example:123456789abcdefghi#didcomm-1",
    "type": "DIDCommMessaging",
    "serviceEndpoint": "did:example:somemediator"
}

The message is encrypted to the recipient, then wrapped in a forward message encrypted to the keyAgreement keys within the did:example:somemediator DID Document, and transmitted to the URIs present in the did:example:somemediator DID Document with type DIDCommMessaging.

Example 2: Mediator + Routing Keys

{
    "id": "did:example:123456789abcdefghi#didcomm-1",
    "type": "DIDCommMessaging",
    "serviceEndpoint": "did:example:somemediator",
    "routingKeys": ["did:example:anothermediator#somekey"]
}

The message is encrypted to the recipient, then wrapped in a forward message encrypted to did:example:anothermediator#somekey. That forward message is wrapped in a forward message encrypted to keyAgreement keys within the did:example:somemediator DID Document, and transmitted to the URIs present in the did:example:somemediator DID Document with type DIDComm.

§ Transports

§ Summary

DIDComm Messaging is designed to be transport independent, including message encryption and agent message format. The encryption envelope provides both encryption and authentication, providing trust as a feature of each message. Each transport does have unique features, and we need to standardize how the transport features are (or are not) applied.

§ Delivery

DIDComm Transports serve only as message delivery. No information about the effects or results from a message is transmitted over the same connection.

§ Reference

§ HTTP(S)

HTTP(S) transports are an effective way to send a message to another online agent.

§ WebSocket

Websockets are an efficient way to transmit multiple messages without the overhead of individual requests. This is useful in a high bandwidth situation

With STOMP over WebSocket, the content-type header is application/didcomm-enc-env as in the HTTP(S) message.

TODO:

§ Internationalization (i18n)

Because automation makes life easier for humans, the data in DIDComm messages is usually assumed to have software as its audience. However, sometimes humans should see part of the data in a DIDComm message. For example, if the high-level application protocol running atop DIDComm is a kind of rich chat, humans may not see message headers and the details of threads – but they will want to read the text sent to them by a friend. Similarly, humans may need to read error messages or terms and conditions in their natural language.

DIDComm offers simple i18n features to address this need. They are intended to impose no up-front design burden on protocol implementers; multi-language support can be added once a protocol has adoption, with very little effort. These features also degrade gracefully and without coordination. Any party can introduce them to an interaction, but if others do not understand or support them, or if parties to the protocol have no human language in common, the interaction is typically still viable. (A protocol that inherently requires multilanguage support — e.g., to provides close captioning in second language — is the only exception.)

§ Internationalized by default

The default assumption about every field in a DIDComm message is that it is locale-independent (internationalized) already. Since number representation is governed by JSON syntax, and dates are represented as seconds-since-epoch or as ISO/IETF 3339 strings, this assumption is automatically true for data types that are not strings.

All string values in DIDComm messages are encoded as UTF-8, which is capable of representing the full Unicode character inventory. However, the default assumption for every string field in DIDComm also MUST be that it is locale-independent. This is appropriate for headers like id and type, for fields that contain URIs, and so forth.

§ accept-lang header

For string values that are language-specific, any party in a DIDComm interaction MAY declare the human languages that they prefer by using the accept-lang header. This allows those who send them messages to localize the content appropriately.

The value of this header is an array of IANA’s language codes, ranked from most to least preferred. Once a language preference has been set, it MUST be assumed to apply until it is changed, or for the duration of an application-level protocol instance (a DIDComm thread) — whichever comes first. Parties who see this header MAY assume it is an appropriate default for future interactions as well. However, they MUST NOT apply the assumption to any other interactions that are already underway, as this would allow one protocol to trigger unpredictable side effects in another.

§ lang header

When a sender is preparing a message that contains language-specific fields, they SHOULD clarify how to interpret those fields by using the lang header. This is a general best practices. Individual protocols that have strong dependencies on human language MAY require this header in contexts they govern.

Ideally, the value of lang will derive from a previously-seen accept-lang header, reflecting the fact that the sender is communicating in a language that the recipient prefers. (The sender could get matching language content by looking it up in message tables, calling a machine translation service, or — if the content is generated dynamically by a human — simply asking the human sender to speak or write in the target language.) However, even when no match is achieved, declaring lang lets the recipient call a machine translation service or take other intelligent action.

This header works much like lang in HTML, and its value comes from IANA’s language subtag registry. If this header is present, then any string field inside body that contains human-readable text (according to the active protocol’s definition of the message type) MUST hold text in the identified language.

§ i18n example

Suppose a chess protocol allows players to include human-friendly comments with their moves. At the beginning of the chess game, Bob includes a message that contains this header:

"accept-lang": ["fr", "en"]

This tells Alice that Bob prefers to interact in French, with English as a backup preference.

When Alice puts Bob in checkmate, assuming she has the desire and ability to honor Bob’s preference, her message might look like this:

{
  "id": "388d599a-fdc1-4890-b32a-be6cd3893564",
  "type": "https://didcomm.org/chess/1.0/move",
  "lang": "fr",
  "body": {
    "move": "BC4+",
    "comment": "C'est échec et mat, mon pote."
  }
}

On the other hand, if Alice is unable to send French text, her message might contain "lang": "en" and "comment": "That's checkmate, buddy." Even though this is not the language content Bob requested, at least Bob knows what language it is.

§ Asking for a different lang

What if Alice doesn’t support any of the languages in Bob’s accept-lang header – or if Bob never used such a header in the first place?

Bob MAY tell Alice that the language she used is problematic by sending her a problem-report message where the code field is w.msg.bad-lang. (In some protocols where language-specific fields may be vital rather than incidental, a problem like this might be an error instead of a warning; in such cases, the code MUST be e.msg.bad-lang instead.) Bob may include an accept-lang header on this problem-report message, teaching Alice what it will take to fix the problem.

§ Advanced i18n patterns

When protocols have i18n needs that are more advanced than this, a DIDComm extension such as the l10n extension is recommended.

§ Advanced Message Passing

TODO:

§ Embedded Messages

DIDComm messages may be passed within other messages are protocols when the outer message is passed in a secure way. When messages are passed in this way, they may be passed either as an encrypted message or in plain text. When in plain text format, messages should be represented in json format.

§ Privacy Considerations

When messages are passed in plain text, the privacy and security of the message is subject to the properties of the protocol and transport moving the messages. Extreme care must be taken to protect the message.

§ Connections

A Connection is the practical application of a relationship in DID Communication. 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.

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. Using the connection to establish a foundation of trust is the next step.

§ General Messaging Constructs

§ Attachments

§ Summary

DIDComm messages use a structured format with a defined schema and a small inventory of scalar data types (string, number, date, etc). However, it will be quite common for messages to supplement formalized exchange with arbitrary data–images, documents, or types of media not yet invented.

We need a way to “attach” such content to DIDComm messages. This method must be flexible, powerful, and usable without requiring new schema updates for every dynamic variation.

§ Reference

Attachments are contained within a list in the attachments header.

Each attachment is contained within the following structure.

§ Example

{
    "type": "<sometype>",
    "to": ["did:example:mediator"],
    "body":{
        "attachment_id": "1",
        "encrypted_details": {
            "id": "x",
            "encrypted_to": "",
            "other_details": "about attachment"
        }
    },
    "attachments": [
        {
			"id": "1",
            "description": "example b64 encoded attachment",
            "data": {
            	"base64": "WW91ciBob3ZlcmNyYWZ0IGlzIGZ1bGwgb2YgZWVscw=="
        	}
        },{
			"id": "2",
            "description": "example linked attachment",
            "data": {
            	"hash": "<multi-hash>",
                "links": ["http://path/to/resource"]
        	}
        },{
			"id": "x",
            "description": "example encrypted DIDComm message as attachment",
            "media_type": "application/didcomm-encrypted+json",
            "data": {
            	"json": {
                    //jwe json structure
                }
        	}
        }
    ]
}

§ Protocols

DIDComm serves as a foundational layer for the development of protocols. This spec does not include protocols themselves, but describes the basic requirements and foundational elements.

Each Protocol is uniquely identified by a Protocol Identifier URI, and contains one or more messages identified by a Message Type URI. In addition to serving as a unique identifier, the URIs may be used by a developer to locate documentation.

§ Protocol Identifier URI

A Protocol Identifier URI identifies protocol versions unambiguously. Additionally, Protocol Identifier URIs may be used by a developer to locate documentation about a protocol.

The URI must be composed as follows:

[doc-uri][delim][protocol-name]/[semver]

With ABNF:

protocol-identifier-uri = doc-uri delim protocol-name "/" semver
delim                   = "?" / "/" / "&" / ":" / ";" / "="

Its loose matcher regex is:

(.*?)([a-z0-9._-]+)/(\d[^/]*)/?$

Example Protocol Type URIs:

http://example.com/protocols?which=lets_do_lunch/1.0
http://example.com/protocols/lets_do_lunch/1.0
https://github.com/hyperledger/aries-toolbox/tree/master/docs/admin-invitations/0.1

The goals of this URI are, in descending priority:

The doc-uri portion is any URI that exposes documentation about protocols. A developer should be able to browse to that URI and use human intelligence to look up the named and versioned protocol.

§ Message Type URI

A Message Type URI identifies message types unambiguously. Standardizing its format is important because it is parsed by agents that will map messages to handlers–basically, code will look at this string and say, “Do I have something that can handle this message type inside protocol X version Y?” When that analysis happens, it must do more than compare the string for exact equality; it may need to check for semver compatibility, and it has to compare the protocol name and message type name ignoring case and punctuation.

The URI MUST be composed as follows:

[protocol-identifier-uri] / [message-type-name]

With ABNF:

message-type-uri  = protocol-identifier-uri "/" message-type-name
protocol-identifier-uri = doc-uri delim protocol-name "/" semver
delim                   = "?" / "/" / "&" / ":" / ";" / "="
protocol-name     = identifier
protocol-version  = semver
message-type-name = identifier
identifier        = alpha *(*(alphanum / "_" / "-" / ".") alphanum)

It can be loosely matched and parsed with the following regex:

    (.*?)([a-z0-9._-]+)/(\d[^/]*)/([a-z0-9._-]+)$

A match will have captures groups of (1) = doc-uri, (2) = protocol-name, (3) = protocol-version, and (4) = message-type-name.

The goals of this URI are, in descending priority:

Example Message Type URIs:

http://example.com/protocols?which=lets_do_lunch/1.0/proposal
http://example.com/protocols/lets_do_lunch/1.0/proposal
did:example:1234567890;spec/trust_ping/1.0/ping
https://github.com/hyperledger/aries-toolbox/tree/master/docs/admin-invitations/0.1/create-invitation

§ Out Of Band Messages

§ URL & QR Codes

When passing a DIDComm Message between two parties, it is often useful to present a message in the form of a URL or encoded into the form of a QR code for scanning with a smartphone or other camera. The format for a QR code is simply the encoded URL form of a message.

§ Privacy Considerations

Any information passed via a URL or QR code is unencrypted, and may be observed by another party. This lack of privacy must be minded in two different ways.

First, no private information may be passed in the message. Private information should be passed between parties in encrypted messages only. Any protocol message that contains private information should not be passed via URL or QR code.

Second, any identifiers passed in a message sent via URL or QR code must no longer be considered private. Any DID used or other identifier no longer considered private MUST be rotated over a secure connection if privacy is required.

§ Message Correlation

The id of the message passed in a URL or a QR code is used to as the thid on a response sent by the recipient of this message. The response recipient can use the thid to correlate it with the original message.

§ Messages

Each message passed this way must be contained within an out-of-band message, as described below.

The out-of-band protocol a single message that is sent by the sender.

§ Invitation: https://didcomm.org/out-of-band/2.0/invitation

{
  "typ": "application/didcomm-plain+json",
  "type": "https://didcomm.org/out-of-band/2.0/invitation",
  "id": "<id used for context as pthid>",
  "body": {
    "goal_code": "issue-vc",
    "goal": "To issue a Faber College Graduate credential",
    "accept": [
      "didcomm/v2",
      "didcomm/aip2;env=rfc587"
    ],
  },
  "attachments": [
    {
        "@id": "request-0",
        "mime-type": "application/json",
        "data": {
            "json": "<json of protocol message>"
        }
    }
  ]
}

The items in the message are:

When encoding a message in a URL or QR code, the sender does not know which protocols are supported by the recipient of the message. Encoding multiple alternative messages is a form of optimistic protocol negotiation that allows multiple supported protocols without coordination

§ Standard Message Encoding

Using a standard message encoding allows for easier interoperability between multiple projects and software platforms. Using a URL for that standard encoding provides a built in fallback flow for users who are unable to automatically process the message. Those new users will load the URL in a browser as a default behavior, and may be presented with instructions on how to install software capable of processing the message. Already onboarded users will be able to process the message without loading in a browser via mobile app URL capture, or via capability detection after being loaded in a browser.

The standard message format is a URL with a Base64URLEncoded plaintext JWM json object as a query parameter.

The URL format is as follows, with some elements described below:

https://<domain>/<path>?_oob=<encodedplaintextjwm>

<domain> and <path> should be kept as short as possible, and the full URL should return human readable instructions when loaded in a browser. This is intended to aid new users. The _oob query parameter is required and is reserved to contain the DIDComm message string. Additional path elements or query parameters are allowed, and can be leveraged to provide coupons or other promise of payment for new users.

_oob is a shortened form of Out of Band, and was chosen to not conflict with query parameter names in use at a particular domain. When the query parameter is detected, it may be assumed to be an Out Of Band message with a reasonably high confidence.

To do: We need to rationalize this approach https:// approach with the use of a special protocol (e.g. didcomm://) that will enable handling of the URL on mobile devices to automatically invoke an installed app on both Android and iOS. A user must be able to process the out-of-band message on the device of the agent (e.g. when the mobile device can’t scan the QR code because it is on a web page on device).

The <encodedplaintextjwm> is a JWM plaintext message that has been base64-url encoded.

encodedplaintextjwm = b64urlencode(<plaintextjwm>)

During encoding, whitespace from the json string should be eliminated to keep the resulting out-of-band message string as short as possible.

§ Example Out-of-Band Message Encoding

Invitation:

{
  "typ": "application/didcomm-plain+json",
  "type": "https://didcomm.org/out-of-band/2.0/invitation",
  "id": "69212a3a-d068-4f9d-a2dd-4741bca89af3",
  "from": "did:example:alice",
  "body": {
      "goal_code": "",
      "goal": ""
  },
  "attachments": [
      {
          "@id": "request-0",
          "mime-type": "application/json",
          "data": {
              "json": "<json of protocol message>"
          }
      }
  ]
}

Whitespace removed:

{"typ":"application/didcomm-plain+json","type":"https://didcomm.org/out-of-band/2.0/invitation","id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","from":"did:example:alice","body":{"goal_code":"","goal":""},"attachments":[{"@id":"request-0","mime-type":"application/json","data":{"json":"<json of protocol message>"}}]}

Base 64 URL Encoded:

eyJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXBsYWluK2pzb24iLCJ0eXBlIjoiaHR0cHM6Ly9kaWRjb21tLm9yZy9vdXQtb2YtYmFuZC8yLjAvaW52aXRhdGlvbiIsImlkIjoiNjkyMTJhM2EtZDA2OC00ZjlkLWEyZGQtNDc0MWJjYTg5YWYzIiwiZnJvbSI6ImRpZDpleGFtcGxlOmFsaWNlIiwiYm9keSI6eyJnb2FsX2NvZGUiOiIiLCJnb2FsIjoiIn0sImF0dGFjaG1lbnRzIjpbeyJAaWQiOiJyZXF1ZXN0LTAiLCJtaW1lLXR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwiZGF0YSI6eyJqc29uIjoiPGpzb24gb2YgcHJvdG9jb2wgbWVzc2FnZT4ifX1dfQ==

Example URL:

http://example.com/path?_oob=eyJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXBsYWluK2pzb24iLCJ0eXBlIjoiaHR0cHM6Ly9kaWRjb21tLm9yZy9vdXQtb2YtYmFuZC8yLjAvaW52aXRhdGlvbiIsImlkIjoiNjkyMTJhM2EtZDA2OC00ZjlkLWEyZGQtNDc0MWJjYTg5YWYzIiwiZnJvbSI6ImRpZDpleGFtcGxlOmFsaWNlIiwiYm9keSI6eyJnb2FsX2NvZGUiOiIiLCJnb2FsIjoiIn0sImF0dGFjaG1lbnRzIjpbeyJAaWQiOiJyZXF1ZXN0LTAiLCJtaW1lLXR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwiZGF0YSI6eyJqc29uIjoiPGpzb24gb2YgcHJvdG9jb2wgbWVzc2FnZT4ifX1dfQ==

DIDComm message URLs can be transferred via any method that can send text, including an email, SMS, posting on a website, or QR Code.

Example Email Message:

To: [email protected]
From: [email protected]
Subject: Your request to connect and receive your graduate verifiable credential

Dear Alice,

To receive your Faber College graduation certificate, click here to [connect](http://example.com/path?_oob=eyJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXBsYWluK2pzb24iLCJ0eXBlIjoiaHR0cHM6Ly9kaWRjb21tLm9yZy9vdXQtb2YtYmFuZC8yLjAvaW52aXRhdGlvbiIsImlkIjoiNjkyMTJhM2EtZDA2OC00ZjlkLWEyZGQtNDc0MWJjYTg5YWYzIiwiZnJvbSI6ImRpZDpleGFtcGxlOmFsaWNlIiwiYm9keSI6eyJnb2FsX2NvZGUiOiIiLCJnb2FsIjoiIn0sImF0dGFjaG1lbnRzIjpbeyJAaWQiOiJyZXF1ZXN0LTAiLCJtaW1lLXR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwiZGF0YSI6eyJqc29uIjoiPGpzb24gb2YgcHJvdG9jb2wgbWVzc2FnZT4ifX1dfQ== with us, or paste the following into your browser:

http://example.com/path?_oob=eyJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXBsYWluK2pzb24iLCJ0eXBlIjoiaHR0cHM6Ly9kaWRjb21tLm9yZy9vdXQtb2YtYmFuZC8yLjAvaW52aXRhdGlvbiIsImlkIjoiNjkyMTJhM2EtZDA2OC00ZjlkLWEyZGQtNDc0MWJjYTg5YWYzIiwiZnJvbSI6ImRpZDpleGFtcGxlOmFsaWNlIiwiYm9keSI6eyJnb2FsX2NvZGUiOiIiLCJnb2FsIjoiIn0sImF0dGFjaG1lbnRzIjpbeyJAaWQiOiJyZXF1ZXN0LTAiLCJtaW1lLXR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIiwiZGF0YSI6eyJqc29uIjoiPGpzb24gb2YgcHJvdG9jb2wgbWVzc2FnZT4ifX1dfQ==

If you don't have an identity agent for holding credentials, you will be given instructions on how you can get one.

Thanks,

Faber College
Knowledge is Good

Example URL encoded as a QR Code:

Example QR Code

§ Short URL Message Retrieval

It seems inevitable that the length of some DIDComm messages will be too long to produce a useable QR code. Techniques to avoid unusable QR codes have been presented above, including using attachment links for requests, minimizing the routing of the response and eliminating unnecessary whitespace in the JSON. However, at some point a sender may need generate a very long URL. In that case, a short URL message retrieval redirection should be implemented by the sender as follows:

A usable QR code will always be able to be generated from the shortened form of the URL.

Note: Due to the privacy implications, a standard URL shortening service SHOULD NOT be used.

§ Discover Features Protocol 1.0

§ Summary

Describes how agents can query one another to discover which features it supports, and to what extent.

§ Motivation

Though some agents will support just one protocol and will be statically configured to interact with just one other party, many exciting uses of agents are more dynamic and unpredictable. When Alice and Bob meet, they won’t know in advance which features are supported by one another’s agents. They need a way to find out.

Disclosing features in this manner has a significant privacy benefit over endpoint disclosures contained in a DID Document published to a Verifiable Data Registry (VDR). Using the single DIDComm endpoint published in the document and this protocol, features can be selectively disclosed to other parties at the owner’s discretion. The problem of anonymous scanning and fingerprinting enabled with VDR disclosures is solved in a privacy preserving way.

§ Reference

This RFC introduces a protocol for discussing the protocols an agent can handle. The identifier for the message family used by this protocol is discover-features, and the fully qualified URI for its definition is:

https://didcomm.org/discover-features/1.0

§ Roles

There are two roles in the discover-features protocol: requester and responder. The requester asks the responder about the protocols it supports, and the responder answers. Each role uses a single message type.

§ States

This is a classic two-step request~response interaction, so it uses the predefined state machines for any requester and responder:

state machines

§ Messages

§ query Message Type

A discover-features/query message looks like this:

{
    "type": "https://didcomm.org/discover-features/1.0/query",
    "id": "yWd8wfYzhmuXX3hmLNaV5bVbAjbWaU",
    "body": {
        "query": "https://didcomm.org/tictactoe/1.*"
    }
}

Query messages say, “Please tell me what your capabilities are with respect to the protocols that match this string.” This particular example asks if another agent knows any 1.x versions of the tictactoe protocol.

The query field may use the * wildcard. By itself, a query with just the wildcard says, “I’m interested in anything you want to share with me.” But usually, this wildcard will be to match a prefix that’s a little more specific, as in the example that matches any 1.x version.

Any agent may send another agent this message type at any time. Implementers of agents that intend to support dynamic relationships and rich features are strongly encouraged to implement support for this message, as it is likely to be among the first messages exchanged with a stranger.

§ disclose Message Type

A discover-features/disclose message looks like this:

{
    "type": "https://didcomm.org/discover-features/1.0/disclose",
    "thid": "yWd8wfYzhmuXX3hmLNaV5bVbAjbWaU",
    "body":{
        "protocols": [
            {
                "ptid": "https://didcomm.org/tictactoe/1.0",
                "roles": ["player"]
            }
        ]
    }
}

The protocols field is a JSON array of protocol support descriptor objects that match the query. Each descriptor has a pid that contains a protocol version (fully qualified message family identifier such as https://didcomm.org/tictactoe/1.0), plus a roles array that enumerates the roles the responding agent can play in the associated protocol.

Response messages say, “Here are some protocols I support that matched your query, and some things I can do with each one.”

§ Sparse Responses

Responses do not have to contain exhaustive detail. For example, the following response is probably just as good:

{
  "type": "https://didcomm.org/discover-features/1.0/disclose",
  "thid": "yWd8wfYzhmuXX3hmLNaV5bVbAjbWaU",
  "protocols": [
    {"ptid": "https://didcomm.org/tictactoe/1.0"}
  ]
}

The reason why less detail probably suffices is that agents do not need to know everything about one another’s implementations in order to start an interaction–usually the flow will organically reveal what’s needed. For example, the outcome message in the tictactoe protocol isn’t needed until the end, and is optional anyway. Alice can start a tictactoe game with Bob and will eventually see whether he has the right idea about outcome messages.

The missing roles in this response does not say, “I support no roles in this protocol.” It says, “I support the protocol but I’m providing no detail about specific roles.”

Even an empty protocols map does not say, “I support no protocols that match your query.” It says, “I’m not telling you that I support any protocols that match your query.” An agent might not tell another that it supports a protocol for various reasons, including: the trust that it imputes to the other party based on cumulative interactions so far, whether it’s in the middle of upgrading a plugin, whether it’s currently under high load, and so forth. And responses to a discover-features request are not guaranteed to be true forever; agents can be upgraded or downgraded, although they probably won’t churn in their protocol support from moment to moment.

§ Privacy Considerations

Because the regex in a request message can be very inclusive, the discover-features protocol could be used to mine information suitable for agent fingerprinting, in much the same way that browser fingerprinting works. This is antithetical to the ethos of our ecosystem, and represents bad behavior. Agents should use discover-features to answer legitimate questions, and not to build detailed profiles of one another. However, fingerprinting may be attempted anyway.

For agents that want to maintain privacy, several best practices are recommended:

§ Follow selective disclosure.

Only reveal supported features based on trust in the relationship. Even if you support a protocol, you may not wish to use it in every relationship. Don’t tell others about protocols you do not plan to use with them.

Patterns are easier to see in larger data samples. However, a pattern of ultra-minimal data is also a problem, so use good judgment about how forthcoming to be.

§ Trust Ping Protocol 2.0

A standard way for agents to test connectivity, responsiveness, and security of a DIDComm channel.

§ Motivation

Agents are distributed. They are not guaranteed to be connected or running all the time. They support a variety of transports, speak a variety of protocols, and run software from many different vendors.

This can make it very difficult to prove that two agents have a functional pairwise channel. Troubleshooting connectivity, responsiveness, and security is vital.

§ Reference

This protocol is analogous to the familiar ping command in networking–but because it operates over DIDComm, it is transport agnostic and asynchronous, and it can produce insights into privacy and security that a regular ping cannot.

§ Roles

There are two parties in a trust ping: the sender and the receiver. The sender initiates the trust ping. The receiver responds. If the receiver wants to do a ping of their own, they can, but this is a new interaction in which they become the sender.

§ Protocol Type URI

https://didcomm.org/trust-ping/2.0

§ Messages

§ ping

The trust ping interaction begins when sender creates a ping message like this:

{
  "type": "https://didcomm.org/trust-ping/2.0/ping",
  "id": "518be002-de8e-456e-b3d5-8fe472477a86",
  "from": "did:example:123456",
  "body": {
      "response_requested": true
  }
}

response_requested: default value is true. If false, the sender is not requesting a ping_response from the receiver. If true, the sender is requesting a response.

§ ping_response

When the message arrives at the receiver, assuming that response_requested is not false, the receiver should reply as quickly as possible with a ping_response message that looks like this:

{
  "type": "https://didcomm.org/trust-ping/2.0/ping-response",
  "id": "e002518b-456e-b3d5-de8e-7a86fe472847",
  "thid": "518be002-de8e-456e-b3d5-8fe472477a86"
}

§ Trust

This is the “trust ping protocol”, not just the “ping protocol.” The “trust” in its name comes from several features that the interaction gains by virtue of the properties of the DIDComm messages. A ping and response verify to both parties that the necessary encryption is in place and working properly for the messages to be understood.

§ Reference Implementation

§ Future-Proofing

§ Versioning

This version of the standard is known as “DIDComm v2” — acknowledging the fact that a v1 generation of DIDComm specs was incubated under the Hyperledger Aries project umbrella. The v1 specs are close conceptual cousins, but use a slightly different encryption envelope, and base their plaintext format on arbitrary JSON instead of JWMs.

Future evolutions of the spec will follow semver conventions. Minor updates that add features without breaking compatibility will carry a minor version number update: 2.1, 2.2, and so forth. Breaking changes will prompt a major version change.

§ Extensions

The general mechanism for DIDComm extensibility is the development of DIDComm protocols. In the case where extensibility requires a modification to the base DIDComm spec itself, a DIDComm extension is to be used. An extension adds a self-contained set of conventions or features. Support for DIDComm extensions is optional.

Each DIDComm extension is described in a specification of its own. Software that implements a DIDComm Extension in addition to the DIDComm spec will indicate so via link to the extension spec.

§ Future Work

§ Additional Encodings

DIDComm Messages are JSON encoded (based on the JOSE family of specs) at the encryption, signature, and content level. Future encodings might introduce binary serializations. Each innovation like this MUST specify a deterministic and reliable method for indicating the alternative encoding used.

At multiple points in the creation of this spec the community discussed switching to CBOR as a primary encoding format to replace JSON. Two reasons prevented that switch: The maturity of the JSON related standards as compared to CBOR related standards, and the cost of switching so late in spec development.

§ Beyond Messaging

This is a DIDComm messaging spec. Security, privacy, routing, and metadata concepts from this spec could be adapted to other communication styles, including multicast/broadcast and streaming. This will create sister specs to DIDComm Messaging, rather than evolving DIDComm Messaging itself.

§ Post-Quantum Crypto

The designers of DIDComm are aware that DIDComm’s cryptographic methods will need to be upgraded when quantum computing matures. This is because DIDComm makes heavy use of asymmetric elliptic curve mechanisms that depend on the discrete logarithm problem; this computational hardness is likely to be vulnerable to quantum cracking. Similar risks will drive upgrades to TLS, Ethereum, Bitcoin, and many other systems that are considered highly secure today.

Some modest preparations for quantum-resistant DIDComm have already begun. DIDComm is able to use arbitrary DID methods, which should allow approaches that are quantum-secure without changing the general pattern of DIDComm’s interaction with key management technology.

Libraries that provide quantum-resistant algorithms for signing and encryption are now available, but research is needed to determine which approaches are worthy of broad adoption. This is the subject of an ongoing project sponsored by NIST, and of a similar project in the EU.

We expect to update the DIDComm Messaging spec as these projects release mature recommendations and the cryptographic libraries they vet achieve adoption. It is not yet clear whether this will require a breaking change to DIDComm’s encryption envelope or signing formats.

§ References

§ Appendix

This section provides test vectors of DIDComm Messages. The test vectors defined in the Appendix C might be used to validate implementations of DIDComm Messaging. The test vectors use the sender and recipient private keys defined in the Appendix A to decrypt and sign DIDComm Messages. The test vectors use the sender and recipient public keys defined in the Appendix B to encrypt DIDComm Encrypted Messages and verify signature of DIDComm Signed Messages.

§ Appendix A. Secrets for Test Vectors

This section provides the sender and recipient private keys. These keys might be used for decryption and signing DIDComm Messages.

§ A.1. Sender Secrets

This section defines the sender private keys in JWK format.

[
  {
    "kid":"did:example:alice#key-1",
    "kty":"OKP",
    "d":"pFRUKkyzx4kHdJtFSnlPA9WzqkDT1HWV0xZ5OYZd2SY",
    "crv":"Ed25519",
    "x":"G-boxFB6vOZBu-wXkm-9Lh79I8nf9Z50cILaOgKKGww"
  },
  {
    "kid":"did:example:alice#key-2",
    "kty":"EC",
    "d":"7TCIdt1rhThFtWcEiLnk_COEjh1ZfQhM4bW2wz-dp4A",
    "crv":"P-256",
    "x":"2syLh57B-dGpa0F8p1JrO6JU7UUSF6j7qL-vfk1eOoY",
    "y":"BgsGtI7UPsObMRjdElxLOrgAO9JggNMjOcfzEPox18w"
  },
  {
    "kid":"did:example:alice#key-3",
    "kty":"EC",
    "d":"N3Hm1LXA210YVGGsXw_GklMwcLu_bMgnzDese6YQIyA",
    "crv":"secp256k1",
    "x":"aToW5EaTq5mlAf8C5ECYDSkqsJycrW-e1SQ6_GJcAOk",
    "y":"JAGX94caA21WKreXwYUaOCYTBMrqaX4KWIlsQZTHWCk"
  },
  {
    "kid":"did:example:alice#key-x25519-1",
    "kty":"OKP",
    "d":"r-jK2cO3taR8LQnJB1_ikLBTAnOtShJOsHXRUWT-aZA",
    "crv":"X25519",
    "x":"avH0O2Y4tqLAq8y9zpianr8ajii5m4F_mICrzNlatXs"
  },
  {
    "kid":"did:example:alice#key-p256-1",
    "kty":"EC",
    "d":"sB0bYtpaXyp-h17dDpMx91N3Du1AdN4z1FUq02GbmLw",
    "crv":"P-256",
    "x":"L0crjMN1g0Ih4sYAJ_nGoHUck2cloltUpUVQDhF2nHE",
    "y":"SxYgE7CmEJYi7IDhgK5jI4ZiajO8jPRZDldVhqFpYoo"
  },
  {
    "kid":"did:example:alice#key-p521-1",
    "kty":"EC",
    "d":"AQCQKE7rZpxPnX9RgjXxeywrAMp1fJsyFe4cir1gWj-8t8xWaM_E2qBkTTzyjbRBu-JPXHe_auT850iYmE34SkWi",
    "crv":"P-521",
    "x":"AHBEVPRhAv-WHDEvxVM9S0px9WxxwHL641Pemgk9sDdxvli9VpKCBdra5gg_4kupBDhz__AlaBgKOC_15J2Byptz",
    "y":"AciGcHJCD_yMikQvlmqpkBbVqqbg93mMVcgvXBYAQPP-u9AF7adybwZrNfHWCKAQwGF9ugd0Zhg7mLMEszIONFRk"
  }
]

§ A.2. Recipient Secrets

This section defines the recipient private keys in JWK format.

[
  {
    "kid ":"did:example:bob#key-x25519-1",
    "kty":"OKP",
    "d":"b9NnuOCB0hm7YGNvaE9DMhwH_wjZA1-gWD6dA0JWdL0",
    "crv":"X25519",
    "x":"GDTrI66K0pFfO54tlCSvfjjNapIs44dzpneBgyx0S3E"
  },
  {
    "kid ":"did:example:bob#key-x25519-2",
    "kty":"OKP",
    "d":"p-vteoF1gopny1HXywt76xz_uC83UUmrgszsI-ThBKk",
    "crv":"X25519",
    "x":"UT9S3F5ep16KSNBBShU2wh3qSfqYjlasZimn0mB8_VM"
  },
  {
    "kid ":"did:example:bob#key-x25519-3",
    "kty":"OKP",
    "d":"f9WJeuQXEItkGM8shN4dqFr5fLQLBasHnWZ-8dPaSo0",
    "crv":"X25519",
    "x":"82k2BTUiywKv49fKLZa-WwDi8RBf0tB0M8bvSAUQ3yY"
  },
  {
    "kid ":"did:example:bob#key-p256-1",
    "kty":"EC",
    "d":"PgwHnlXxt8pwR6OCTUwwWx-P51BiLkFZyqHzquKddXQ",
    "crv":"P-256",
    "x":"FQVaTOksf-XsCUrt4J1L2UGvtWaDwpboVlqbKBY2AIo",
    "y":"6XFB9PYo7dyC5ViJSO9uXNYkxTJWn0d_mqJ__ZYhcNY"
  },
  {
    "kid ":"did:example:bob#key-p256-2",
    "kty":"EC",
    "d":"agKz7HS8mIwqO40Q2dwm_Zi70IdYFtonN5sZecQoxYU",
    "crv":"P-256",
    "x":"n0yBsGrwGZup9ywKhzD4KoORGicilzIUyfcXb1CSwe0",
    "y":"ov0buZJ8GHzV128jmCw1CaFbajZoFFmiJDbMrceCXIw"
  },
  {
    "kid ":"did:example:bob#key-p384-1",
    "kty":"EC",
    "d":"ajqcWbYA0UDBKfAhkSkeiVjMMt8l-5rcknvEv9t_Os6M8s-HisdywvNCX4CGd_xY",
    "crv":"P-384",
    "x":"MvnE_OwKoTcJVfHyTX-DLSRhhNwlu5LNoQ5UWD9Jmgtdxp_kpjsMuTTBnxg5RF_Y",
    "y":"X_3HJBcKFQEG35PZbEOBn8u9_z8V1F9V1Kv-Vh0aSzmH-y9aOuDJUE3D4Hvmi5l7"
  },
  {
    "kid ":"did:example:bob#key-p384-2",
    "kty":"EC",
    "d":"OiwhRotK188BtbQy0XBO8PljSKYI6CCD-nE_ZUzK7o81tk3imDOuQ-jrSWaIkI-T",
    "crv":"P-384",
    "x":"2x3HOTvR8e-Tu6U4UqMd1wUWsNXMD0RgIunZTMcZsS-zWOwDgsrhYVHmv3k_DjV3",
    "y":"W9LLaBjlWYcXUxOf6ECSfcXKaC3-K9z4hCoP0PS87Q_4ExMgIwxVCXUEB6nf0GDd"
  },
  {
    "kid ":"did:example:bob#key-p521-1",
    "kty":"EC",
    "d":"AV5ocjvy7PkPgNrSuvCxtG70NMj6iTabvvjSLbsdd8OdI9HlXYlFR7RdBbgLUTruvaIRhjEAE9gNTH6rWUIdfuj6",
    "crv":"P-521",
    "x":"Af9O5THFENlqQbh2Ehipt1Yf4gAd9RCa3QzPktfcgUIFADMc4kAaYVViTaDOuvVS2vMS1KZe0D5kXedSXPQ3QbHi",
    "y":"ATZVigRQ7UdGsQ9j-omyff6JIeeUv3CBWYsZ0l6x3C_SYqhqVV7dEG-TafCCNiIxs8qeUiXQ8cHWVclqkH4Lo1qH"
  },
  {
    "kid ":"did:example:bob#key-p521-2",
    "kty":"EC",
    "d":"ABixMEZHsyT7SRw-lY5HxdNOofTZLlwBHwPEJ3spEMC2sWN1RZQylZuvoyOBGJnPxg4-H_iVhNWf_OtgYODrYhCk",
    "crv":"P-521",
    "x":"ATp_WxCfIK_SriBoStmA0QrJc2pUR1djpen0VdpmogtnKxJbitiPq-HJXYXDKriXfVnkrl2i952MsIOMfD2j0Ots",
    "y":"AEJipR0Dc-aBZYDqN51SKHYSWs9hM58SmRY1MxgXANgZrPaq1EeGMGOjkbLMEJtBThdjXhkS5VlXMkF0cYhZELiH"
  }
]

§ Appendix B. DIDDocs for Test Vectors

This section provides DIDDocs for the sender and recipient. The following DIDDocs might be used to validate implementations of the DIDComm Messaging. They are also intended to test vectors defined in the Appendix C.

§ B.1. Sender DIDDocs

This section defines the sender DIDDoc.

{
   "@context":[
      "https://www.w3.org/ns/did/v1",
      "http://w3id.org/security/suites/jws-2020/v1"
   ],
   "id":"did:example:alice",
   "authentication":[
      {
         "id":"did:example:alice#key-1",
         "type":"JsonWebKey2020",
         "controller":"did:example:alice#key-1",
         "publicKeyJwk":{
            "kty":"OKP",
            "crv":"Ed25519",
            "x":"G-boxFB6vOZBu-wXkm-9Lh79I8nf9Z50cILaOgKKGww"
         }
      },
      {
         "id":"did:example:alice#key-2",
         "type":"JsonWebKey2020",
         "controller":"did:example:alice#key-2",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-256",
            "x":"2syLh57B-dGpa0F8p1JrO6JU7UUSF6j7qL-vfk1eOoY",
            "y":"BgsGtI7UPsObMRjdElxLOrgAO9JggNMjOcfzEPox18w"
         }
      },
      {
         "id":"did:example:alice#key-3",
         "type":"JsonWebKey2020",
         "controller":"did:example:alice#key-3",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"secp256k1",
            "x":"aToW5EaTq5mlAf8C5ECYDSkqsJycrW-e1SQ6_GJcAOk",
            "y":"JAGX94caA21WKreXwYUaOCYTBMrqaX4KWIlsQZTHWCk"
         }
      }
   ],
   "keyAgreement":[
      {
         "id":"did:example:alice#key-x25519-1",
         "type":"JsonWebKey2020",
         "controller":"did:example:alice#key-x25519-1",
         "publicKeyJwk":{
            "kty":"OKP",
            "crv":"X25519",
            "x":"avH0O2Y4tqLAq8y9zpianr8ajii5m4F_mICrzNlatXs"
         }
      },
      {
         "id":"did:example:alice#key-p256-1",
         "type":"JsonWebKey2020",
         "controller":"did:example:alice#key-p256-1",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-256",
            "x":"L0crjMN1g0Ih4sYAJ_nGoHUck2cloltUpUVQDhF2nHE",
            "y":"SxYgE7CmEJYi7IDhgK5jI4ZiajO8jPRZDldVhqFpYoo"
         }
      },
      {
         "id":"did:example:alice#key-p521-1",
         "type":"JsonWebKey2020",
         "controller":"did:example:alice#key-p521-1",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-521",
            "x":"AHBEVPRhAv-WHDEvxVM9S0px9WxxwHL641Pemgk9sDdxvli9VpKCBdra5gg_4kupBDhz__AlaBgKOC_15J2Byptz",
            "y":"AciGcHJCD_yMikQvlmqpkBbVqqbg93mMVcgvXBYAQPP-u9AF7adybwZrNfHWCKAQwGF9ugd0Zhg7mLMEszIONFRk"
         }
      }
   ]
}

§ B.2. Recipient DIDDocs

This section defines the recipient DIDDoc.

{
   "@context":[
      "https://www.w3.org/ns/did/v2"
   ],
   "id":"did:example:bob",
   "keyAgreement":[
      {
         "id":"did:example:bob#key-x25519-1",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-x25519-1",
         "publicKeyJwk":{
            "kty":"OKP",
            "crv":"X25519",
            "x":"GDTrI66K0pFfO54tlCSvfjjNapIs44dzpneBgyx0S3E"
         }
      },
      {
         "id":"did:example:bob#key-x25519-2",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-x25519-2",
         "publicKeyJwk":{
            "kty":"OKP",
            "crv":"X25519",
            "x":"UT9S3F5ep16KSNBBShU2wh3qSfqYjlasZimn0mB8_VM"
         }
      },
      {
         "id":"did:example:bob#key-x25519-3",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-x25519-3",
         "publicKeyJwk":{
            "kty":"OKP",
            "crv":"X25519",
            "x":"82k2BTUiywKv49fKLZa-WwDi8RBf0tB0M8bvSAUQ3yY"
         }
      },
      {
         "id":"did:example:bob#key-p256-1",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-p256-1",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-256",
            "x":"FQVaTOksf-XsCUrt4J1L2UGvtWaDwpboVlqbKBY2AIo",
            "y":"6XFB9PYo7dyC5ViJSO9uXNYkxTJWn0d_mqJ__ZYhcNY"
         }
      },
      {
         "id":"did:example:bob#key-p256-2",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-p256-2",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-256",
            "x":"n0yBsGrwGZup9ywKhzD4KoORGicilzIUyfcXb1CSwe0",
            "y":"ov0buZJ8GHzV128jmCw1CaFbajZoFFmiJDbMrceCXIw"
         }
      },
      {
         "id":"did:example:bob#key-p384-1",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-p384-1",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-384",
            "x":"MvnE_OwKoTcJVfHyTX-DLSRhhNwlu5LNoQ5UWD9Jmgtdxp_kpjsMuTTBnxg5RF_Y",
            "y":"X_3HJBcKFQEG35PZbEOBn8u9_z8V1F9V1Kv-Vh0aSzmH-y9aOuDJUE3D4Hvmi5l7"
         }
      },
      {
         "id":"did:example:bob#key-p384-2",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-p384-2",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-384",
            "x":"2x3HOTvR8e-Tu6U4UqMd1wUWsNXMD0RgIunZTMcZsS-zWOwDgsrhYVHmv3k_DjV3",
            "y":"W9LLaBjlWYcXUxOf6ECSfcXKaC3-K9z4hCoP0PS87Q_4ExMgIwxVCXUEB6nf0GDd"
         }
      },
      {
         "id":"did:example:bob#key-p521-1",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-p521-1",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-521",
            "x":"Af9O5THFENlqQbh2Ehipt1Yf4gAd9RCa3QzPktfcgUIFADMc4kAaYVViTaDOuvVS2vMS1KZe0D5kXedSXPQ3QbHi",
            "y":"ATZVigRQ7UdGsQ9j-omyff6JIeeUv3CBWYsZ0l6x3C_SYqhqVV7dEG-TafCCNiIxs8qeUiXQ8cHWVclqkH4Lo1qH"
         }
      },
      {
         "id":"did:example:bob#key-p521-2",
         "type":"JsonWebKey2020",
         "controller":"did:example:bob#key-p521-2",
         "publicKeyJwk":{
            "kty":"EC",
            "crv":"P-521",
            "x":"ATp_WxCfIK_SriBoStmA0QrJc2pUR1djpen0VdpmogtnKxJbitiPq-HJXYXDKriXfVnkrl2i952MsIOMfD2j0Ots",
            "y":"AEJipR0Dc-aBZYDqN51SKHYSWs9hM58SmRY1MxgXANgZrPaq1EeGMGOjkbLMEJtBThdjXhkS5VlXMkF0cYhZELiH"
         }
      }
   ]
}

§ Appendix C. Test Vectors

This section provides the test vectors. The following the test vectors might be used to validate implementations of DIDComm Messaging. The test vectors use private keys defined in the Appendix A and public keys defined in the Appendix B.

§ C.1. DIDComm Plaintext Messages

The following example defines DIDComm Plaintext message. The message is used for DIDComm Signed Messages and DIDComm Encrypted Messages.

{
   "id":"1234567890",
   "typ":"application/didcomm-plain+json",
   "type":"http://example.com/protocols/lets_do_lunch/1.0/proposal",
   "from":"did:example:alice",
   "to":[
      "did:example:bob"
   ],
   "created_time":1516269022,
   "expires_time":1516385931,
   "body":{
      "messagespecificattribute":"and its value"
   }
}

§ C.2 DIDComm Signed Messages

This section provides examples for DIDComm Signed Messages. Examples sign DIDComm Plaintext Message.

This example uses EdDSA digital signature with a curve Ed25519.

{
   "payload":"eyJpZCI6IjEyMzQ1Njc4OTAiLCJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXBsYWluK2pzb24iLCJ0eXBlIjoiaHR0cDovL2V4YW1wbGUuY29tL3Byb3RvY29scy9sZXRzX2RvX2x1bmNoLzEuMC9wcm9wb3NhbCIsImZyb20iOiJkaWQ6ZXhhbXBsZTphbGljZSIsInRvIjpbImRpZDpleGFtcGxlOmJvYiJdLCJjcmVhdGVkX3RpbWUiOjE1MTYyNjkwMjIsImV4cGlyZXNfdGltZSI6MTUxNjM4NTkzMSwiYm9keSI6eyJtZXNzYWdlc3BlY2lmaWNhdHRyaWJ1dGUiOiJhbmQgaXRzIHZhbHVlIn19",
   "signatures":[
      {
         "protected":"eyJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXNpZ25lZCtqc29uIiwiYWxnIjoiRWREU0EifQ",
         "signature":"FW33NnvOHV0Ted9-F7GZbkia-vYAfBKtH4oBxbrttWAhBZ6UFJMxcGjL3lwOl4YohI3kyyd08LHPWNMgP2EVCQ",
         "header":{
            "kid":"did:example:alice#key-1"
         }
      }
   ]
}

This example uses ES256 digital signature.

{
   "payload":"eyJpZCI6IjEyMzQ1Njc4OTAiLCJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXBsYWluK2pzb24iLCJ0eXBlIjoiaHR0cDovL2V4YW1wbGUuY29tL3Byb3RvY29scy9sZXRzX2RvX2x1bmNoLzEuMC9wcm9wb3NhbCIsImZyb20iOiJkaWQ6ZXhhbXBsZTphbGljZSIsInRvIjpbImRpZDpleGFtcGxlOmJvYiJdLCJjcmVhdGVkX3RpbWUiOjE1MTYyNjkwMjIsImV4cGlyZXNfdGltZSI6MTUxNjM4NTkzMSwiYm9keSI6eyJtZXNzYWdlc3BlY2lmaWNhdHRyaWJ1dGUiOiJhbmQgaXRzIHZhbHVlIn19",
   "signatures":[
      {
         "protected":"eyJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXNpZ25lZCtqc29uIiwiYWxnIjoiRVMyNTYifQ",
         "signature":"gcW3lVifhyR48mLHbbpnGZQuziskR5-wXf6IoBlpa9SzERfSG9I7oQ9pssmHZwbvJvyMvxskpH5oudw1W3X5Qg",
         "header":{
            "kid":"did:example:alice#key-2"
         }
      }
   ]
}

This example uses ES256K digital signature.

{
   "payload":"eyJpZCI6IjEyMzQ1Njc4OTAiLCJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXBsYWluK2pzb24iLCJ0eXBlIjoiaHR0cDovL2V4YW1wbGUuY29tL3Byb3RvY29scy9sZXRzX2RvX2x1bmNoLzEuMC9wcm9wb3NhbCIsImZyb20iOiJkaWQ6ZXhhbXBsZTphbGljZSIsInRvIjpbImRpZDpleGFtcGxlOmJvYiJdLCJjcmVhdGVkX3RpbWUiOjE1MTYyNjkwMjIsImV4cGlyZXNfdGltZSI6MTUxNjM4NTkzMSwiYm9keSI6eyJtZXNzYWdlc3BlY2lmaWNhdHRyaWJ1dGUiOiJhbmQgaXRzIHZhbHVlIn19",
   "signatures":[
      {
         "protected":"eyJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLXNpZ25lZCtqc29uIiwiYWxnIjoiRVMyNTZLIn0",
         "signature":"EGjhIcts6tqiJgqtxaTiTY3EUvL-_rLjn9lxaZ4eRUwa1-CS1nknZoyJWbyY5NQnUafWh5nvCtQpdpMyzH3blw",
         "header":{
            "kid":"did:example:alice#key-3"
         }
      }
   ]
}

§ C.3. DIDComm Encrypted Messages

This section provides examples for DIDComm Encrypted Messages. Examples encrypt the DIDComm Plaintext Message.

This example uses ECDH-ES key wrapping algorithm using key with X25519 elliptic curve and XC20P for content encryption of the message.

{
   "ciphertext":"KWS7gJU7TbyJlcT9dPkCw-ohNigGaHSukR9MUqFM0THbCTCNkY-g5tahBFyszlKIKXs7qOtqzYyWbPou2q77XlAeYs93IhF6NvaIjyNqYklvj-OtJt9W2Pj5CLOMdsR0C30wchGoXd6wEQZY4ttbzpxYznqPmJ0b9KW6ZP-l4_DSRYe9B-1oSWMNmqMPwluKbtguC-riy356Xbu2C9ShfWmpmjz1HyJWQhZfczuwkWWlE63g26FMskIZZd_jGpEhPFHKUXCFwbuiw_Iy3R0BIzmXXdK_w7PZMMPbaxssl2UeJmLQgCAP8j8TukxV96EKa6rGgULvlo7qibjJqsS5j03bnbxkuxwbfyu3OxwgVzFWlyHbUH6p",
   "protected":"eyJlcGsiOnsia3R5IjoiT0tQIiwiY3J2IjoiWDI1NTE5IiwieCI6IkpIanNtSVJaQWFCMHpSR193TlhMVjJyUGdnRjAwaGRIYlc1cmo4ZzBJMjQifSwiYXB2IjoiTmNzdUFuclJmUEs2OUEtcmtaMEw5WFdVRzRqTXZOQzNaZzc0QlB6NTNQQSIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJYQzIwUCIsImFsZyI6IkVDREgtRVMrQTI1NktXIn0",
   "recipients":[
      {
         "encrypted_key":"3n1olyBR3nY7ZGAprOx-b7wYAKza6cvOYjNwVg3miTnbLwPP_FmE1A",
         "header":{
            "kid":"did:example:bob#key-x25519-1"
         }
      },
      {
         "encrypted_key":"j5eSzn3kCrIkhQAWPnEwrFPMW6hG0zF_y37gUvvc5gvlzsuNX4hXrQ",
         "header":{
            "kid":"did:example:bob#key-x25519-2"
         }
      },
      {
         "encrypted_key":"TEWlqlq-ao7Lbynf0oZYhxs7ZB39SUWBCK4qjqQqfeItfwmNyDm73A",
         "header":{
            "kid":"did:example:bob#key-x25519-3"
         }
      }
   ],
   "tag":"6ylC_iAs4JvDQzXeY6MuYQ",
   "iv":"ESpmcyGiZpRjc5urDela21TOOTW8Wqd1"
}

This example uses ECDH-ES key wrapping algorithm using key with NIST defined P-384 elliptic curve and A256CBC-HS512 for content encryption of the message.

{
   "ciphertext":"HPnc9w7jK0T73Spifq_dcVJnONbT9MZ9oorDJFEBJAfmwYRqvs1rKue-udrNLTTH0qjjbeuji01xPRF5JiWyy-gSMX4LHdLhPxHxjjQCTkThY0kapofU85EjLPlI4ytbHiGcrPIezqCun4iDkmb50pwiLvL7XY1Ht6zPUUdhiV6qWoPP4qeY_8pfH74Q5u7K4TQ0uU3KP8CVZQuafrkOBbqbqpJV-lWpWIKxil44f1IT_GeIpkWvmkYxTa1MxpYBgOYa5_AUxYBumcIFP-b6g7GQUbN-1SOoP76EzxZU_louspzQ2HdEH1TzXw2LKclN8GdxD7kB0H6lZbZLT3ScDzSVSbvO1w1fXHXOeOzywuAcismmoEXQGbWZm7wJJJ2r",
   "protected":"eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTM4NCIsIngiOiIxNjFhZ0dlYWhHZW1IZ25qSG1RX0JfU09OeUJWZzhWTGRoVGdWNVc1NFZiYWJ5bGxpc3NuWjZXNzc5SW9VcUtyIiwieSI6ImNDZXFlRmdvYm9fY1ItWTRUc1pCWlg4dTNCa2l5TnMyYi12ZHFPcU9MeUNuVmdPMmpvN25zQV9JQzNhbnQ5T1gifSwiYXB2IjoiTEpBOUVva3M1dGFtVUZWQmFsTXdCaEo2RGtEY0o4SEs0U2xYWldxRHFubyIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiRUNESC1FUytBMjU2S1cifQ",
   "recipients":[
      {
         "encrypted_key":"SlyWCiOaHMMH9CqSs2CHpRd2XwbueZ1-MfYgKVepXWpgmTgtsgNOAaYwV5pxK3D67HV51F-vLBFlAHke7RYp_GeGDFYhAf5s",
         "header":{
            "kid":"did:example:bob#key-p384-1"
         }
      },
      {
         "encrypted_key":"5e7ChtaRgIlV4yS4NSD7kEo0iJfFmL_BFgRh3clDKBG_QoPd1eOtFlTxFJh-spE0khoaw8vEEYTcQIg4ReeFT3uQ8aayz1oY",
         "header":{
            "kid":"did:example:bob#key-p384-2"
         }
      }
   ],
   "tag":"bkodXkuuwRbqksnQNsCM2YLy9f0v0xNgnhSUAoFGtmE",
   "iv":"aE1XaH767m7LY0JTN7RsAA"
}

This example uses ECDH-ES key wrapping algorithm using key with NIST defined P-521 elliptic curve and A256GCM for content encryption of the message.

{
   "ciphertext":"mxnFl4s8FRsIJIBVcRLv4gj4ru5R0H3BdvyBWwXV3ILhtl_moqzx9COINGomP4ueuApuY5xdMDvRHm2mLo6N-763wjNSjAibNrqVZC-EG24jjYk7RPZ26fEW4z87LHuLTicYCD4yHqilRbRgbOCT0Db5221Kec0HDZTXLzBqVwC2UMyDF4QT6Uz3fE4f_6BXTwjD-sEgM67wWTiWbDJ3Q6WyaOL3W4ukYANDuAR05-SXVehnd3WR0FOg1hVcNRao5ekyWZw4Z2ekEB1JRof3Lh6uq46K0KXpe9Pc64UzAxEID93SoJ0EaV_Sei8CXw2aJFmZUuCf8YISWKUz6QZxRvFKUfYeflldUm9U2tY96RicWgUhuXgv",
   "protected":"eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTUyMSIsIngiOiJBRWtrc09abW1oZkZYdU90MHMybVdFYlVybVQ3OXc1SFRwUm9TLTZZNXpkYlk5T0I5b2RHb2hDYm1PeGpqY2VhWUU5ZnNaX3RaNmdpTGFBNUFEUnBrWE5VIiwieSI6IkFDaWJnLXZEMmFHVEpHbzlmRUl6Q1dXT2hSVUlObFg3Q1hGSTJqeDlKVDZmTzJfMGZ3SzM2WTctNHNUZTRpRVVSaHlnU1hQOW9TVFczTkdZTXVDMWlPQ3AifSwiYXB2IjoiR09lbzc2eW02TkNnOVdXTUVZZlcwZVZEVDU2Njh6RWhsMnVBSVctRS1IRSIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiRUNESC1FUytBMjU2S1cifQ",
   "recipients":[
      {
         "encrypted_key":"W4KOy5W88iPPsDEdhkJN2krZ2QAeDxOIxW-4B21H9q89SHWexocCrw",
         "header":{
            "kid":"did:example:bob#key-p521-1"
         }
      },
      {
         "encrypted_key":"uxKPkF6-sIiEkdeJcUPJY4lvsRg_bvtLPIn7eIycxLJML2KM6-Llag",
         "header":{
            "kid":"did:example:bob#key-p521-2"
         }
      }
   ],
   "tag":"aPZeYfwht2Nx9mfURv3j3g",
   "iv":"lGKCvg2xrvi8Qa_D"
}

This example uses ECDH-1PU key wrapping algorithm using key with X25519 elliptic curve and A256CBC-HS512 for content encryption of the message.

{
   "ciphertext":"MJezmxJ8DzUB01rMjiW6JViSaUhsZBhMvYtezkhmwts1qXWtDB63i4-FHZP6cJSyCI7eU-gqH8lBXO_UVuviWIqnIUrTRLaumanZ4q1dNKAnxNL-dHmb3coOqSvy3ZZn6W17lsVudjw7hUUpMbeMbQ5W8GokK9ZCGaaWnqAzd1ZcuGXDuemWeA8BerQsfQw_IQm-aUKancldedHSGrOjVWgozVL97MH966j3i9CJc3k9jS9xDuE0owoWVZa7SxTmhl1PDetmzLnYIIIt-peJtNYGdpd-FcYxIFycQNRUoFEr77h4GBTLbC-vqbQHJC1vW4O2LEKhnhOAVlGyDYkNbA4DSL-LMwKxenQXRARsKSIMn7z-ZIqTE-VCNj9vbtgR",
   "protected":"eyJlcGsiOnsia3R5IjoiT0tQIiwiY3J2IjoiWDI1NTE5IiwieCI6IkdGY01vcEpsamY0cExaZmNoNGFfR2hUTV9ZQWY2aU5JMWRXREd5VkNhdzAifSwiYXB2IjoiTmNzdUFuclJmUEs2OUEtcmtaMEw5WFdVRzRqTXZOQzNaZzc0QlB6NTNQQSIsInNraWQiOiJkaWQ6ZXhhbXBsZTphbGljZSNrZXkteDI1NTE5LTEiLCJhcHUiOiJaR2xrT21WNFlXMXdiR1U2WVd4cFkyVWphMlY1TFhneU5UVXhPUzB4IiwidHlwIjoiYXBwbGljYXRpb24vZGlkY29tbS1lbmNyeXB0ZWQranNvbiIsImVuYyI6IkEyNTZDQkMtSFM1MTIiLCJhbGciOiJFQ0RILTFQVStBMjU2S1cifQ",
   "recipients":[
      {
         "encrypted_key":"o0FJASHkQKhnFo_rTMHTI9qTm_m2mkJp-wv96mKyT5TP7QjBDuiQ0AMKaPI_RLLB7jpyE-Q80Mwos7CvwbMJDhIEBnk2qHVB",
         "header":{
            "kid":"did:example:bob#key-x25519-1"
         }
      },
      {
         "encrypted_key":"rYlafW0XkNd8kaXCqVbtGJ9GhwBC3lZ9AihHK4B6J6V2kT7vjbSYuIpr1IlAjvxYQOw08yqEJNIwrPpB0ouDzKqk98FVN7rK",
         "header":{
            "kid":"did:example:bob#key-x25519-2"
         }
      },
      {
         "encrypted_key":"aqfxMY2sV-njsVo-_9Ke9QbOf6hxhGrUVh_m-h_Aq530w3e_4IokChfKWG1tVJvXYv_AffY7vxj0k5aIfKZUxiNmBwC_QsNo",
         "header":{
            "kid":"did:example:bob#key-x25519-3"
         }
      }
   ],
   "tag":"uYeo7IsZjN7AnvBjUZE5lNryNENbf6_zew_VC-d4b3U",
   "iv":"o02OXDQ6_-sKz2PX_6oyJg"
}

In this example, the message is first signed with EdDSA digital signature and then encrypted with ECDH-1PU key wrapping algorithm using key with NIST defined P-521 elliptic curve and A256CBC-HS512 for content encryption of the message.

{
   "ciphertext":"WCufCs2lMZfkxQ0JCK92lPtLFgwWk_FtRWOMj52bQISa94nEbIYqHDUohIbvLMgbSjRcJVusZO04UthDuOpSSTcV5GBi3O0cMrjyI_PZnTb1yikLXpXma1bT10D2r5TPtzRMxXF3nFsr9y0JKV1TsMtn70Df2fERx2bAGxcflmd-A2sMlSTT8b7QqPtn17Yb-pA8gr4i0Bqb2WfDzwnbfewbukpRmPA2hsEs9oLKypbniAafSpoiQjfb19oDfsYaWWXqsdjTYMflqH__DqSmW52M-SUp6or0xU0ujbHmOkRkcdh9PsR5YsPuIWAqYa2hfjz_KIrGTxvCos0DMiZ4Lh_lPIYQqBufSdFH5AGChoekFbQ1vcyIyYMFugzOHOgZ2TwEzv94GCgokBHQR4_qaU_f4Mva64KPwqOYdm5f4KX16afTJa-IV7ar7__2L-A-LyxmC5KIHeGOedV9kzZBLC7TuzRAuE3vY7pkhLB1jPE6XpTeKXldljaeOSEVcbFUQtsHOSPz9JXuhqZ1fdAx8qV7hUnSAd_YMMDR3S6SXtem8ak2m98WPvKIxhCbcto7W2qoNYMT7MPvvid-QzUvTdKtyovCvLzhyYJzMjZxmn9-EnGhZ5ITPL_xFfLyKxhSSUVz3kSwK9xuOj3KpJnrrD7xrp5FKzEaJVIHWrUW90V_9QVLjriThZ36fA3ipvs8ZJ8QSTnGAmuIQ6Z2u_r4KsjL_mGAgn47qyqRm-OSLEUE4_2qB0Q9Z7EBKakCH8VPt09hTMDR62aYZYwtmpNs9ISu0VPvFjh8UmKbFcQsVrz90-x-r-Q1fTX9JaIFcDy7aqKcI-ai3tVF_HDR60Jaiw",
   "protected":"eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiJObHJ3UHZ0SUluZWNpeUVrYTRzMi00czhPalRidEZFQVhmTC12Z2x5enFvIiwieSI6ImhiMnZkWE5zSzVCQ2U3LVhaQ0dfLTY0R21UT19rNUlNWFBaQ00xdGFUQmcifSwiYXB2Ijoiei1McXB2VlhEYl9zR1luM21qUUxwdXUyQ1FMZXdZdVpvVFdPSVhQSDNGTSIsInNraWQiOiJkaWQ6ZXhhbXBsZTphbGljZSNrZXktcDI1Ni0xIiwiYXB1IjoiWkdsa09tVjRZVzF3YkdVNllXeHBZMlVqYTJWNUxYQXlOVFl0TVEiLCJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLWVuY3J5cHRlZCtqc29uIiwiZW5jIjoiQTI1NkNCQy1IUzUxMiIsImFsZyI6IkVDREgtMVBVK0EyNTZLVyJ9",
   "recipients":[
      {
         "encrypted_key":"ZIL6Leligq1Xps_229nlo1xB_tGxOEVoEEMF-XTOltI0QXjyUoq_pFQBCAnVdcWNH5bmaiuzCYOmZ9lkyXBkfHO90KkGgODG",
         "header":{
            "kid":"did:example:bob#key-p256-1"
         }
      },
      {
         "encrypted_key":"sOjs0A0typIRSshhQoiJPoM4o7YpR5LA8SSieHZzmMyIDdD8ww-4JyyQhqFYuvfS4Yt37VF4z7Nd0OjYVNRL-iqPnoJ3iCOr",
         "header":{
            "kid":"did:example:bob#key-p256-2"
         }
      }
   ],
   "tag":"nIpa3EQ29hgCkA2cBPde2HpKXK4_bvmL2x7h39rtVEc",
   "iv":"mLqi1bZLz7VwqtVVFsDiLg"
}

In this example, the message is first signed with EdDSA digital signature and then encrypted with ECDH-1PU key wrapping algorithm using key with X25519 elliptic curve and A256CBC-HS512 for content encryption of the message. After that the message is encrypted a second time with ECDH-ES key wrapping algorithm using key with X25519 elliptic curve and XC20P for content encryption of the message. The second anoncrypt is used to protect the sender ID.

{
   "ciphertext":"lfYmR7CNas5hOePxWQEkUEwzSRds3t5GkMW4VUZKJWJ7H3y1X8a1RnUg3c0BCqdszzhZk8xE0vfQ67vJAWGdev8OWy7oGY_e1o4iAVj3mPNfnV5N7sjld6yUhrxqDsxtmVAp7LAipbJNhxqBoEXdb8hPbdPeUIov-5X0_cQHpHalSD6zMoyUPb0cCnw8bfmdN3aaVDrzsZRIkvhezZCkaQFMO75XKVEDyTzn8Eqwgpg_tzD_Hr00jHa9mTyTiDA_1ZzqleF-XSe5NEtFc7_BukgjPWMZAouPMWwIP0h-BPULxUzYcWKfC6hiU2ZuxWz8Fs8v9r6MCAaPOG37oA_yfWwE_FWl7x61sl6iZfDVQhOTkdlXNoZ0LiaC4ImXop2wSvKimkGqhysj1OefrUrpHmSx1qNz7vCWqW8Mo7fykXQCVYr6zXmcvWF5-KvXDu6DR3EFlgs6An9tWLv1flDrZWb-lS6RlL6Z8AqmLjP0Yb2r6mTopiulTTpXXpwe-Qs1_DHDGi0DfsZmcYhyra-F8YQ3tGIgy6wWCtyBh7Fq_zRy8RMvV3DkaLHYTekIle0YOoRdZRJBb3ycXHycIi7iT1ewOFlIGjsBg73Hkqa6O1weewS3uIxl4veO6cBOksfDRpC279X9tV1HDqROBolNBsWHQ2UpUD1Bat8UnfJMrwBcZkGQCjhlR9SSlZzEIqP3leRh5e2y2FGTm7wNRNwmgl6s6OUiKD-nbUnnSugGzolbavafHS80XrdfEuUyuPjnpQQQROapFfcjd7dSLd58g9OjOEqb1-Edk4KcW-yYU17_zfIzv1qykEH7F22Nq9HGbReXuao83ItUWgpBDZ-uf-_RbcpW2X1U5QGnI1SF4Trbhx74lnswEF_AlZ4SUh7frcMfKQLYobT1X_wIEY8pwN1AzWf482LJKKsxm0EcY73vf0n3uT_OS3EgBNCVYyF6_snm7MdOV-RM5ZZyQl64BsZ4aL4RVVCOa8bxYGPxvpOf9Ay-aQjwYQfyFxayRJiQWkywk8SRAdLLfSiveqvXAoIIi_XI98CRIaJ6DSKr-TuCDlz4yVP_8emS_S0S7F-Buh-P6nzjdJ04CAm95p6do_q8jk1IRHvubqrPKcpvk4U3p-6obJK9feJPffoe3-ddJvKJ5h8Et3xEKG7oId3NkbbFfYUnkEyC_wUeKtyrXK8uBz5HKhW1S27qsBAnKv5WTCyfrDsfX0eTaqdeJ3O9uR4niBc2sa2t89G5AEKWcOUnJcytAAAuhMZiz2zXXhmffPG5A7QSmZMAl75CP6ulN0KCBE0nTeuvNPueqpF4PV4CCcMfokz0hu5k5oo9FHfkQMVDBTiQUtEezIXiglqhu6VwcDgbbatAKUIYxnoisHKPg17zGMl5VMULVY5WBYPAUylKpWELnMc9BHUHNUxfSVlqdd847v__D1Go17MTsQujVGQQuM61Ay0-z1JwN0fki0M8t20U_sWX5jNMbdZCPBxy7rpZlztaF01j1NCaM3ZPh-_KLy8vQ584R5I5LlE5OejgyLQYMOMzSgUZZEAeTGV_S-kEnt36k-L8Kbyv_LWuiuTQzwLSwlmWOKLdDbmjEjA1JsEaKmorDKz0q7MFIoC-gKKJBjPTJ5PxJLJj4RHOxxDWhx00HjLLE3S1B6uAvKVUhN4ka_wWusVqffrRZm_e7Oz0hbCO8pT4tzlbFWTu0-O44kHkRjfubEi4PnaNzKbGMXTrDo7aY6sgiDB8KlJSsKrNeG0OLjBAYF_zmHlrqctFQidTD_YIDzcSfkCTrMoOYa07nXG6E1nArScOgkNuNkPVhCq_VD6w-pZ1mSUBwKVCnjNueTrB5RvFBydaoWcAAX3OtH8yFeDWGzlRYWJNKEKull_Vah8B7nwwnTPxyeUwnr2txlwDvLx9ASrl5CjwvLc9bL7jCa6SrWt3hPjvjDY4JdFxnCqyyXD11Mpt2kyA4TTBaBbzI5Kja6pKsCUw0QCTCfTBu7bKGTOJKai32c4WRXvpVgIowOzdyjtKD0LgnY2fRTpJWpcTMVAHPfSad0jc23iTwOKcJQ0n_ExfOxzW_PSvAYbakrRwdZdDefb_fLrILxgS7OA9KepGQOJnp0-X_o1bBkXsm_cvVhcprLViUxHR1uCTMXaUl24viekps45aODvfBj5OsG3GrEShqtLb7ukEHEJjLsIe1l-4kFtNp4RlPZlapYgNyMSjnGopw2D51khuOHdJ2yLWASgFJPIa4dan4KTcDhp7qmbijN8JR_s_p1DB4E1nFlQPuncA8lIiuGv2PKHKXQkkuHcKmPMYTjRlam5IBHXQPV_njHMAIV60XU8kxa5G7t-Iwl_6OeRIj_HXdf5mfdTNEYlwbQWHInkS4U32RD9Kf0u6SC1bpRZx6AbFK8xlIgUPhB_sP3kG_ZZIZhcJ1Oy6Q7pAzmKXZYWKMkDWZk7a-WsiA0Z8gOcd7PYA13GRIw0MT_GIRcFRfkp7821j2ArHHo6jagqMdEuCZHzHrfwD0XHzT4FP3-aTaHIqrKx0TiYRfn2k2Q",
   "protected":"eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTUyMSIsIngiOiJBYmxoeVVENUxYNE9zWDhGRTVaODRBX09CYThiOHdhVUhXSFExbTBnczhuSFVERDdySDlJRWRZbzJUSzFQYU5ha05aSk54a1FBWC1aUkxWa1BoNnV4eTJNIiwieSI6IkFQTjh6c0xEZGJpVjN0LTloWTJFQzFVZWEzTm5tMzFtNWowRmNiUWM0Y2ZWQmFNdzVCQ2VpcU9QWkljZTVMNjI4bnVORkxKR2szSjh6SVBPYUlLU0xmaTEifSwiYXB2IjoiR09lbzc2eW02TkNnOVdXTUVZZlcwZVZEVDU2Njh6RWhsMnVBSVctRS1IRSIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJYQzIwUCIsImFsZyI6IkVDREgtRVMrQTI1NktXIn0",
   "recipients":[
      {
         "encrypted_key":"iuVx5qAiRtijMfHnkF95_ByjHyiAmRqNTrExrEQK4p7HwW7sit1F0g",
         "header":{
            "kid":"did:example:bob#key-p521-1"
         }
      },
      {
         "encrypted_key":"6OWnv-tY1ZDUBt8uRNpmteoXTVDzRGz2UF04Y2eh2-bp2jiViU8VCw",
         "header":{
            "kid":"did:example:bob#key-p521-2"
         }
      }
   ],
   "tag":"pEh6LS1GCTYQaWR-6vAe_Q",
   "iv":"ZMHYqq1xV1X81bFzzEH_iAfBcL75fznZ"
}
Table of Contents