The did:ssb Method v0.1

A DID Method based on SSB (Secure Scuttlebutt)


Latest version:
Previous version:
Charles E. Lehner (@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519)

This document is licensed under a Creative Commons Attribution 4.0 International Public License. (CC-BY)


Secure Scuttlebutt (SSB) is a peer-to-peer network and protocol for social applications based on append-only verifiable logs. The SSB DID Method (did:ssb) enables using SSB with Decentralized Identifiers (DIDs).

Status of This Document

This document is a draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organization or of the SSB community.

The Editor does not recommend using this specification on the main SSB network until it is stabilized with implementation experience.


This document describes how an SSB user can manage a DID corresponding to their SSB feed ID.


The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.


SSB DID Syntax rules are as follows, based on DID Core's ABNF:

ssb-did          = "did:ssb:" feed-id
feed-id          = feed-type ":" feed-chars
feed-type        = "ed25519"
feed-chars       = 1*(ALPHA / DIGIT / "." / "-" / "_")


The SSB feed ID, encoded for representation in the DID.
The SSB feed type, e.g. ed25519.
The public key bytes of the SSB feed, encoded in base64url without padding (RFC 7515).


The SSB DID method supports the following operations, as defined in DID Core.


An SSB user is considered authorized to create and update the DID document for the SSB DID derived from their SSB feed ID (public key).

Authorization to perform Read operations is up to implementations, instance configurations and network policies. An SSB user may run a resolver on their device for their own use. On a public SSB network, an SSB DID resolver may be configured to answer requests from arbitrary peers.

Create (Register)

A SSB user creates a DID by publishing an initial DID document update message to their SSB feed. Publishing a DID document update message is described in Update (Replace).

Read (Resolve)

Resolution implements the following interface defined in DID Core:

resolve(did, resolutionOptions) →
   « didResolutionMetadata, didDocument, didDocumentMetadata »

resolveRepresentation(did, resolutionOptions) →
   « didResolutionMetadata, didDocumentStream, didDocumentMetadata »

Resolution is performed as follows, generalizing for both resolve and resolveRepresentation. To return an error, set property error of didResolutionMetadata to the error code, and return the resolution result.

  1. Initialize a new DID Document metadata structure, didDocumentMetadata.
  2. Initialize a new DID Resolution metadata structure, didResolutionMetadata.
  3. Convert did to an SSB feed id, feedId. If unable to convert, return error invalidDid.
  4. If resolution option versionId is set:
    1. Parse the value of the versionId parameter as an SSB message ID, msgId. If unable to parse, return error code invalidVersionId.
    2. Query SSB for message msg with id msgId. If unable to get the message, return error ssbMessageMissing.
    3. If msg's author is not feedId, return error ssbMessageInvalidAuthor.
    4. If msg's message type is not did-document-update, return error notFound.
  5. Otherwise, if resolution option versionTime is set:
    1. Query SSB for the latest message, msg, of type did-document-update published by feedId prior to versionTime, according to the published message metadata timestamps.
  6. Otherwise, query SSB for the latest message, msg, of type did-document-update published by the identified SSB feed.
  7. If no message found, return error notFound.
  8. If resolution option versionId or versionTime is set, query SSB for the next message, nextMsg, of type did-document-update published by feedId subsequent to msg. If found nextMsg:
    1. Set property nextVersionId of didDocumentMetadata to nextMsg's SSB message ID.
    2. Set property nextUpdate of didDocumentMetadata to nextMsg's timestamp converted to a datetime string and formatted as specified in DID Core.
  9. If msg's timestamp is nonzero, set DID Document Metadata property updated to msg's timestamp converted to a datetime string and formatted as specified in DID Core.
  10. Query SSB for the earliest message, firstMsg, of type did-document-update published by feedId.
  11. Set property created of didResolutionMetadata to firstMsg's timestamp converted to a datetime string and formatted as specified in DID Core.
  12. Set contentType to the value of msg's content's contentType property if present, or else to "application/did+json".
  13. If msg's content has a property didDocumentBlob, with some value blobLink:
    1. If blobLink is a string, set blobId to blobLink.
    2. Otherwise, if blobLink is an object:
      1. Set blobId to the value of property link of blobLink.
      2. If blobLink has property type, set contentType to its value.
    3. Otherwise, return error ssbInvalidBlobLink.
    4. Fetch SSB blob blobId, and set didDocumentStream to its contents.
  14. Otherwise, if msg's content has a property didDocumentString, set didDocumentStream to its value.
  15. Otherwise, if msg's content has a property didDocument, with some value document:
    1. Transform document into a DID Document Data Model, didDocument, according to the consumption rules of the representation corresponding to contentType.
  16. Otherwise, return error ssbInvalidUpdate.
  17. If function resolveRepresentation was called:
    1. Set property contentType of didResolutionMetadata to contentType.
    2. If didDocumentStream is not set, serialize didDocument into a byte stream, didDocumentStream, using the production rules of the representation corresponding to contentType.
    3. Return the resolution result (didResolutionMetadata, didDocumentStream, didDocumentMetadata).
  18. If function resolve was called:
    1. If didDocument is not set, parse didDocumentStream into a DID Document Data Model, didDocument, using the consumption rules of the representation corresponding to contentType.
    2. Return the resolution result (didResolutionMetadata, didDocument, didDocumentMetadata).

Update (Replace)

An SSB user updates their DID document by publishing an SSB message of type did-document-update. The resulting message constitutes a DID Document update. The message MUST include exactly one of properties didDocument, didDocumentString, or didDocumentBlob.

If property didDocumentBlob is used, the value MUST be either a SSB blob ID, or an object containing a SSB blob ID as the value of property link. If the object form is used, the object SHOULD contain a size property with the size of the identified SSB blob in bytes.

The string data of didDocumentString, or the blob data of property didDocumentBlob, or the JSON data of property didDocument, MUST be the DID Document serialized in a representation conformant to DID Core. The Media Type of the representation SHOULD be included in the type property of the blob link object if present, or in the contentType property of the message content. If the Media Type is not included in the message, the representation MUST be JSON.

An SSB DID document update message, other than an initial update message, SHOULD link to the feed's previous DID document update message using property previousUpdate. The value of the previousUpdate property, if present, MUST be either an SSB message ID, or an array of SSB message IDs. If any previous DID document update messages in the feed, other than the initial update, did not use the previousUpdate property, a new DID document update message SHOULD include a link to the un-linked-to messages in the new message's previousUpdate array.

Message properties

An SSB DID Document update message uses the following content properties:

The Media Type of the representation that this DID document update uses.
The DID document as a JSON object.
The DID document as a string.
A link to an SSB blob containing the DID document
Link to the previous DID document update message(s).


Example 1: DID Document Update using JSON
  "type": "did-document-update",
  "contentType": "application/did+json",
  "didDocument": {
    "@context": "",
    "id": "did:ssb:ed25519:aaTWXmj9rNHWl3_Z_uomAkf_5WzjLhZPSmAtFrgE20o"
  "previousUpdate": "%47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=.sha256"
Example 2: DID Document Update using a string
  "type": "did-document-update",
  "contentType": "application/did+json",
  "didDocumentString": "{\"@context\":\"\",\"id\":\"did:ssb:ed25519:aaTWXmj9rNHWl3_Z_uomAkf_5WzjLhZPSmAtFrgE20o\"}",
  "previousUpdate": "%47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=.sha256"
Example 3: DID Document Update using an SSB blob, with array for previousUpdate
  "type": "did-document-update",
  "didDocumentBlob": {
    "link": "&MfxVzArCk0ydDxyUEQR1cfAsZEq6n8DMol7Lu9m/asA=.sha256",
    "type": "application/did+json",
    "size": 128
  "previousUpdate": ["%47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=.sha256"]


Deactivation is not supported.

Security Considerations

This section aims to fulfill DID Core's Security Requirements for DID method specifications.

Long-term Use

An SSB feed is identified by its public key. There is no mechanism in the SSB protocol for rotating, revoking, or recovering the key used to publish to a feed.

For more secure long-term use, an SSB key could be kept offline, and its DID Document update operations performed using an air gap.

Secret Keys

An SSB DID has a corresponding private key, which should be kept secret by the user.

Some SSB implementations store the private key unencrypted on the filesystem. Users of such systems should consider using an encrypted file system or block device.

Reliability of Timestamps

DID Core notes that verifying a signature or proof made using a verification method that has been revoked depends on using the versionId versionTime or DID parameters, and updated and nextUpdate DID document metadata properties. With the SSB DID Method, the timestamp of a DID Document Update operation is asserted by its author in the SSB message that constitutes that update operation. Verifiers may use heuristics to establish trust in a timestamp of a SSB message, such as based on the social network graph (web of trust), hash links between messages, monotonicity of timestamps within feeds, and/or other trust factors. When a SSB DID document is updated, especially to revoke a verification method, other SSB users may link to the update message from their feeds, such as with "like" messages, to contribute to establishing the temporarity of the update.

Integrity Protection and Update Authentication

SSB DID Create and Update operations are based on publishing SSB messages containing DID document updates. The Read operation is based on querying SSB for such messages. An SSB message is signed by its author, who is identified by a public key. An SSB feed is an append-only list of SSB messages published by a public key, and is identified by that public key ("feed ID"). SSB messages are identified by their content hash ("message ID"). Each SSB message links to the previous message in its feed by its message ID - except the first message in a feed, which has no previous. Implementations may evaluate SSB DID Document update messages as they are received, or as they are retrieved in queries.

Uniqueness of Assignment

An SSB DID contains a representation of a public key which is assumed to identify a SSB feed. Entropy in key generation is assumed to result in a unique keypair.

Cryptographic Protection

SSB DID document updates are published as SSB messages. SSB messages are integrity-protected and authenticated by the signature from their author's keypair. References to SSB messages, such as in versionId, are additionally integrity-protected by content hashing. The contents of a SSB message includes user-specified optionally-encrypted content, and fixed metadata fields including the previous message ID, sequence number, and asserted timestamp. Message IDs are subject to hash collision attacks. Message signatures are subject to forgery attacks.

SSB peer communication may be authenticated and encrypted using the Secret Handshake and Box Stream protocols. In SSB peer communication, peers request feeds from eachother, sending the latest sequence number of each feed they are interested in. SSB DID documents on a public SSB network should generally be considered public.

Resource Burden and Denial of Service

The following considerations apply to SSB implementations generally, and to SSB DID implementations to the extent that they depend on a full peer-to-peer SSB implementation.

A complete SSB implementation involves retrieving ("replicating") content from peers, including messages and blobs by their content hashes, and any new messages by particular authors (SSB feeds). Which feeds are replicated is based primarily on which feeds the local user "follows". Transitively followed feeds may also be replicated to a user-configurable degree ("hops" setting), as "follow" messages are typically public. Replicating SSB blobs, and/or "out-of-order" messages, is based on what each user and/or their application requests, and on query flooding between connected peers to a configurable degree ("blobs sympathy" setting). Using SSB with a nonzero blobs sympathy setting means replicating blobs on behalf of connected peers and/or transitively-connected peers, rather than only blobs requested by the local user.

Replicating SSB messages and blobs takes bandwidth, storage, and processing to decode content and verify hashes. Message replication additionally requires signature verification, and database indexing, which can block application processing. Replicating an excessively large SSB feed presents a resource burden for network participants. SSB implementations should ensure that resource use, especially storage, is within a range expected by the user.

SSB replication may be vulnerable to peers sending unboundedly large payloads in blob contents, message contents, or other RPC arguments. Implementations should protect against this by limiting the size of payloads received or of memory use during processing, in message and blob replication as well as in the RPC layer.

If a SSB DID implementation resolves SSB DIDs by replicating their corresponding SSB feeds, the above consideration about excessively large feeds apply. If a SSB DID implementation allows using SSB blobs, considerations around blob replication apply.

Lite Clients

When a full SSB implementation is not available or would be too resource-intensive, a SSB DID implementation may use a more specialized SSB implementation or a thin-client approach. For example:

Residual Risks

An SSB DID is compromised if its corresponding keypair is compromised, such as through unauthorized access to the private key in plaintext. Security of a SSB DID also depends on the underlying cryptographic primitives for message signing, hashing, and verification; this is subject to brute force attacks and advances in computing decreasing the cost of attacks. Secure key generation also relies on sufficient entropy. If an incorrect implementation or user error results in a mistaken update to a DID document, recovery may be possible by publishing a subsequent update. But if a SSB DID's SSB private key is compromised, recovery is not possible.

Message Manipulation

As SSB messages are authenticated by cryptographic signing, Message modification may occur if SSB keys and/or cryptographic functions are compromised, or through incorrect implementations or security assumptions. Message insertion within a SSB feed is the same in this regard. Message insertion in unrelated feeds should not affect the integrity of SSB DIDs, since an SSB DID is resolved only based on messages published by its corresponding SSB feed, but may cause Denial of Service. Message deletion could be performed by a peer witholding messages, for example to prevent disemmination of a DID document update revoking a compromised verification method. SSB implementations protect against message deletion by engaging in SSB replication ("gossip") with many peers, so that content has many possible paths through the network and is likely to reach peers that are interested in it.


As SSB DID document update messages are authenticated based on public key material in the DID, and SSB peer connections are authenticated based on SSB feed IDs, Man-in-the-middle attack is believed to be out of the scope of the SSB DID Method, unless using a remote resolver without peer authentication.

Confidentiality and Eavesdropping

Visibility of SSB DID update messages and SSB DID document contents depends on the SSB network. In a public SSB network, SSB messages should be assumed to be potentially public.

An SSB DID Read operation MAY trigger the SSB implementation to request from peers messages in the SSB feed corresponding to the requested SSB DID. If the versionId resolution option is used, or if the DID document update messages uses the didDocumentBlob property, the SSB implementation may additionally request content from peers by content hash. It is possible that connected peers could then infer that the user is performing a SSB DID Read operation.

Other Attacks

The SSB DID method is not known to be susceptible to Replay Attacks or amplification attacks.

Privacy Considerations

Message Visibility

SSB messages SHOULD be assumed to be public.

Remote Connections

SSB implementations commonly connect automatically to peers discovered on the SSB network. This can lead to loss of privacy through IP address disclosure. For greater privacy, users should either limit outgoing connections to trusted peers, connect via rooms, and/or use a privacy-enhancing overlay network, such as Tor.

Reference Implementations

No known implementations.