Skip to main content
Version: 0.6

Connection

info

The IOTA DIDComm Specification is in the RFC phase and may undergo changes. Suggestions are welcome at GitHub #464.

  • Version: 0.1
  • Status: IN-PROGRESS
  • Last Updated: 2021-10-29

Overview

Allows establishment of a DIDComm connection between two parties. The connection may be established by an explicit invitation delivered out-of-bandsuch as a QR code, URL, or emailor by following an implicit invitation in the form of a service endpoint attached to a public DID document.

Relationships

Example Use-Cases

  • A corporation offers a QR code on their website for customers to connect to their services.
  • A person sends an invitation as an email to a friend, to exchange information.
  • A device has a service embedded in their DID, that allows others to connect to it, in order to read data.

Roles

  • Inviter: offers methods to establish connections.
  • Invitee: may connect to the inviter using offered methods.

Interaction

ConnectionDiagram

For guidance on diagrams see the corresponding section in the overview.

Messages

1. invitation

  • Type: https://didcomm.org/out-of-band/2.0/invitation
  • Role: inviter

A message containing information on how to connect to the inviter. This message is delivered out-of-band, e.g. in form of a link or QR code. The message contains all information required to establish a DIDComm connection.

Structure

The general structure of the invitation message is described in the Out Of Band Messages of the DIDComm specification. Note that the invitation message may be signed to provide tamper resistance.

The actual invitation is contained in the attachments field in the message, which is structured as follows:

{
"serviceId": DIDUrl, // OPTIONAL
"service": {
"serviceEndpoint": string, // REQUIRED
"accept": [string], // OPTIONAL
"recipientKeys": [DIDUrl | DIDKey], // OPTIONAL
"routingKeys": [DIDUrl | DIDKey], // OPTIONAL
}, // OPTIONAL
FieldDescriptionRequired
serviceIdA string representing a DIDUrl referencing a resolvable service.1 2
serviceA structure analogous to the DID service specification, including all information necessary to establish a connection with the inviter.1
serviceEndpointA URI including all details needed to connect to the inviter.
acceptAn optional array of DIDComm profiles in the order of preference for sending a message to the endpoint. If omitted, defer to the accept field of the invitation body.
recipientKeysAn ordered array of DIDUrls or did:key strings referencing public keys, any of which may be used for anonymous encryption.3 4
routingKeysAn ordered array of DIDUrls or did:key strings referencing keys to be used when preparing the message for transmission; see DIDComm Routing.4

1 One of serviceId or service MUST be present for the invitee to be able to connect. If both fields are present, the invitee SHOULD default to the serviceId.

2 It is RECOMMENDED that the service referenced by serviceId conforms to the "DIDCommMessaging" service type from the DIDComm specification as it allows routingKeys to be included if necessary. The DID document referenced by serviceId SHOULD include one or more keyAgreement sections to use for anonymous encryption; the absence of any keyAgreement section implies no anonymous encryption will be used for the connection and an invitee may choose to reject such an invitation. A public serviceId may reveal the identity of the inviter to anyone able to view the invitation; if privacy is a concern using an inline service should be preferred. For a public organisation whose DID is already public knowledge, using serviceId has a few benefits: it establishes some level of trust that the invitee may be connecting to the correct party since a service from their public DID document is used, and the invitation may be re-used indefinitely even if the service referenced is updated with different endpoints. When using service instead of serviceId, a signed invitation may provide a similar level of trust. However, neither should be used as a complete replacement for interactive authentication due to the risk of man-in-the-middle attacks.

3 Note that recipientKeys may have multiple entries in order of preference of the inviter; this is to offer multiple key types (e.g. Ed25519, X25519) and an invitee may choose any key with which they are compatible. These keys may be static or generated once per invitation. Omitting recipientKeys implies that anonymous encryption will not be used in the ensuing DIDComm connection. It is RECOMMENDED to include as anonymous encryption ensures message integrity and protects communications from eavesdroppers over insecure channels. Invitees may choose to reject invitations that do not include recipientKeys if they want to enforce anonymous encryption.

4 Implementors should avoid using a DIDUrl for the recipientKeys or routingKeys if privacy is a concern, as may reveal the identity of the inviter to any party other than the invitee that intercepts the invitation. However, using a DIDUrl may be useful as it allows for key-rotation without needing to update the invitation.

Examples

The following examples include the entire DIDComm message structure for illustration, including message headers with the actual invitation payload defined in this specification included in the attachments section.

For further information on how to encode the invitation message for delivery refer to the DIDComm specification.

  1. Invitation with a single attachment:
{
"typ": "application/didcomm-plain+json",
"type": "https://didcomm.org/out-of-band/2.0/invitation",
"id": "fde5eb9e-0560-48cf-b860-acd178c1e0b0",
"body": {
"accept": ["didcomm/v2"]
},
"attachments": [
{
"@id": "request-0",
"mime-type": "application/json",
"data": {
"json": {
"service": {
"serviceEndpoint": "wss://example.com/path",
"recipientKeys": [
"did:key:z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ"
],
"routingKeys": []
}
}
}
}
]
}

Refer to the DIDComm specification for further information on how to encode the invitation message for delivery.

  1. Invitation with a goal indicated and two attachments in order of preference. An invitee should pick the first one with which they are compatible:
{
"typ": "application/didcomm-plain+json",
"type": "https://didcomm.org/out-of-band/2.0/invitation",
"id": "fde5eb9e-0560-48cf-b860-acd178c1e0b0",
"body": {
"goal_code": "issue-vc",
"goal": "To issue a Faber College Graduate credential",
"accept": ["didcomm/v2"]
},
"attachments": [
{
"@id": "request-0",
"mime-type": "application/json",
"data": {
"json": {
"service": {
"serviceEndpoint": "wss://example.com/path",
"accept": ["didcomm/v2"],
"recipientKeys": [
"did:key:z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ",
"did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9"
],
"routingKeys": [
"did:key:z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha"
]
}
}
}
},
{
"@id": "request-1",
"mime-type": "application/json",
"data": {
"json": {
"serviceId": "did:iota:123456789abcdefghi#didcomm-1"
}
}
}
]
}

2. connection

  • Type: iota/connection/0.1/connection
  • Role: invitee

Following a successful connection, the invitee sends its public keys necessary to establish anonymous encryption. This may be preceded by an invitation message, or the invitee may connect directly to the inviter in the case of an implicit invitation.

Structure

{
"recipientKey": DIDUrl | DIDKey, // OPTIONAL
"routingKeys": [DIDUrl | DIDKey], // OPTIONAL
}
FieldDescriptionRequired
recipientKeyA DIDUrl or did:key strings referencing a public key of the invitee to be used for anonymous encryption.1 2
routingKeysAn ordered array of DIDUrls or did:key strings referencing keys to be used by the inviter when preparing the message for transmission; see DIDComm Routing.2

The id of the preceding invitation message MUST be used as the pthid header property on this message. Both the thid and pthid properties MUST be omitted in the case of an implicit invitation when connecting to a public service endpoint of an inviter. See DIDComm Message Headers for more information.

1 If present, the recipientKey sent by the invitee MUST match the key type (e.g. Ed25519, X25519) of one of the recipientKeys in the invitation message, or of a keyAgreement public key attached to the inviter`s DID document in the case of an implicit invitation. The recipientKey should be omitted if no recipientKeys or keyAgreement sections are present, or if the invitee does not wish to use anonymous encryption for the connection. An inviter may choose to reject connection messages that omit a recipientKey, terminating the connection.

2 Similar to the considerations for the invitation message, implementors should avoid using a DIDUrl for the recipientKey or routingKeys as it may reveal the identity of the invitee to eavesdroppers prior to encryption being established. Using a DIDUrl for key rotation is less of a concern for a connection message as, unlike an invitation, the message is intended to be transient and should not persist beyond a single connection attempt.

Examples

  1. Connection with a P-384 Key DID as the recipient key:
{
"recipientKey": "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54"
}

Problem Reports

The following problem-report codes may be raised in the course of this protocol and are expected to be recognised and handled in addition to any general problem-reports. Implementers may also introduce their custom application-specific problem-reports.

For guidance on problem-reports and a list of general codes see problem reports.

CodeMessageDescription
e.p.msg.iota.connection.reject-connectionconnectionInviter rejects a connection request for any reason, e.g. untrusted invitee or lacking recipientKey for anonymous encryption.

Considerations

This section is non-normative.

  • Authentication: implementors SHOULD NOT use any information transmitted in the connection protocol for direct authentication or proof of identity. See the authentication protocol.

Unresolved Questions

  • List supported handshake protocols for authentication post-connection?
  • How do parties know what to do post-connection, send protocol in the invitation, or does one party just try to start a protocol immediately? For custom/corporate applications likely hard-coded, for general SSI wallets, it is an open question.

Further Reading