DIDs are a Dead End

This article is a summary of my learnings from working with the Decentralized Identifiers standard, first at the uPort project where we designed the first DID method on Ethereum and contributed to the DID spec itself, and later as CTO and co-founder of Ceramic Network where we designed and implemented numerus DID methods (e.g. did:3, did:pkh, did:nft). I've shared this perspective in various private conversations when people has asked for my thoughts on DID, sometimes more directly "which DID method(s) should I support". Hopefully this can be insightful for a wider audience as well.

What are DIDs?

According to the DID specification:

Decentralized identifiers (DIDs) are a new type of identifier that enables verifiable, decentralized digital identity. ... In contrast to typical, federated identifiers, DIDs have been designed so that they may be decoupled from centralized registries, identity providers, and certificate authorities. ... DIDs are URIs that associate a DID subject with a DID document allowing trustable interactions associated with that subject.

To simplify, a DID is a URL (e.g. did:pkh:eip155:1:0xb9c5714089478a...) that can be resolved into a DID document, which essentially contains a list of public keys associated with this given identifier. However, the DID specification conveniently leaves out the most critical part of this process, namely the resolution process, i.e. the protocol for how you go from the DID URI to the DID document. Instead DIDs are positioned as an interoperability standard where implementers can define their own resolution protocol. This is a historical artifact due to the original authors couldn't agree on which blockchain to use, or even if a blockchain was to be used in the first place.

DIDs are Meaningless without Blockchains

While the DID spec tries to remain politically neutral, defining Verifiable Data Registries much broader than just blockchains, I personally tend to believe that the "D" in DIDs should mean something. To quickly define decentralized, the core properties it must fulfill is censorship resistance and trustless verification. Specifically for DIDs we care about being able to trustlessly verify the order in which keys where added or removed (rotated / revoked) to the DID document. This problem can only be solved by using blockchains, that is unless you want to introduce trust somwhere in your system (this is what did:web and did:plc does). For more detail on why this is the case, have a look at my talk at EthCC from 2021. The most scalable way to do key rotation/revocation trustlessly is to just anchor batches of off-chain data on a blockchain (which is the approach we took with Ceramic Network), however it's not optimal since it's vulnerable to the Late publishing attack described see Sidetree spec. Only by publishing key rotation/revocations directly on-chain do you get guaranteed finality of your operations.

The Failed Promise of Interoperability

While leaving the resolution protocol up to implementers might have been a good political choice to get a huge amount of initial alignment around the DID specification, it's ultimately the choice which renders DIDs mostly useless. Let's consider for a moment only true DID methods, e.g. the ones that rely on blockchains. Doesn't the DID standard at least enable interoperability between them? And yes, it does make interoperability of interpretation easier since the DID URI and the DID document have to follow the same format. However, when it comes to actually resolving multiple DID methods we run in to problems.
Suppose your application want's to trustlessly resolve DIDs for DIDs on Bitcoin, Ethereum, and Solana. Now your app needs to, in the best case, run light clients of these blockchains. Likely though your users would need to run full nodes to do it fully trustlessly since many DID methods are not designed with light clients in mind. This is obviously a non-starter for most real world applications. Instead most apps that use DIDs end up relying on a centralized resolver, like the Universal Resolver for example. I write more about this in my Generative DID Maximalism article.
So if you can't actually use DIDs in a trustless setting, the shared format actually have little value. You are better of not using DIDs at all.

Choose One Public Key Infrastructure

Now you might be thinking: are we not throwing out the baby with the bath water? The reason we care about DIDs is the broader decentralized identity functionality we get from it. But what are actually those things? Here's a few examples:

  • Stable Identifiers - a string that represents an identity over time, even as keys are changed
  • Verifiable Credentials - signed claims about an identity, ideally stored off-chain in your wallet
  • Credential Revocation - the ability of the issuer or holder to revoke a verifiable credential
  • Authentication - a protocol for proving to a third party that you are the controller of the given identity
  • Selective Disclosure - extending the authentication protocol with the ability to reveal certain aspects of your identity, e.g. through partially revealing a verifiable credential

We don't actually need DIDs to achieve these things. What we need to do is to pick one public key infrastructure, e.g. one blockchain. In my experience, Ethereum is actually ideal because makes it easy to design light client friendly protocols on top. Let's go through a few of the examples above applied on Ethereum.

Stable identifiers

There are two different approaches to a stable identity on Ethereum: (1) a multisig, here the stable identifier is the address of the multisig, (2) an ENS name, e.g. jthor.eth, this name can be updated to point to different ethereum addresses.

Verifiable Credentials

A great example of a system for verifiable credentials from the Ethereum ecosystem is ZuPass. It doesn't directly use a blockchain, but uses advanced cryptography (i.e. zero-knowledge proofs) that allows users to selective disclose properties from within the credentials awarded to the users.

Credential Revocation

If you need a way to revoke credentials an on-chain is ideal. Here we would simply notarize a fingerprint of the credential in an registry. When a third party is verifying the credential they would simply look up the registry to check if the credential is still valid.

Authentication & Selective Disclosure

There are two main protocols that are used in the Ethereum ecosystem. Sign-in With Ethereum, which also happens to be compatible with OpenID Connect, but besides authentication is rather limited, and the auth protocol used by ZuPass. The latter is interesting because it affords the user the ability to disclose only the necessary information, e.g. that they have a ticket to an event, without disclosing their identity or other information.