This specification defines a standardized, interoperable mechanism for recovering control of [=Decentralized Identifiers=] (DIDs) when private keys are lost or compromised. It introduces three complementary recovery types — Social ZKP Recovery, Deterministic Seedling Inheritance, and MPC-based Mediated Recovery — each addressing different trust models and user personas. The specification includes cryptographic hardening through mathematically correct Verifiable Secret Sharing (Feldman VSS over a proper prime-order group), Verifiable Delay Functions, Proactive Secret Refreshment, and comprehensive security considerations with a formal JSON-LD context for machine interoperability.
This document is a draft specification being developed by the W3C Credentials Community Group. Comments and contributions are welcome via the GitHub repository.
The [=Decentralized Identifier=] (DID) architecture provides the foundation for self-sovereign identity but deliberately omits key recovery mechanisms, leaving implementers to develop ad-hoc, non-interoperable solutions. This gap represents a critical barrier to mass adoption, as users face permanent loss of identity or vendor lock-in when keys are lost. The DID Key Recovery Extension (DID-KR) addresses this gap by defining standardized recovery methods that can be published in DID Documents, discovered by resolvers, and executed through interoperable protocols.
The specification embraces a three-way solution recognizing that no single recovery model suits all use cases:
This specification extends DID Core by defining:
recovery verification relationship.Some terminology used throughout this document is defined in the Terminology section of the [[[DID]]] specification. This section defines additional terms used throughout this specification.
recovery
verification relationship and define the protocol, parameters, and participants
necessary to perform recovery operations. These methods MUST NOT be used for
general authentication or assertion purposes.
The DID-KR architecture introduces a new verification relationship recovery in the DID Document. This relationship contains one or more [=recovery methods=] that define how a DID can be recovered.
Recovery methods are discovered through standard DID resolution. A resolver or wallet implementing DID-KR:
@context including the DID-KR context.recovery verification relationship.type.Type URI: RecoveryMethodZKPSocial
The Social ZKP Recovery mechanism enables recovery through a [=threshold=] of trusted [=guardians=] without revealing secret shares to any party, including the guardians themselves. Implementations MUST use Feldman's Verifiable Secret Sharing (VSS) with zero-knowledge proofs for share verification.
s ∈ Zq (the recovery key).P(x) of degree t−1 over Zq where P(0) = s.si = P(i) mod q for each of n guardians.Cj = gaj mod p for each coefficient aj.t in the DID Document.t guardians.si consistent with commitments.Zq.s is used to generate new DID keys.
{
"id": "did:example:123#recovery-social",
"type": "RecoveryMethodZKPSocial",
"controller": "did:example:123",
"recoveryThreshold": 3,
"vssScheme": "feldman-safe-prime-256",
"vssGroupParameters": {
"p": "0x50179e4375e428b3af8fe52af1f2a50e5100b916d0d1c1bbedc304c3d35f3217",
"q": "0x280bcf21baf21459d7c7f29578f9528728805c8b6868e0ddf6e18261e9af990b",
"g": "4"
},
"vssCommitments": ["0x2a3f...", "0x7c91..."],
"recoveryGuardians": [
{
"id": "urn:hash:sha256:3a7b...c9f2",
"guardianEndpoint": "https://guardian1.example.com/recover",
"commitmentIndex": 0
}
]
}
sequenceDiagram
participant User as User (Recovering Party)
participant G1 as Guardian 1
participant G2 as Guardian 2
participant G3 as Guardian 3
User->>G1: Request recovery (nonce, commitments)
User->>G2: Request recovery (nonce, commitments)
User->>G3: Request recovery (nonce, commitments)
G1-->>User: ZKP Proof
G2-->>User: ZKP Proof
G3-->>User: ZKP Proof
User->>User: Verify ZKPs & reconstruct secret
User->>User: Generate new DID keys
Type URI: RecoveryMethodDeterministic
The Deterministic Seedling mechanism enables recovery through a master seed phrase, with optional time-locked inheritance for [=beneficiaries=] using [=Verifiable Delay Functions=] (VDFs).
{
"id": "did:example:123#recovery-seedling",
"type": "RecoveryMethodDeterministic",
"controller": "did:example:123",
"seedDerivationPath": "m/44'/0'/0'/0/0",
"derivationStandard": "bip32-ed25519",
"encryptedSeedLockbox": {
"ciphertext": "0x7b3a...f9c2",
"algorithm": "XChaCha20-Poly1305",
"iv": "0x1a2b...3c4d",
"beneficiaryPublicKey": "did:beneficiary:abc#key-1",
"beneficiaryKeyType": "x25519"
},
"deadMansSwitch": {
"type": "VDFTimeLock",
"vdfParameters": {
"difficulty": 1000000,
"estimatedWallTime": "P30D",
"referencePlatform": "intel-i9-13900k-2024",
"tolerance": 0.2,
"vdfAlgorithm": "wesolowski-2024"
},
"inactivityPeriod": "P1Y"
}
}
Type URI: RecoveryMethodMPC
The MPC-Mediated Recovery mechanism distributes key shares across multiple independent [=providers=] who perform [=threshold=] signatures without reconstructing the full key, using fROST (Flexible Round-Optimized Schnorr Threshold) signatures.
{
"id": "did:example:123#recovery-mpc",
"type": "RecoveryMethodMPC",
"controller": "did:example:123",
"mpcThreshold": 2,
"mpcTotalProviders": 3,
"mpcProtocol": "fROST-ed25519",
"mpcProviders": [
{
"id": "did:provider:one#mpc-node",
"endpoint": "https://provider1.example.com/mpc",
"authType": "vc-presentation"
}
],
"shareRotation": {
"rotationInterval": "P30D",
"currentEpoch": 42,
"lastRotationProof": "0x8a3c...f2b5",
"synchronization": {
"maxEpochSkew": 1,
"catchupProtocol": "vss-refresh-verifiable-2025",
"timeout": "PT30S",
"requiredQuorum": 2
}
}
}
When providers operate at different epochs, the recovery protocol MUST handle version skew. The [=catch-up protocol=] ensures lagging providers can synchronize:
The recovery verification relationship indicates that the associated
[=recovery methods=] are specifically authorized for recovering control of the DID.
These methods are limited to recovery operations and MUST NOT be used for general
authentication.
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3c-ccg.github.io/did-recovery/context/v1"
],
"id": "did:example:123",
"recovery": [
"did:example:123#recovery-social",
"did:example:123#recovery-seedling",
"did:example:123#recovery-mpc"
]
}
recovery relationship.controller is authorized to modify the DID Document.Feldman VSS verification requires the equation:
For this to hold consistently, exponents on both sides must reduce modulo the same value — the order of the generator g in the group. This requires:
Implementations MUST use the following parameters, or an equivalent set verifiable by the same properties:
Parameter verification MUST ensure:
Let (p, q, g) be as defined above. All scalar operations are in Zq. All commitment operations are in Zp*.
s ∈ Zq and random coefficients a1, …, at-1 ←R Zq.P(x) = s + a1x + … + at-1xt-1 over Zq.i = 1…n, share si = P(i) mod q.Cj = gaj mod p for j = 0…t-1.Participant i verifies their share by checking:
Given t shares {(i, si)}, recover s = P(0) via Lagrange interpolation in Zq:
To re-randomize shares without changing the secret ([=share refreshment=]):
R(x) = r1x + … + rt-1xt-1 over Zq with R(0) = 0.δi = R(i) mod q and refresh commitments Dj = grj mod p.sinew = (siold + δi) mod q.Cjnew = Cjold · Dj mod p.To prove knowledge of share si ∈ Zq without revealing it (Schnorr proof):
r ← Zq.R = gr mod p.c ← Zq.z = (r + c · si) mod q.gz ≡ R · (∏ Cjij mod q)c (mod p).Input: x ∈ QR(N), time parameter T
Output: y = x2T mod N, proof π
y = x2T mod N via sequential squaring.l = ⌊2T / 2⌋, compute π = xl mod N.π2(T/2) · x2T mod 2(T/2) = y mod N.Threat: A [=threshold=] of [=guardians=] collude to reconstruct the user's private key.
Mitigation: Feldman VSS with commitments ensures shares are individually verifiable. Guardians SHOULD be selected from diverse trust domains, and [=threshold=] SHOULD be ≥ 3-of-5. The use of zero-knowledge proofs prevents guardians from learning each other's shares during recovery.
Threat: An attacker compromises the dead man's switch to release inheritance keys prematurely.
Mitigation: [=Verifiable Delay Functions=] provide computational asymmetry that cannot be parallelized, making premature release computationally infeasible within the specified time window. The Wesolowski proof system enables efficient verification that the required sequential computation was performed.
Threat: MPC [=providers=] update shares independently, causing key desynchronization.
Mitigation: [=Share refreshment=] with verifiable refresh transcripts ensures consistency. The [=catch-up protocol=] handles [=epoch=] lag by providing cryptographically verifiable refresh transcripts that lagging providers can verify and apply.
Threat: Circular recovery dependencies make recovery impossible.
Mitigation: Implementations MUST validate that the dependency graph of [=recovery methods=] is acyclic at publication time, at recovery initiation, and during periodic health checks.
Threat: Weak encryption of seed lockboxes.
Mitigation: All encrypted payloads MUST use AEAD with ≥ 256-bit keys. XChaCha20-Poly1305 or AES-256-GCM are REQUIRED. The algorithm MUST be explicitly named in the DID Document.
Threat: Current cryptographic algorithms may become vulnerable over time.
Mitigation: Implementations SHOULD plan transition paths:
Recovery methods may expose social graph ([=guardian=] identities), security posture ([=threshold=] values), and activity patterns. Implementations SHOULD use hashed guardian identifiers:
{
"recoveryGuardians": [{
"id": "urn:hash:sha256:3a7b...c9f2",
"salt": "0x4d8e...f2a3",
"guardianEndpoint": "http://guardian1.onion/recover"
}]
}
Instead of full DIDs, implementations SHOULD publish salted hashes of [=guardian=] identifiers to prevent correlation across different DIDs. Guardian endpoints SHOULD use onion services or other privacy-preserving communication channels where possible.
The same recovery method across multiple DIDs could correlate them. DID controllers SHOULD use different guardian sets, salt values, and encryption keys per DID to prevent correlation across identities.
[=Beneficiaries=] SHOULD use single-use derived keys specific to each inheritance relationship, not linked to their primary identity. This prevents correlation of inheritance relationships across multiple DIDs.
| Algorithm | Usage |
|---|---|
| Ed25519 | Signatures, guardian keys |
| SHA-256 | Hashing |
| XChaCha20-Poly1305 | Seed lockbox encryption |
| AES-256-GCM | Share encryption at rest |
| BIP-32 | Key derivation |
| fROST (Ed25519) | Threshold signatures |
| Feldman VSS (p,q,g per §Cryptographic Primitives) | Verifiable secret sharing |
| Wesolowski VDF | Time-locks |
| Algorithm | Usage |
|---|---|
| secp256k1 | Blockchain compatibility |
| BLS12-381 | Pairing-based cryptography |
| Pietrzak VDF | Alternative time-locks |
| Dilithium | Post-quantum signatures |
| Kyber | Post-quantum encryption |
This specification is DID method agnostic but requires methods that support DID Document updates, resolution for recovery method discovery, and deactivation of compromised recovery methods.
The JSON-LD context is available at: https://w3c-ccg.github.io/did-recovery/context/v1.jsonld
{
"@context": {
"@version": 1.1,
"@protected": true,
"recovery": "https://w3c-ccg.github.io/did-recovery#recovery",
"RecoveryMethodZKPSocial": "https://w3c-ccg.github.io/did-recovery#RecoveryMethodZKPSocial",
"RecoveryMethodDeterministic": "https://w3c-ccg.github.io/did-recovery#RecoveryMethodDeterministic",
"RecoveryMethodMPC": "https://w3c-ccg.github.io/did-recovery#RecoveryMethodMPC",
"recoveryThreshold": "https://w3c-ccg.github.io/did-recovery#recoveryThreshold",
"vssScheme": "https://w3c-ccg.github.io/did-recovery#vssScheme",
"vssGroupParameters": "https://w3c-ccg.github.io/did-recovery#vssGroupParameters",
"vssCommitments": "https://w3c-ccg.github.io/did-recovery#vssCommitments",
"recoveryGuardians": "https://w3c-ccg.github.io/did-recovery#recoveryGuardians",
"guardianEndpoint": "https://w3c-ccg.github.io/did-recovery#guardianEndpoint",
"seedDerivationPath": "https://w3c-ccg.github.io/did-recovery#seedDerivationPath",
"encryptedSeedLockbox": "https://w3c-ccg.github.io/did-recovery#encryptedSeedLockbox",
"deadMansSwitch": "https://w3c-ccg.github.io/did-recovery#deadMansSwitch",
"mpcThreshold": "https://w3c-ccg.github.io/did-recovery#mpcThreshold",
"mpcProviders": "https://w3c-ccg.github.io/did-recovery#mpcProviders",
"shareRotation": "https://w3c-ccg.github.io/did-recovery#shareRotation",
"currentEpoch": "https://w3c-ccg.github.io/did-recovery#currentEpoch",
"synchronization": "https://w3c-ccg.github.io/did-recovery#synchronization",
"maxEpochSkew": "https://w3c-ccg.github.io/did-recovery#maxEpochSkew",
"catchupProtocol": "https://w3c-ccg.github.io/did-recovery#catchupProtocol"
}
}
Group parameters: (p, q, g) as defined in §Cryptographic Primitives.
Setup: Secret s = 42, [=threshold=] t = 2, total shares n = 3, polynomial P(x) = 42 + 17·x (over Zq).
Commitments: C₀ = 442 mod p, C₁ = 417 mod p
Share verification example for s₃ (x=3):
Recovery with shares s₁, s₂ (Lagrange in Zq):
Applying a refresh polynomial R(x) = 5·x (R(0)=0):
Master Seed: 0x7f3a9b8c2d5e1f4a3b6c7d8e9f0a1b2c
Derivation Path: m/44'/0'/0'/0/0
PBKDF2 salt: "did-recovery-salt:did:example:123" (UTF-8), 100,000 iterations
Derived Private Key: SHA-256(PBKDF2(seed, salt, 100000, 32))
fROST t=2, n=3 — share format (illustrative):
Group Public Key: 0x3a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d...
Share 1 (epoch 1): 0x8c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f...
Share 2 (epoch 1): 0x2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e...
Share 3 (epoch 1): 0x7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c...
The editor thanks the members of the W3C Credentials Community Group for their valuable feedback.