DIDComm Messaging through libp2p

Oliver Terbu
uPort
Published in
8 min readNov 29, 2021

by Oliver Terbu (ConsenSys Mesh), Alen Horvat (AceBlock)

Introduction

With InterPlanetary File System (IPFS) the Web3 community has established a critical piece of infrastructure that is used by the majority of web3 protocols to different degrees. Libp2p is part of the IPFS stack and is used for the underlying peer-to-peer network for discovery, routing and data exchange. Peers in the network can dial other peers in the network to exchange messages using various transports, like QUIC, TCP, WebSocket, and Bluetooth. Modular design of the libp2p framework enables it to build drivers for other transports. Peers can run on any device, as a cloud service, mobile application or in the browser and talk to each other as long as they are connected through the same libp2p network.

A peer in a libp2p network is identified through its peer identity (peer ID). A peer ID is essentially derived from the public key (hash) of the peer’s key pair which can change over time, specifically when keys are rotated or revoked. For that reason, peer IDs are insufficient for building a stable fully-decentralized messaging framework. W3C Decentralized Identifiers (DIDs), on the other hand, were designed to support key rotation while keeping a stable identifier. Hence, DIDs should be used as the more permanent public identifier for peers in the network, which would hold information about the peer IDs, libp2p network and supported protocols. Peers would still use their peer ID for libp2p routing and authentication. Alice and Bob would exchange their DID out of band and will be able to find their counterparty’s peer ID via their DIDs. In this way, the DID acts as an indirection layer for the peer ID, thus allowing Alice and Bob to change their peer ID for practical reasons without the need to notify each other.

Note: A peer ID is a term defined by libp2p and is not the same as a peer DID although a peer ID can also be used with a peer DID by following the approach described in this article.

Libp2p is a modular system of protocols and specifications for building P2P applications. It can be also used to build P2P messaging applications. although messaging through libp2p has limitations. Peers in the network are usually not always online, especially if Bob is travelling a lot, lives in an area with limited connectivity, is actually an intelligent car, or has a monthly limit with his mobile data plan. When Alice wants to send Bob a message and Bob is not online, then the likelihood of Bob eventually receiving the message reduces dramatically. DIF DIDComm Messaging solves this problem by defining mediator nodes that can run in high-availability mode. Those mediators can act as Alice and Bob’s mailboxes where both use DID authentication to receive the latest messages from their mediators. Instead of associating Bob’s peer ID with his DID, Bob would associate his mediator’s peer ID with the DID, so Alice would dial-up Bob’s mailbox through the libp2p network and first forward the message to the mediator. DIDComm Messaging ensures that only Bob can decrypt the message and that Bob can verify Alice authenticated the message through authenticated encryption (authcrypt). Additional trust, security and access management can be added through W3C Verifiable Credentials (VCs) that counteract spam and fraud.

This article explains how two parties, Alice and Bob, can securely communicate using DIDComm Messaging through a libp2p network, where discovery, security and trust are rooted in Decentralized Identity technologies. First, we present how Alice and Bob prepare and exchange information about their peers, next we describe how peers establish secure P2P connections, and last we present DIDComm message exchange via the channels. We assume you are familiar with DIDs and VCs. If you are not, check out DIF FAQ for a great intro.

Exchanging information

To start messaging, Alice and Bob must exchange information about their peers and mediators. DIDs help to establish a trusted Decentralized Identity layer for the peers, where peers can always find the latest information about the active mediators, peer IDs, authentication, and encryption keys. This enables mutual peer authentication and end-to-end stream encryption. We use the DID service property to manage and share peer information as presented below.

DIDComm Messaging service section using libp2p transport

Thus Alice and Bob need to exchange their DID out-of-band and clients will be able to discover, authenticate and connect. The design is applicable to almost all DID methods.

Establishing secure streams

Now that Alice and Bob exchanged information about their peers, the peers establish authenticated and end-to-end encrypted P2P streams. If at least one of the peers has public endpoints or supports NAT transversal, peers can connect directly. Since most services are behind firewalls or don’t have public endpoints, P2P connection can be established only via relay or proxy nodes. These nodes either help with the NAT traversal or simply relay all the traffic. Libp2p has full support for relay nodes that can be hosted by anyone, i.e. self-hosted or hosted by a 3rd party provider. Furthermore, every client can select which relay node(s) can be used to establish a connection with it and every new connection can be established via different nodes. Such an open design enables us to build a fully decentralized mesh of relay nodes.

After discovery, peers mutually authenticate. Authentication can be performed using peer IDs or any other DID authentication key(s). DIDs ensure that keys are valid (not revoked) and are linked to the DID. Modular design enables plug in various mutual authentication protocols, like mutual TLS. After a successful mutual authentication, the streams are end-to-end encrypted either using TLSv1.3 or Noise Protocol, both supporting perfect forward secrecy. Note that other encryption protocols or frameworks can be plugged in. Only allow-listed peers, i.e., DIDs of Alice or Bob registered with their clients, are allowed to open a stream. W3C Verifiable Credentials (VC) can be used to define more granular identity and access management policies.

Libp2p supports establishing a connection on the network levels, like QUIC, TCP/UDP, WebSocket, client authentication and traffic encryption. DIDComm Messaging is introduced on top of libp2p to fill-in the missing messaging capabilities.

Messaging

DIDComm Messaging (aka DIDComm V2) provides a secure, private communication methodology built atop the decentralized design of DIDs. Version 1 of DIDComm was specified in the HyperLedger (HL) Aries project as a set of HL Aries RFCs. With governance and further development moved to DIF, the goal was to specify one core specification for DIDComm Messaging that addresses previously defined gaps and achieve better development experience. In particular V2 relies on better formalized methods, simpler message structures, has no requirement for DID exchange, treats ephemeral and full mode in the same way and has explicit support for all DID methods. Another goal was to address requirements beyond the HL Aries community.

In DIDComm Messaging trust is rooted in DIDs. Atop DIDComm Messaging defines a set of methodologies to send messages between DIDs or more specifically their agents. Messages can be extended through specific DIDComm Messaging protocols. At a glance, DIDComm Messaging entails the following:

  • Defines a data model for a common plaintext messages structure i.e. headers, body.
  • JOSE-based authn and encryption between DIDs with repudiation by default.
  • Defines a methodology for DID rotation.
  • Defines a methodology for (onion-)routing for various network architectures.
  • Defines core protocols such as invitations and feature discovery.
  • Defines core transport protocols for HTTP(S) and WebSockets.
  • Defines an extensibility model for adding new sub-protocols (e.g., VC Exchange) and new transports (e.g., libp2p).

The following diagram shows the DIDComm Messaging mental model.

DIDComm Messaging Mental Model

Typically, if Alice wants to send a message to Bob, Bob sends Alice an explicit invitation or Bob gives her his public DID (implicit invitation through Bob’s DID Document). Alice would then extract the service endpoint and recipient/routing keys from the invitation and can start sending messages to Bob. The first message could already contain a DIDComm Messaging protocol message, since Alice can encrypt the message to Bob. After Bob receives the message, Bob can create a new DID for Alice and indicate the change through DID rotation.

DIDComm Messaging is transport-agnostic and DID Documents can be extended to support various transport mechanisms. The community developed approaches for HTTP(S) and WebSockets primarily, other transports such as Bluetooth are also under development.

Putting all together

DIDComm Messaging running on top of a libp2p overlay network enables us to build a next generation decentralized messaging framework. Libp2p enables establishing secure connections between peers regardless of their transport and IP properties (public, local, static, dynamic). Once peers establish secure connections with the help of DIDs, they can authenticate (DID Authentication) and exchange DIDComm Messaging protocol messages. Using a libp2p overlay network doesn’t require any changes to the DIDComm Messaging protocol as libp2p clients can support multiple messaging protocols and multiple different libp2p networks (private or public) — it can work via existing public IPFS network, private AceBlock network, and others. Layered architecture and clear separation of the P2P network from the messaging protocols, in our case DIDComm Messaging, enables us to design and develop the P2P network and DIDComm Messaging independently. Namely, the libP2P network doesn’t need to know anything about the DIDComm Messaging and vice versa. Using such a setup, anyone can build edge agents and mediator nodes. Maintenance of such a P2P network is inexpensive. It is built using open source components.

The proposed solution supports

  • direct communication (both clients have public IPs)
  • indirect communication (communication is relayed via libp2p relay nodes; messages can be relayed via random relay nodes or pre-defined ones)
  • synchronous message exchange (if both clients are online)
  • asynchronous message exchange via mediator nodes (if one of the clients is offline)
Sending Messages through DIDComm Messaging and libp2p

Conclusion and outlook

We outlined the next generation decentralized messaging solution built on top of DIDComm Messaging, DIDs and VCs and a libp2p overlay network. We presented how Alice and Bob establish a connection, exchange messages and demonstrated what connection types are supported.

We are currently working to demonstrate different setups and scenarios (using Veramo and AceBlock libp2p client), we are adding libp2p transport to the DIDComm Messaging specs and are working on the full framework design.

Stay tuned for more updates and join our Discord if you want to get involved!

--

--

Oliver Terbu
uPort
Editor for

Decentralization architect with uPort | ConsenSys. Member of CEN/CENELEC FG-BDLT, DIF, EEA, ISO/IEC TC307, OIDF and W3C.