§ DIDComm Messaging

Specification Status: Editor’s Draft

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

Editors:

Contributors: Daniel Hardman

Participate:
GitHub repo
File a bug
Commit history

§ Purpose and Scope

The purpose of DIDComm 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 can fix this. Using DIDComm, 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 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 works, consider a situation where Alice wants to negotiate with Bob to sell something online. Because DIDComm, 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 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 interactions:

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

§ Specific Requirements

The DIDComm 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, 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, A can talk to B without a direct connection to B; 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 devs start simple without heavy learning or dependencies; customize easily; facilitates higher-level protocols that inherit DIDComm’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 is message-based, asynchronous, and simplex. Agent X sends a message over channel A. Sometime later, it may receive a response from Agent Y 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.

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

§ Processing Model

§ Message Types

This spec discusses messages in three different formats. The casual phrase “DIDComm message” is ambiguous, but usually refers to DIDComm encrypted messages (the outermost box in the diagram below). These will constitute the vast majority of network traffic in most DIDComm 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 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 spec to give examples of headers and other internals. Depending on ambient security, plaintext may or may not be an appropriate format for DIDComm data at rest.

When higher-level protocols are built atop DIDComm, applications remove the protective envelope(s) and process the plaintext that’s inside. Specs 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.

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. Signed messages are only necessary when the origin of plaintext must 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 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 applications, and is the safest format for storing DIDComm data at rest.

The media type of a DIDComm encrypted non-nested 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. Future DIDComm specs that encompass comm 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 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

§ Examples

The following table provides an overview of examples for using the media type properties in various DIDComm messages:

DIDComm message typ
Encrypted application/didcomm-encrypted+json
Signed, then encrypted application/didcomm-encrypted+json
Encrypted, then encrypted application/didcomm-encrypted+json
Signed application/didcomm-signed+json
Plaintext application/didcomm-plain+json

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

§ 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 message, and are called headers. A message also includes attributes specific to the message type. Type specific message attributes are contained within the body attribute of a message.

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

The following example shows common elements of a 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

The predefined attributes of a DIDComm plaintext message at the level of its outer packaging (effectively, the “headers” of the message) are as follows:

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.

In the outer packaging of message metadata, DIDComm follows the extensibility pattern established by the JW* family of standards. (It also emulates the design of message headers in SMTP, request headers in HTTP, and labels on physical pieces of mail.) 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 explicitly rejects the X-* headers convention that creates divergent pseudo-standards; if a new header needs broad support, it must be standardized properly. Alternatively, a JSON-LD @context header can be added, providing namespacing for fields other than those predefined in the spec. 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 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’s relationship to JSON-LD and to the rich semantics and extensibility features it offers. The short answer is that DIDComm 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 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 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. 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 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 itself.

When a DID is rotated, the new DID is put into immediate use encrypting the message, and one additional attribute is 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 should 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

§ 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

Due to the triple Key Derivation algorithm used in ECDH-1PU, all messages sent via DIDComm have weak perfect forward secrecy without any additional security added by the transport layer. In ECDH-1PU this is achieved by encrypting the content encryption key with the output of the hash of the Ze (ECDH of ephemeral key and recipient static key) and Zs (ECDH of static sender key and recipient static key). With Ze bringing the changed derived secret in each message and Zs bringing the repudiable authenticity of each message, the resulting Z (hash of Ze and Zs) carries the properties of weak perfect forward secrecy and repudiable authenticity for each message as well.

§ 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"
    }
  ],
  ...
}

There should be only 1 entry in the recipients of the envelope, representing Bob. The corresponding kid header for this recipient MUST have did:example:jklmnopqrstuvwxyz1#key-1 as value. The packing process MUST extract the public key bytes found in publicKeyBase58 of Bob’s DID Doc KeyAgreement[0] 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 skid header

When the skid cannot be revealed in a plain-text JWE header (to avoid potentially leaking sender’s key id), the skid MAY be encrypted for each recipient. In this case, instead of having a skid protected header in the envelope, each recipient MAY include an encrypted_skid header with a value based on the encryption of skid using ECDH-ES Z computation of the epk and the recipient’s key as the encryption key.

For applications that don’t require this protection, they MAY use skid protected header directly without any additional recipient headers.

Applications MUST use either skid protected header or encrypted_skid recipients header but not both in the same envelope.

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

TODO: Add examples here

§ 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

TODO: Add examples here

§ 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, 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 appended at the end of the routingKeys section from the message recipient’s DID Document as per the process in [Sender Forward Process]. The key 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:

§ 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 attachment",
            "data": {
            	"jwe": {
                    //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/%VER/invitation

{
  "typ": "application/didcomm-plain+json",
  "type": "https://didcomm.org/out-of-band/%VER/invitation",
  "id": "<id used for context as pthid>",
  "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/0.1/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/0.1/invitation","id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","from":"did:example:alice","body":{"goal_code":"","goal": "","request~attach":[{"@id":"request-0","mime-type":"application/json","data":{"json":"<json of protocol message>"}}]}}

Base 64 URL Encoded:

eyJ0eXAiOiAiYXBwbGljYXRpb24vZGlkY29tbS1wbGFpbitqc29uIiwidHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMC4xL2ludml0YXRpb24iLCJpZCI6IjY5MjEyYTNhLWQwNjgtNGY5ZC1hMmRkLTQ3NDFiY2E4OWFmMyIsImZyb20iOiJkaWQ6ZXhhbXBsZTphbGljZSIsImJvZHkiOnsiZ29hbF9jb2RlIjoiIiwiZ29hbCI6ICIiLCJyZXF1ZXN0fmF0dGFjaCI6W3siQGlkIjoicmVxdWVzdC0wIiwibWltZS10eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6Ijxqc29uIG9mIHByb3RvY29sIG1lc3NhZ2U-In19XX19

Example URL:

http://example.com/path?_oob=eyJ0eXAiOiAiYXBwbGljYXRpb24vZGlkY29tbS1wbGFpbitqc29uIiwidHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMC4xL2ludml0YXRpb24iLCJpZCI6IjY5MjEyYTNhLWQwNjgtNGY5ZC1hMmRkLTQ3NDFiY2E4OWFmMyIsImZyb20iOiJkaWQ6ZXhhbXBsZTphbGljZSIsImJvZHkiOnsiZ29hbF9jb2RlIjoiIiwiZ29hbCI6ICIiLCJyZXF1ZXN0fmF0dGFjaCI6W3siQGlkIjoicmVxdWVzdC0wIiwibWltZS10eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6Ijxqc29uIG9mIHByb3RvY29sIG1lc3NhZ2U-In19XX19

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=eyJ0eXAiOiAiYXBwbGljYXRpb24vZGlkY29tbS1wbGFpbitqc29uIiwidHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMC4xL2ludml0YXRpb24iLCJpZCI6IjY5MjEyYTNhLWQwNjgtNGY5ZC1hMmRkLTQ3NDFiY2E4OWFmMyIsImZyb20iOiJkaWQ6ZXhhbXBsZTphbGljZSIsImJvZHkiOnsiZ29hbF9jb2RlIjoiIiwiZ29hbCI6ICIiLCJyZXF1ZXN0fmF0dGFjaCI6W3siQGlkIjoicmVxdWVzdC0wIiwibWltZS10eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6Ijxqc29uIG9mIHByb3RvY29sIG1lc3NhZ2U-In19XX19 with us, or paste the following into your browser:

http://example.com/path?_oob=eyJ0eXAiOiAiYXBwbGljYXRpb24vZGlkY29tbS1wbGFpbitqc29uIiwidHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMC4xL2ludml0YXRpb24iLCJpZCI6IjY5MjEyYTNhLWQwNjgtNGY5ZC1hMmRkLTQ3NDFiY2E4OWFmMyIsImZyb20iOiJkaWQ6ZXhhbXBsZTphbGljZSIsImJvZHkiOnsiZ29hbF9jb2RlIjoiIiwiZ29hbCI6ICIiLCJyZXF1ZXN0fmF0dGFjaCI6W3siQGlkIjoicmVxdWVzdC0wIiwibWltZS10eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6Ijxqc29uIG9mIHByb3RvY29sIG1lc3NhZ2U-In19XX19

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 1.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/1.0

§ Messages

§ ping

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

{
  "type": "https://didcomm.org/trust_ping/1.0/ping",
  "id": "518be002-de8e-456e-b3d5-8fe472477a86",
  "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/1.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.

§ 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

Table of Contents