Why DIDs?
This post breaks down DIDs, their structure, key methods used at Storacha, and how they enable secure, self-sovereign identity.
At Storacha, we use DIDs to identify just about everything. You may have seen them: every Space is identified by something like did:key:z6MkksCTrQAGDkFZp34CLcnzoqbddAVExKj5GHmHSCuRNuaX, and your own account is identified as something like did:mailto:example.com:jsmith. But what exactly is a DID, and why does it matter? Unlike traditional identifiers tied to centralized platforms, DIDs let their controllers—the humans who are using and defining them—assert a verifiable identity without relying on some trusted third party to vouch for them. Neat trick, right? How's that possible? Read on, and we'll explore just how DIDs can be so powerful, and how Storacha uses them to keep authentication and identity completely decentralized.
Wait. What is a DID, actually?
A Decentralized Identifier (DID) is a string identifier which identifies some entity, called the DID subject. In other words, a DID is a name for its subject. It’s a kind of URI. It has some important properties, though, that make it a particularly useful kind of URI:
- Universal: A DID isn’t just a primary key into a database table — it can be understood in a global context. We already have a great example of this in URIs (Universal Resource Identifiers) generally:
http://example.com/exists in a universal namespace. - Verifiable: Not only does the name exist and refer to something, but if that something is us, we can prove it. If you act on behalf of
http://example.com/, there isn’t really a way to prove that—at least not a standardized one. - Decentralized: That’s always a hand-wavy word, so let’s be clear about what it means here: “the design enables the controller of a DID to prove control over it without requiring permission from any other party.” (spec) Notably, that means no OAuth flows. Your identity is your identity; once someone knows how the subject is supposed to verify that they are in fact the subject, you can identify yourself to them without anyone else being involved. That makes them great to use with UCAN.
- Extensible: There are a few ways in which the DID spec can be extended, but the main one is by DID methods. A DID guarantees a certain interface that lets it have the properties above, but there are several implementations of that interface. To work with a DID, you need to be aware of how its method works (or have a library that is), but once you are, you can use that common interface to verify and operate on it.
Basic Anatomy
A DID looks like this: (spec)

The Scheme is always did, identifying the URI as a DID. The DID Method here is example, specifying that this DID uses a DID Method called example. (That name is meant to universally identify the method, so it should be registered so everyone agrees on what it means.) After the second colon is a string which only has to make sense to that specific method.
At Storacha, we use three DID methods extensively. The first is key (spec). It looks like:
Method
╭╵╮
did:key:z6MkksCTrQAGDkFZp34CLcnzoqbddAVExKj5GHmHSCuRNuaX
╰╷╯ ╰──────────────────────╷───────────────────────╯
Scheme Multiformat Public KeyThe subject of this DID is the entity which holds the private key — which ideally is the entity which generated the private key, since the best security involves never transmitting it. The subject can verify that they are the subject by signing something with the private key, proving they hold it.
We use did:key:s to identify Spaces (which typically UCAN-delegate their authority and then throw away their own private key, so no one can “be” the Space itself again) and Agents (which are created when you “log in” to Storacha, receive UCAN delegations to act on other subjects’ behalves, and disappear when you “log out”). They’re great for ephemeral subjects, which can be pretty useful in UCAN contexts, where authority can be delegated.
The second is web (spec). It looks like:
Method Path (opt.)
╭╵╮ ╭───╵────╮
did:web:example.com:user:alice
╰╷╯ ╰────╷────╯
Scheme Domain NameThe subject of this DID is the controller of the website it points to, as interpreted as an HTTP URL (in this case, http://example.com/user/alice). The subject can verify that they are the subject by placing a public key on that website and signing something with the private key.
We use did:web:s to identify the services Storacha runs. They’re great for stable, server-side entities with well-known URLs.
The third is mailto (spec), and this one’s a little tricky because we made it up, and it stretches the way DIDs work a bit.
Method Local Part
╭──╵──╮ ╭──╵──╮
did:mailto:example.com:jsmith
╰╷╯ ╰────╷────╯
Scheme Domain NameThe subject of this DID is the controller of the email inbox it points to (in this case, jsmith@example.com). According to the spec, the subject can verify that they are the subject by sending an email from that address in a particular format, but we currently never use that mechanism in Storacha. Instead, we send something to that address prompting the recipient to open a URL which effectively sends a UCAN back to the authenticating service. This works for now, but it’s messy. More on this later.
Okay, I’ve got a DID. Now what?
There’s essentially one main thing you can do (directly) with a DID: resolve it. To resolve a DID is to access the DID document associated with it. A DID document tells you everything you need to know about a DID to do other things with it, such as verify that someone is its subject. The way to resolve a DID is specified by the DID method. In other words, any DIDs can be resolved to a DID document (interface), but the method tells you what you have to do to actually do that (implementation).
The resolution of did:key:s is the simplest, because it’s defined in the spec as a transformation from the DID itself—which, remember, contains a literal public key—to a DID document which says that that public key can be used to verify the subject of the DID. To resolve a did:web:, you transform the identifier in the DID into an HTTP URL which should give you a DID document. To resolve a did:mailto: you first need to get an email from that address with a DKIM-Signature: header, which should contain the information to construct it. If your application doesn’t receive an email from the address, then…well, you kind of can’t resolve it. Storacha, notably, doesn’t receive such an email, and just avoids any need for the DID document.
Once you’ve got a DID document, you’ve got all sorts of options (potentially) available, and you no longer have to care what the DID method was that got you there.
Verification Methods
If the DID document provides verification methods, they describe ways that you can verify the DID subject, be it for authenticating someone as the DID subject, verifying that they’ve signed some document, or other cryptographic needs. There are several keys in the DID document which can contain verification methods, depending on what they’re meant to be used for. We don’t need to get into specifics here — it’s enough to know that this is where we can find a public key for a DID.
Services
There’s another major thing that the DID document can tell you: what services are associated with the subject. Not every subject has a service: an Agent, for instance, doesn’t host any services. But did:web:indexer.storacha.network sure does! Today, our code often depends on pairs of environment variables which specify the DID and the URL of each service that code needs to talk to. But the DID itself can tell us what the URL is! We just need to look in the DID document. (Which, incidentally, we don’t actually currently publish.)
So, could we use other DIDs?
Sure could! Currently, we tend to expect that Spaces are did:key:s and Accounts are did:mailto:s, so using other kinds of DIDs would require a bit of work to generalize them. But once we do, we can support anything we can provide a DID method implementation for.
But we have to keep in mind how this works: we can accept delegations issued by any DID, and we can issue delegations to any DID, but we can’t issue delegations on behalf of any DID. We can only issue delegations on behalf of “ourselves” — that is, with private keys we have access to.
So DIDs are…
…pretty dang powerful for self-sovereign identity! At Storacha, we currently use did:key:, did:web:, and did:mailto:, but because DID methods can often be used interchangeably, there’s a great big world of possibilities for our future. Could a Space be a did:web: instead of a did:key:? Could an Account be identified by a did:ethr: Ethereum address? Yeah! Maybe! Not without adding a bit of support to Storacha first, but there are hundreds of potential use cases to explore, and we’re constantly curious about what could be valuable for our users. Using DIDs as a flexible base, we’re excited to see what new kinds of open, interoperable, and trustless systems we can help our customers build.