Skip to main content

DID (Decentralized Identifiers)

DIDs are globally unique identifiers that you control. No registration authority, no central database — just cryptography.

The Basics

A DID looks like this:

did:method:specific-identifier

Examples:

did:nostr:npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqkxl8lt
did:web:alice.example.com
did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK

Each DID:

  • Is globally unique
  • Resolves to a DID Document
  • Is controlled by whoever holds the private key

DID Documents

When you resolve a DID, you get a DID Document:

{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:nostr:npub1abc123...",
"authentication": [{
"id": "did:nostr:npub1abc123...#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:nostr:npub1abc123...",
"publicKeyMultibase": "z6Mk..."
}],
"service": [{
"id": "did:nostr:npub1abc123...#solid-pod",
"type": "SolidPod",
"serviceEndpoint": "https://alice.pod.example/"
}]
}

Document Sections

SectionPurpose
idThe DID itself
authenticationKeys that can authenticate as this DID
assertionMethodKeys that can issue credentials
keyAgreementKeys for encrypted communication
serviceEndpoints (pods, profiles, messaging)
controllerWho can update this document

DID Methods

Different methods use different mechanisms for creating, resolving, and updating DIDs.

Method Comparison

MethodResolutionKey RotationDependenciesBest For
did:nostrRelay queryVia new keysNostr relaysNostr users
did:webHTTP fetchUpdate fileWeb serverOrganizations
did:keyDecode DIDNot possibleNoneEphemeral

did:nostr

Uses Nostr keypairs. Simple, no infrastructure needed:

did:nostr:npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqkxl8lt

Resolution flow:

See did:nostr for details.

did:web

Uses your domain:

did:web:alice.example.com
did:web:example.com:users:alice

Resolution:

did:web:alice.example.com
→ GET https://alice.example.com/.well-known/did.json

did:web:example.com:users:alice
→ GET https://example.com/users/alice/did.json

Good for organizations and anyone with a domain. You control the domain, you control the DID.

did:key

The DID is the public key:

did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK

Resolution: Decode the key from the DID itself. No network needed.

// The DID encodes the key type and public key
// z6Mk... = Ed25519 key
// Resolution is deterministic from the DID string

Great for ephemeral identities, offline use, or when you don't need key rotation.

Resolution

DID resolution turns a DID into a DID Document:

Universal Resolver

The Universal Resolver supports many methods:

GET https://resolver.example/1.0/identifiers/did:web:alice.example.com

Returns:

{
"didDocument": { ... },
"didResolutionMetadata": {
"contentType": "application/did+ld+json"
},
"didDocumentMetadata": {
"created": "2024-01-01T00:00:00Z",
"updated": "2024-06-01T00:00:00Z"
}
}

Resolution Errors

ErrorCauseSolution
notFoundDID doesn't existCheck DID is correct
invalidDidMalformed DIDFix DID syntax
methodNotSupportedUnknown methodUse supported method
representationNotSupportedFormat not availableRequest different format

Key Management

Key Rotation

Changing keys while maintaining identity:

MethodRotation SupportMechanism
did:webYesUpdate did.json file
did:nostrPartialPublish new profile with key reference
did:keyNoKey IS the identifier

did:web Key Rotation

{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:web:alice.example.com",
"authentication": [
{
"id": "did:web:alice.example.com#key-2",
"type": "Ed25519VerificationKey2020",
"publicKeyMultibase": "z6Mk...NEW..."
}
],
"capabilityDelegation": [
{
"id": "did:web:alice.example.com#key-1",
"type": "Ed25519VerificationKey2020",
"publicKeyMultibase": "z6Mk...OLD...",
"revoked": "2024-06-01T00:00:00Z"
}
]
}

Security Best Practices

  1. Backup keys securely — Encrypted, offline storage
  2. Use hardware keys — When possible (did:web with HSM)
  3. Rotate periodically — For did:web, rotate annually
  4. Plan for recovery — Document rotation procedures

Verifiable Credentials

DIDs enable Verifiable Credentials (VCs) — digital credentials that:

  1. Are issued by any party (issuer has a DID)
  2. Are held by you (subject has a DID)
  3. Can be verified by anyone (check signatures)

Example Credential

{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": ["VerifiableCredential", "DiplomaCredential"],
"issuer": "did:web:university.edu",
"issuanceDate": "2024-06-01T00:00:00Z",
"expirationDate": "2034-06-01T00:00:00Z",
"credentialSubject": {
"id": "did:nostr:npub1...",
"degree": {
"type": "BachelorDegree",
"name": "Bachelor of Science in Computer Science"
}
},
"proof": {
"type": "Ed25519Signature2020",
"created": "2024-06-01T00:00:00Z",
"verificationMethod": "did:web:university.edu#key-1",
"proofPurpose": "assertionMethod",
"proofValue": "z..."
}
}

Credential Flow

Credential Revocation

Methods for revoking credentials:

MethodDescription
Status ListBitstring of revoked credentials
Revocation ListList of revoked credential IDs
ExpirationCredentials expire automatically

DID in SAND

DIDs integrate across the stack:

ProtocolDID RoleExample
SolidWebID can be a DIDdid:web:alice.pod.example
ActivityPubActor IDs can reference DIDsService endpoint in DID Document
NostrKeys naturally map to did:nostrdid:nostr:npub1...

Cross-Protocol Identity

Implementations

DID Methods

Tools

Quick Example

Using did:nostr:

// Your Nostr public key IS your DID
const npub = "npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqkxl8lt";
const did = `did:nostr:${npub}`;

// Resolve by querying relays for kind 0 (profile) events
async function resolveDid(did) {
const npub = did.replace('did:nostr:', '');
const pubkey = nip19.decode(npub).data;

const profile = await pool.get(relays, {
kinds: [0],
authors: [pubkey]
});

return buildDidDocument(did, profile);
}

Using did:web:

async function resolveDidWeb(did) {
// did:web:alice.example.com → https://alice.example.com/.well-known/did.json
const domain = did.replace('did:web:', '');
const url = `https://${domain}/.well-known/did.json`;

const response = await fetch(url);
return response.json();
}

Specifications

SpecDescription
DID CoreW3C Recommendation
DID ResolutionHow to resolve DIDs
Verifiable CredentialsCredential format
did:webWeb-based method
did:keyKey-based method

Learn More