DEV Community

Cover image for So...What are these Decentralized Identifiers?
João Augusto Perin
João Augusto Perin

Posted on

So...What are these Decentralized Identifiers?

Recently, I took notice of a "new" type of identifier that is being more and more used through many systems nowadays, but, although it comes with a lot of design decisions that may sound revolutionary at first, we need to be careful before thinking anything more of it.

Let's take a look, today, at the Decentralized Identifiers.


What are Decentralized Identifiers (DIDs)

Decentralized Identifiers, or DIDs, are a new class of globally unique identifiers that are cryptographically verifiable, self‑sovereign, and resolvable without a central authority. Unlike typical identifiers (email, username, social media handle), which are issued and controlled by a central service provider, DIDs are defined in a way that lets the identity controller fully own and control the identifier.

A DID has a canonical form:

did:<method>:<method‑specific‑id>
Enter fullscreen mode Exit fullscreen mode

For example: did:example:123456789abcdefghi

  • example is the DID method (implementation rules, e.g. did:ion, did:key, did:sov).
  • The method‑specific‑id is some unique string or public key fingerprint.
  • The DID itself can resolve to a DID document—a JSON object that holds public keys, service endpoints, authentication methods, and more.

Because DIDs are not tied to any central registry, the holder can generate new DIDs freely, rotate keys, and choose where the DID document lives (on a DID network, IPFS, HTTPS, etc.).


🧠 How DIDs Work (Step by Step)

  1. Creation
    You generate a key pair (e.g. ed25519). That public key fingerprint becomes your method‑specific‑id. You choose a DID method, e.g. did:key, which encodes the public key directly, or did:ion, which anchors state updates on blockchain-like infrastructure.

  2. DID Document
    The DID resolves to a DID Document that typically includes:

    • public key(s) for authentication or encryption,
    • authentication and assertion methods,
    • service endpoints (e.g. service: messaging, service: vc-storage).
  3. Resolution & Verification
    Clients use a DID resolver for the specific method. They fetch (or verify) the DID document, check cryptographic bindings, and confirm that the public key matches. That guarantees: “this DID corresponds to someone who holds the private key.”

  4. Authentication & Verifiable Credentials
    Using DID-based authentication (e.g. using JSON‑LD proof or JWT with DID DID‑Auth), the controller proves ownership by signing a challenge. Receiving systems verify signatures based on the DID document.

For Verifiable Credentials, an issuer signs a credential (e.g. a diploma, attestation) using their DID key. The holder stores the credential and later presents proofs, and verifiers check both signature and revocation status using DID resolution or credential registry.

  1. Key Rotation & DID Updates
    Some DID methods (like did:ion, did:sov) support versioned DID documents: you can rotate keys, add or remove public keys. The DID still resolves to the latest document, with history anchored immutably (e.g. on multi-party anchoring networks).

  2. Decentralization & Trust Model

    • There's no single root authority leasing identifiers.
    • Control comes from cryptographic proofs, not trust in a central issuer.
    • The integrity of DID history depends on the method (blockchain‑anchored, distributed ledger, registry, etc.).

🛠️ Use Cases & Practical Examples

1. Authentication without passwords

A user generates did:key on their device. When signing into a service, they sign a challenge using their private key. The service resolves the DID, fetches the public key, verifies the signature—and logs the user in.

No usernames, no passwords, no provider‑centralized identities.

2. Verifiable Credentials ecosystem

Universities, employers, and governments can issue credentials (degree certificates, licenses, KYC attestations) signed with their DIDs. Holders store them in encrypted wallets, share only necessary proofs with third parties (e.g. “I have a degree, not which major”). The verifier resolves issuer DID, verifies signature, optionally checks revocation.

Privacy-preserving, portable, and user‑controlled.

3. Decentralized Web of Trust & social networks

In peer‑to‑peer networks, each node publishes their DID document with service endpoints and verification keys. Peers can exchange signed messages or verify membership without relying on central servers.

4. IoT device identity

IoT devices can hold did:ion‑style identifiers. When a sensor sends data to a network, it signs readings—automated systems verify the sender’s DID, its key authority, and optionally check that it was registered at device minting time.

5. Supply chain provenance

Brands allocate DIDs to shipments or batches. Each actor writes attested events (manufacturing, shipping, storage) tied to those DIDs. Verifiers can query events linked to the item’s DID history, confirming origin and transit chain.


⚙️ Implementation Patterns & Tech Stack

  • DID methods

    • did:key: simplest, public key encoded as DID, no blockchain or registry.
    • did:ion (built on Sidetree): supports updates, anchored on public ledger.
    • did:sov: part of Hyperledger Indy, often used in enterprise credential networks.
  • DID Document structure
    Standard JSON‑LD structure with keys, authentication, service endpoints.

    Resolution may return historical versions or meta‑information depending on the method.

  • Libraries & tooling
    Tools like did‑kit, indy‑sdk, veramo, trinsic, or ssi‑web implement DID management, issuance, storage, resolution, and credential flows in languages like TypeScript, Rust, and Go.

  • Security & key management
    Local key stores, hardware security modules (HSMs), or secure enclaves hold private keys. Seed phrases or recovery methods are critical for user control.

  • Interoperability considerations
    Credential formats (W3C VC), proof standards (JSON‑LD, BBS+, JWT), DID resolver compatibility—all matter for systems that interact across networks.


🧾 Pros and Cons

Pros

  • Self‑sovereign identity: users own their identifiers and data.
  • Interoperable standard: W3C‑recognized, cross‑platform.
  • Verifiable and portable: cryptographic assurance without central providers.
  • Privacy‑preserving: selective disclosure, zero‑knowledge proof support.

Cons

  • Method fragmentation: many DID methods exist, and not all are interoperable.
  • Infrastructure complexity: resolution, key rotation, revocation require external networks or registries.
  • Usability challenges: key management, recovery, wallet compatibility—not as seamless as centralized login flows.
  • Trust bootstrapping: verifying issuer trust (e.g. a university DID) may still rely on registries or off‑chain trust lists.

💻 Pseudo-code

Here we'll have some basic examples of usage, and some diagrams to help understand the usage of these DIDs:

DID Authentication Flow

DID Authentication Flow

// Verifier generates a random challenge
const challenge = generateRandomString();
sendToClient(challenge);

// Client signs the challenge with their private key
const signature = sign(challenge, privateKey);

// Verifier resolves the DID document
const didDocument = resolveDID(clientDID);
const publicKey = extractPublicKey(didDocument);

// Verifier checks the signature
const isValid = verifySignature(challenge, signature, publicKey);

if isValid grantAccess();
Enter fullscreen mode Exit fullscreen mode

Creating a DID Key

// Generate a keypair
const keypair = generateKeyPair(algorithm = "ed25519")

// Encode public key in multibase + multicodec format
const encodedKey = encodeMultibase(keypair.publicKey)

// Construct the DID
const did = "did:key:" + encodedKey

// Create a DID document
const didDocument = {
  "@context": "https://www.w3.org/ns/did/v1",
  "id": did,
  "publicKey": [{
    "id": did + "#key-1",
    "type": "Ed25519VerificationKey2018",
    "controller": did,
    "publicKeyMultibase": encodedKey
  }],
  "authentication": [did + "#key-1"]
}
Enter fullscreen mode Exit fullscreen mode

Resolving a DID

// Generic DID resolver
function resolveDID(did) {
    const method = extractMethodFrom(did) // e.g. "key", "ion", "web"
    const resolver = getResolverForMethod(method)
    return resolver.resolve(did)
}
Enter fullscreen mode Exit fullscreen mode

Verifiable Credential Issuance & Verification

Verifiable Credential Issuance & Verification

// Verifier checks integrity and authenticity of a credential
const credential = receiveCredential();

// 1. Resolve issuer DID to get public key
const issuerDID = credential["issuer"];
const issuerDoc = resolveDID(issuerDID);
const issuerKey = extractPublicKey(issuerDoc);

// 2. Verify the signature
const isValid = verifySignature(credential, credential["proof"], issuerKey);

if isValid acceptCredential();
else rejectCredential();
Enter fullscreen mode Exit fullscreen mode

🧠 Tips for Real Implementations

  • Use Well-known libraries like didkit, veramo, or @identity.com/credentials for implementation.
  • Prefer did:key for ephemeral, short-lived identities.
  • Use did:ion or did:web for long-lived, public identities.
  • Use credential formats like JSON-LD for maximum interoperability.
  • Consider key rotation and revocation strategies early.

✅ Takeaways

DIDs are a thoughtful re‑imagining of digital identity—rooted in cryptographic verification and user control, decoupled from centralized authorities. They enable flows like password‑less authentication, verifiable credentials, and IoT provenance that are portable and privacy‑aware.

Yet, despite their potential, real‑world adoption still faces friction: fragmentation of methods, key recovery UX, and ecosystem trust models. As with variance and authentication systems you've written about, it's essential to look under the hood—understand cryptographic anchors, resolution design, and architectural trade‑offs—before embracing the hype.

Top comments (0)