In this chapter: We explore Decentralized Identifiers (DIDs), the W3C standard that provides globally unique, user-controlled identifiers. You'll learn DID syntax, methods, document structure, resolution, and how DIDs enable self-sovereign identity.
2.1 What Are Decentralized Identifiers?
At the heart of self-sovereign identity lies a deceptively simple innovation: a new type of identifier that you create and control yourself, without permission from any central authority. These are called Decentralized Identifiers, or DIDs.
Traditional identifiers—email addresses, usernames, social security numbers—are all issued and controlled by someone else. Your email address belongs to Gmail or Outlook. Your username is subject to the platform's terms of service. Your SSN is assigned and managed by the government. You're merely the subject of these identifiers, not their owner.
DIDs flip this model completely. When you create a DID:
- You don't need permission from anyone
- No central registry is required
- You control it for as long as you want
- No one can take it away from you
- It works across any platform or service
- It's cryptographically verifiable
A DID is to traditional identifiers what Bitcoin is to traditional currency: a way to have ownership and control without depending on a central authority. Just as you can create a Bitcoin address yourself and hold the private keys, you can create a DID and hold the cryptographic keys that prove it's yours.
2.2 W3C DID Specification
The World Wide Web Consortium (W3C)—the standards body that maintains the web's core technologies—published the Decentralized Identifiers specification as an official standard in July 2022. This was a landmark moment: DIDs became as official and standardized as URLs, HTML, and other web technologies.
2.2.1 DID Syntax
A DID follows a simple, standardized format:
did:method:method-specific-identifier
Let's break this down:
- did: The URI scheme, always lowercase "did"
- method: The DID method name (ethr, key, web, ion, sov, etc.)
- method-specific-identifier: An identifier unique to the method
Examples of real DIDs:
did:ethr:0x3b0BC51Ab9De1e5B7B6E34E5b960285805C41736
did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH
did:web:example.com
did:ion:EiClkZMDxPKqC9c-umQfTkR8vvZ9JPhl_xLDI9Nfk38w5w
did:sov:WRfXPg8dantKVubE3HX8pw
2.2.2 DID Methods
Different DID methods store and resolve DID documents in different ways. Each method has trade-offs regarding decentralization, cost, performance, and features. Here are the most important methods:
| Method | Full Name | Storage | Best For |
|---|---|---|---|
did:ethr |
Ethereum DID | Ethereum blockchain | Ethereum ecosystem integration |
did:key |
Key DID | No storage (derived from key) | Simple, offline use cases |
did:web |
Web DID | Web server | Organizations with existing domains |
did:ion |
ION (Bitcoin) | Bitcoin blockchain | High security, Bitcoin users |
did:sov |
Sovrin | Sovrin ledger | Enterprise SSI deployments |
did:peer |
Peer DID | Peer-to-peer | Private, pairwise relationships |
did:ethr (Ethereum): Stores DID documents on Ethereum or Ethereum-compatible blockchains. Widely adopted in crypto/DeFi. Gas fees apply for updates. Fully decentralized and censorship-resistant.
did:key: The simplest method. The DID is derived directly from a cryptographic public key. No blockchain or storage needed. Perfect for simple peer-to-peer use cases. Limitation: can't update or rotate keys.
did:web: Uses existing web infrastructure. The DID document is hosted at a well-known URL on your domain. Easy to deploy, leverages DNS and HTTPS. Trade-off: relies on centralized web infrastructure.
did:ion: Built on Bitcoin using the Sidetree protocol. Offers Bitcoin's security with efficient, scalable operations. No cryptocurrency required to use it. Good balance of decentralization and usability.
did:sov: The Sovrin Network, one of the earliest SSI implementations. Permissioned ledger operated by trusted stewards. Strong governance model. Popular in enterprise deployments.
did:peer: For private, peer-to-peer relationships. Two parties exchange DIDs directly without any public registration. Perfect for private messaging, confidential business relationships, etc.
2.3 DID Documents
A DID by itself is just a string—an identifier. The real power comes from what it points to: a DID Document. This is a JSON-LD document that contains public keys, authentication methods, service endpoints, and other metadata about the DID.
2.3.1 Anatomy of a DID Document
Here's a complete example of a DID document:
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1"
],
"id": "did:example:123456789abcdefghi",
"authentication": [
{
"id": "did:example:123456789abcdefghi#keys-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:example:123456789abcdefghi",
"publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}
],
"assertionMethod": [
"did:example:123456789abcdefghi#keys-1"
],
"keyAgreement": [
{
"id": "did:example:123456789abcdefghi#keys-2",
"type": "X25519KeyAgreementKey2020",
"controller": "did:example:123456789abcdefghi",
"publicKeyMultibase": "z9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE"
}
],
"service": [
{
"id": "did:example:123456789abcdefghi#messaging",
"type": "MessagingService",
"serviceEndpoint": "https://example.com/messaging"
},
{
"id": "did:example:123456789abcdefghi#credentials",
"type": "CredentialRepositoryService",
"serviceEndpoint": "https://credentials.example.com"
}
]
}
2.3.2 Core Components
@context: Defines the JSON-LD context, specifying what vocabularies and standards this document uses. Required for interoperability.
id: The DID this document describes. Must match the DID being resolved.
authentication: Public keys or methods used to authenticate as the DID subject. When you prove you control a DID, you typically sign something with a key listed here.
assertionMethod: Keys used for making claims or issuing credentials. If you issue a verifiable credential using this DID, you'd sign it with an assertion method key.
keyAgreement: Keys for encrypted communication. When someone wants to send you an encrypted message, they use your key agreement key.
service: Endpoints for services related to this DID. Could be messaging services, credential repositories, social media profiles, etc.
Additional optional properties include capabilityInvocation (for invoking capabilities), capabilityDelegation (for delegating capabilities to others), and controller (who controls this DID).
2.4 Cryptographic Keys in DIDs
Cryptographic keys are fundamental to DIDs. They prove ownership, enable authentication, sign credentials, and encrypt communications. Understanding key types and their uses is crucial.
2.4.1 Common Key Types
Ed25519: Fast, secure signature algorithm. Most common choice for DIDs. Small key and signature sizes. Widely supported. Good default choice.
secp256k1: The same curve used by Bitcoin and Ethereum. Choose this if integrating with crypto wallets and blockchain systems. Allows using existing Ethereum keys as DIDs.
RSA: Traditional public-key cryptography. Larger keys but widely supported in legacy systems. Good for compatibility with existing infrastructure.
X25519: Designed for key agreement (Diffie-Hellman). Perfect for encrypted communication. Often paired with Ed25519 (same elliptic curve, different purposes).
2.4.2 Key Purposes
Different keys serve different purposes in DID documents:
| Purpose | Use Case | Example |
|---|---|---|
| Authentication | Prove you control the DID | Logging into a website with your DID |
| Assertion Method | Sign claims and credentials | University issuing your degree credential |
| Key Agreement | Encrypted communication | Receiving encrypted messages |
| Capability Invocation | Invoke authorized capabilities | Executing smart contract functions |
| Capability Delegation | Delegate authority to others | Allowing assistant to act on your behalf |
2.4.3 Key Management and Rotation
One of DIDs' most powerful features is the ability to rotate keys without changing the identifier. If your private key is compromised, you can update your DID document with a new key. The DID stays the same, but the old compromised key is removed.
This is impossible with traditional identifiers. If your email password is compromised, you can change it, but if the email address itself is burned, you need a new address. DIDs separate the identifier from the cryptographic material, enabling safer key management.
Regularly rotate your keys even if not compromised. Like changing passwords periodically, key rotation limits the damage if keys are ever stolen. The frequency depends on security requirements: every 90 days for high-security applications, yearly for personal use.
2.5 DID Resolution
Creating a DID and a DID document is only half the picture. The other half is resolution—how does someone take a DID string and retrieve the associated DID document?
2.5.1 The Resolution Process
When you encounter a DID like did:ethr:0x123..., resolution happens in these steps:
- Parse the DID: Extract the method (ethr) and method-specific identifier
- Identify the resolver: Use the appropriate DID method resolver for that method
- Retrieve the document: The resolver fetches the DID document from wherever it's stored (blockchain, web server, etc.)
- Validate: Ensure the document is properly formatted and hasn't been tampered with
- Return: Provide the DID document to the application
2.5.2 Universal Resolver
Because different DID methods resolve differently, the Decentralized Identity Foundation created the Universal Resolver—a service that can resolve any DID method. You send it any DID, and it routes to the appropriate method-specific resolver.
This is crucial for interoperability. Applications don't need to implement every DID method; they just integrate with the Universal Resolver.
// Resolving a DID using the Universal Resolver
const response = await fetch(
'https://resolver.identity.foundation/1.0/identifiers/did:ethr:0x123...'
);
const didDocument = await response.json();
2.6 Creating and Managing DIDs
Let's walk through practical examples of creating and managing DIDs using different methods.
2.6.1 Creating a did:key
The simplest method—create a DID from a cryptographic key pair:
import { generateKeyPair } from '@noble/ed25519';
import { base58btc } from 'multiformats/bases/base58';
// Generate Ed25519 key pair
const privateKey = generateKeyPair();
const publicKey = privateKey.slice(32); // Ed25519 public key
// Encode as multibase
const publicKeyMultibase = 'z' + base58btc.encode(publicKey);
// DID is just the key
const did = `did:key:${publicKeyMultibase}`;
console.log(did);
// did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH
The DID document is deterministically generated from the key. No storage needed!
2.6.2 Creating a did:ethr
For Ethereum-based DIDs:
import { Wallet } from 'ethers';
import { EthrDID } from 'ethr-did';
// Create Ethereum wallet
const wallet = Wallet.createRandom();
// Create DID (Ethereum address)
const did = `did:ethr:${wallet.address}`;
// Create DID instance
const ethrDid = new EthrDID({
identifier: wallet.address,
privateKey: wallet.privateKey
});
console.log(did);
// did:ethr:0x3b0BC51Ab9De1e5B7B6E34E5b960285805C41736
2.6.3 Creating a did:web
For web-based DIDs, you host the DID document on your domain:
- Create a DID document (like the example in section 2.3.1)
- Host it at
https://yourdomain.com/.well-known/did.json - Your DID is
did:web:yourdomain.com
For a subdomain or path:
did:web:example.com:users:alice→https://example.com/users/alice/did.jsondid:web:id.example.com→https://id.example.com/.well-known/did.json
2.7 Advanced DID Concepts
2.7.1 DID Controllers
A DID can be controlled by a different DID. This enables powerful delegation and guardian scenarios:
{
"id": "did:example:child123",
"controller": "did:example:parent456",
"authentication": ["did:example:parent456#key-1"]
}
Here, the child's DID is controlled by the parent's DID. The parent can authenticate as the child. Useful for:
- Parental control over children's identities
- Corporate control over employee identities
- Guardian access to incapacitated persons' identities
- Multi-signature control (multiple controllers)
2.7.2 Pairwise DIDs
For privacy, create a unique DID for each relationship. Instead of one DID for everything, generate a new DID for each person or organization you interact with. They can't correlate your activities across different contexts.
Example: You have DID-A for your bank, DID-B for your employer, DID-C for healthcare provider. Even if they collude, they can't link these DIDs to the same person.
2.7.3 DID Deactivation
DIDs can be deactivated when no longer needed. The DID document includes a deactivated flag. After deactivation, the DID cannot be reactivated (preventing resurrection attacks).
{
"id": "did:example:123",
"deactivated": true
}
Chapter Summary
- Decentralized Identifiers (DIDs) are globally unique identifiers you create and control without central authority, specified by W3C as an official web standard
- DID syntax:
did:method:method-specific-idwith various methods (ethr, key, web, ion, sov) offering different trade-offs - DID documents are JSON-LD files containing public keys, authentication methods, and service endpoints associated with a DID
- Cryptographic keys enable authentication, signing, encryption, and capability management with support for key rotation without changing the DID
- DID resolution retrieves DID documents from various storage systems (blockchains, web servers, peer-to-peer) using method-specific resolvers
- Advanced features include multiple controllers, pairwise DIDs for privacy, and deactivation mechanisms
- DIDs form the foundation of self-sovereign identity, enabling user-controlled, portable, and interoperable digital identities