[=Decentralized Identifiers=] (DIDs) are a type of identifier for verifiable, decentralized digital identity. These identifiers are designed to enable the [=controller=] of a DID to prove control over the identifier in a way that is independent of any centralized registry, identity provider, or certificate authority. These sorts of identifiers often utilize a heavy-weight registry, such as ones utilizing Decentralized Ledger Technologies (DLT), to create, read, update, and deactivate DIDs. This specification describes a non-registry based [=DID Method=] based on expanding a cryptographic public key into a [=DID Document=]. This approach provides the simplest possible implementation of a DID Method that is able to achieve many, but not all, of the benefits of utilizing DIDs.
Portions of the work on this specification have been funded by the United States Department of Homeland Security's Science and Technology Directorate under contract HSHQDC-17-C-00019. The content of this specification does not necessarily reflect the position or the policy of the U.S. Government and no official endorsement should be inferred.
[=Decentralized Identifiers=] (DIDs) are a type of identifier for verifiable, decentralized digital identity. These identifiers are designed to enable the [=controller=] of a DID to prove control over it and to be implemented independently of any centralized registry, identity provider, or certificate authority. These sorts of identifiers often utilize a heavy-weight registry, such as ones utilizing Decentralized Ledger Technologies (DLT), to create, read, update, and deactivate DIDs.
While DLT-based DID Methods have great decentralization characteristics, and some of the more centralized DID Methods provide strong system control guarantees, the general approaches tend to be expensive to setup and operate. Some use cases requiring DIDs do not need the guarantees provided by these heavy-weight systems. The `did:key` method offers a lightweight alternative that provides several distinct advantages in specific scenarios: immediate availability without network dependencies, deterministic resolution requiring no registry lookups, zero infrastructure costs, complete offline operation capability, and maximum simplicity in implementation. These characteristics make `did:key` particularly well-suited for ephemeral interactions, development and testing environments, bootstrap scenarios, and situations where the overhead of registry operations is not justified by the duration or value of the interaction.
The choice to use `did:key` over a registry-based DID method is primarily driven by the temporal nature and risk profile of the intended use case. Registry-based methods excel when persistent identity, key rotation, recovery mechanisms, or deactivation capabilities are required—such as for long-term business relationships, credential issuance by established organizations, or scenarios involving high-value transactions. In contrast, `did:key` is optimal for short-lived sessions where the identifier will be used for days to weeks, peer-to-peer communications that do not require persistent identity, temporary credential presentations, or situations where the keys are protected by hardware security modules and can be rotated at the application layer. The deterministic nature of `did:key` also makes it valuable for testing and development, as the same key material always produces the same identifier without requiring access to external registries or networks.
Use of `did:key` for long-lived use cases is only recommended when accompanied with high confidence in hardware isolation.
The rest of this document outlines the syntax for the `did:key` identifier, the operations supported by the `did:key` method, and some security and privacy considerations that implementers might want to be aware of when implementing.
The format for the `did:key` method conforms to the [[[DID]]] specification and is simple. It consists of the `did:key` prefix, followed by a Multibase base58-btc or base64-url encoded value that is a concatenation of the Multikey identifier for the public key type and the raw bytes associated with the public key format.
The ABNF for the key format is described below:
did-key-format := did:key:<mb-value>
mb-value := (z[a-km-zA-HJ-NP-Z1-9]+|u[A-Za-z0-9_-]+)
Alternatively, the encoding rules can also be thought of as the application of a series of transformation functions on the raw public key bytes:
did-key-base58-btc-format := did:key:MULTIBASE(base58-btc, MULTICODEC(public-key-type, raw-public-key-bytes))A simple example of a valid Ed25519 `did:key` DID is:
did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
The following section outlines the DID operations for the `did:key` method. Implementers might note that this DID Method is purely generative, requiring no look ups in a registry. Since `did:key` values are not stored in any registry, they cannot be updated or deactivated.
Creating a `did:key` value consists of creating a cryptographic key pair and encoding the public key using the format provided in Section [[[#did-key-identifier-syntax]]]. The creation of a DID Document is also performed by taking the public key value and expanding it into DID Document. An example is given below that expands the ed25519 `did:key` `did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK` into its associated DID Document:
{
"@context": [
"https://www.w3.org/ns/did/v1.1"
],
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"verificationMethod": [{
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"type": "Multikey",
"controller": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"publicKeyMultibase": "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
}],
"authentication": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"assertionMethod": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"capabilityDelegation": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"capabilityInvocation": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"keyAgreement": [{
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6LSj72tK8brWgZja8NLRwPigth2T9QRiG1uH9oKZuKjdh9p",
"type": "Multikey",
"controller": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"publicKeyMultibase": "z6LSj72tK8brWgZja8NLRwPigth2T9QRiG1uH9oKZuKjdh9p"
}]
}
The following algorithm can be used for expanding a did:key identifier to a DID Document. An identifier and options are the required inputs. Implementations are expected to set a reasonable default for the options.publicKeyFormat value such as `JsonWebKey` or `Multikey`. The options.enableExperimentalPublicKeyTypes value SHOULD be set to `false`. The options.defaultContext value SHOULD be set to an array where the first element is the string value `https://www.w3.org/ns/did/v1`. Defaults might be overridden by the caller of this algorithm. A document is the resulting output.
Any alternative algorithm can be used that produces an equivalent result to the output from the algorithm above.
The following algorithm can be used for decoding a multibase-encoded multicodec value into a verification method that is suitable for verifying digital signatures. An identifier, multibaseValue, and options are the required inputs. A verificationMethod is the resulting output.
| Multicodec hexadecimal value | public key byte length | Description |
|---|---|---|
| `0xe7` | 33 bytes | secp256k1-pub - Secp256k1 public key (compressed) |
| `0xec` | 32 bytes | x25519-pub - Curve25519 public key |
| `0xed` | 32 bytes | ed25519-pub - Ed25519 public key |
| `0x1200` | 33 bytes | p256-pub - P-256 public key (compressed) |
| `0x1201` | 49 bytes | p384-pub - P-384 public key (compressed) |
The following algorithm can be used for expanding a multibase-encoded multicodec value to decoded public key components. A multibaseValue and options are the required inputs. A decodedPublicKey is the output.
There are 2 categories of JWK expressions for multicodec encoded public keys.
Standard JWK representations can be found under the IANA registry for JSON Object Signing and Encryption (JOSE) .
In cases where a key type has not been formally standardized yet a specification describing the key encoding is provided.
BLS12-381 is the only instance of such a key type in the current method specification. See this document tracking its proposed standardization at IETF. See draft-looker-cose-bls-key-representations.
Implementations MUST conform to the normative requirements of the RFCs and specifications above.
The following algorithm can be used to encode a multicodec value to a JSON Web Key. A multicodecValue, rawPublicKeyBytes are the required inputs. An encodedJWK is the output.
Address BLS12-381 Encoding.
The following algorithm can be used for decoding a multibase-encoded multicodec value into a verification method that is suitable for verifying that encrypted information will be received by the intended recipient. An identifier, multibaseValue, and options are the required inputs. A verificationMethod is the resulting output.
| Multicodec hexadecimal value | public key byte length | Description |
|---|---|---|
| `0xec` | 32 bytes | x25519-pub - Curve25519 public key |
The following algorithm can be used to transform a multibase-encoded multicodec value to public encryption key components that are suitable for encrypting messages to a receiver. A mathematical proof elaborating on the safety of performing this operation is available in [[THORMARKER]]. A multibaseValue and options are the required inputs. A publicEncryptionKey is the output.
The following algorithm is used to generate the array for the `@context` property in the DID Document. A document and options are the required inputs. A contextArray is the output.
| `type` value | Context URL |
|---|---|
| `Ed25519VerificationKey2020` | https://www.w3.org/ns/did/v1.1 |
| `X25519KeyAgreementKey2020` | https://www.w3.org/ns/did/v1.1 |
| `JsonWebKey` | https://www.w3.org/ns/did/v1.1 |
| `Multikey` | https://www.w3.org/ns/did/v1.1 |
Reading a `did:key` value is a matter of deterministically expanding the value to a DID Document. This process is described in Section .
This DID Method does not support updating the DID Document.
This DID Method does not support deactivating the DID Document.
This section contains a variety of privacy considerations that people using the `did:key` Method are advised to consider before deploying this technology in a production setting. Readers are urged to read the Privacy Considerations section of the [[[CID]]] specification, as well as the Privacy Considerations section of the [[[DID]]] specification, before reading this section.
The `did:key` method encodes the public key directly in the identifier itself, creating a deterministic relationship between the key material and the DID. This means that any two systems that receive the same `did:key` identifier can immediately recognize it as referring to the same subject, enabling correlation across different contexts and verifiers. Unlike registry-based DID methods where the identifier can be an opaque value, `did:key` identifiers are intrinsically tied to the cryptographic key, making the identifier both globally unique and globally correlatable.
This correlation risk is particularly acute in scenarios where a subject might wish to present different personas or maintain separation between different interactions. If the same `did:key` is reused across multiple verifiers, service providers, or interactions, those parties can collude or independently determine that they are interacting with the same subject, potentially building comprehensive profiles of the subject's activities without their knowledge or consent.
The `did:key` method does not support key rotation because the identifier is derived directly from the public key material itself. Any change to the cryptographic key would result in an entirely different DID, effectively creating a new identity rather than updating an existing one. This limitation has significant privacy implications, as there is no mechanism to recover privacy after a correlation event or to refresh the identifier while maintaining continuity of the underlying digital identity.
In long-lived relationships or scenarios where privacy requirements evolve over time, the inability to rotate keys without changing identifiers forces a choice between maintaining identifier continuity and improving privacy posture. This makes `did:key` particularly unsuitable for use cases where subjects might need to respond to correlation attacks, regulatory requirements for periodic key updates, or evolving privacy threat models over the lifetime of the identifier.
Every `did:key` identifier directly exposes the complete public key material as part of the identifier string itself. This is fundamentally different from registry-based DID methods where the identifier is a reference that must be resolved to obtain the public key. With `did:key`, anyone who observes the identifier in any context—whether in a credential, a transaction log, a communication header, or any other location—immediately gains access to the full cryptographic public key without any additional resolution step.
This constant exposure of public key material increases the attack surface for cryptanalysis and makes it impossible to implement selective disclosure of verification methods. It also means that any storage or transmission of the identifier itself, regardless of context, constitutes storage and transmission of cryptographic material, which might have implications for systems with strict data handling requirements or key management policies.
While the `did:key` method can technically be used to create pairwise DIDs by generating a new cryptographic key pair for each relationship, this approach significantly increases the operational burden on the subject. Each new pairwise relationship requires generating, storing, and managing an additional private key, along with the associated backup and recovery procedures. For subjects engaged in numerous relationships, this can quickly become unmanageable and increase the risk of key loss.
Additionally, unlike registry-based methods where a single key can be used to control multiple pairwise DIDs through controller relationships, `did:key` requires actual generation of new key material for each pairwise identifier. This makes it difficult to implement recovery mechanisms or delegate key management to trusted services, as each `did:key` represents an independent cryptographic identity with no hierarchical or delegated relationship to other identifiers controlled by the same subject.
This section contains a variety of security considerations that people using the `did:key` Method are advised to consider before deploying this technology in a production setting. Readers are urged to read the Security Considerations section of the [[[CID]]] specification, as well as the Security Considerations section of the [[[DID]]] specification, before reading this section.
The `did:key` method is a purely generative method, which means that updates are not supported. This creates a security concern for any long-lived use of the identifier, as there is no mechanism to rotate cryptographic keys in response to potential compromise, suspected exposure, or as part of routine security hygiene practices. If a private key associated with a `did:key` is compromised through theft, social engineering, malware, side-channel attacks, or any other means, the attacker gains permanent control over that identity with no possibility for the legitimate controller to regain exclusive control by rotating to new key material.
This limitation is of concern because best practices in cryptographic key management typically mandate periodic key rotation even in the absence of known compromise, as a defense-in-depth measure against undetected breaches. Modern security frameworks often require key rotation on regular schedules or after personnel changes, system migrations, or security incidents. The `did:key` method's inability to support these practices means that any use beyond short-lived, ephemeral interactions carries inherent and unmitigable risk of permanent compromise. To mitigate this concern, long-term use of `did:key` is expected to be via hardware security modules with the `did:key` value itself being rotated in whatever process it is used in on an acceptable cadence.
The `did:key` method provides no mechanism for deactivating or revoking an identifier once it has been created and distributed. In the event of key compromise, loss of control, or the need to terminate an identity for security reasons, there is no way to signal to verifiers that the `did:key` is not to be trusted or accepted other than via a high-level mechanism such as the revocation of a [=verifiable credential=] that is associated with the `did:key` identifier.
In contrast to did:key, registry-based DID methods can publish a deactivation status or remove the [=DID Document=] entirely, providing a clear signal to all verifiers that the identifier is no longer valid. Without deactivation support, security incident response for `did:key` is limited to out-of-band communication. This makes `did:key` not ideal in scenarios involving high-value transactions, legally binding agreements, or situations where unauthorized use of the identity could cause significant harm to the controller or relying parties.
Some implementations might utilize a key derivation function when converting from an Ed25519 public key to a Curve25519 ECDH key for use in the `keyAgreement` verification method. While this conversion is supported by the specification and is believed to be cryptographically sound based on the mathematical relationship between the Edwards curve (Ed25519) and the Montgomery curve (Curve25519) representations of Curve25519, there is no complete mathematical proof that this derivation preserves the full security properties of the original key in all contexts. This introduces a potential security risk, as subtle vulnerabilities in the conversion process could potentially be exploited to weaken the encryption key agreement without compromising the signature key.
The security concern is compounded by the fact that the same underlying key material is being used for two different cryptographic purposes—digital signatures and key agreement—which violates the cryptographic principle of key separation. While research such as [[THORMARKER]] provides analysis supporting the safety of this practice for Ed25519/X25519 specifically, implementers are relying on carefully constructed mathematical relationships rather than formally proven security guarantees. Organizations with strict security requirements might prefer to use separate key pairs for signature and encryption operations, which would require generating and managing multiple `did:key` identifiers rather than relying on key derivation.
Since there is no support for update and deactivate for the `did:key` method, it is not possible to recover from a security compromise, making long-term use inherently risky. The security posture of a `did:key` can only degrade over time as the private key is exposed to an increasing number of potential attack vectors—including storage vulnerabilities, backup procedures, key usage in multiple contexts, potential cryptographic weaknesses discovered in the future, and the general accumulation of attack surface over extended periods. Any long-lived `did:key` essentially becomes a single point of failure where compromise at any point during its lifetime results in permanent and irrecoverable security breach.
For this reason, using a `did:key` for interactions that last weeks to months is strongly discouraged unless it is coupled with a hardware security module of some kind. Use beyond short-lived contexts is to be carefully evaluated against specific threat models. The method is most appropriate for scenarios such as ephemeral peer-to-peer connections, short-lived authentication sessions, temporary delegation of capabilities, or situations where the identifier will be used only a small number of times with a limited set of verifiers. For any use case requiring persistent identity over extended periods, involving high-value assets, containing sensitive data, or subject to regulatory compliance requirements, implementers might instead consider registry-based DID methods that support key rotation, recovery mechanisms, and deactivation capabilities.
We provide only the `verificationMethod` section of the DID Document in these examples.
did:key:z6Mkf5rGMoatrSj1f4CyvuHBeXJELe9RPdzo2PKGNCKVtZxP
It is possible to derive an X25519 key from an Ed25519 one. An X25519 key is useful when perform such functions as key agreement between two systems.
{
"@context": [
"https://www.w3.org/ns/did/v1.1"
],
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"verificationMethod": [{
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"type": "Multikey",
"controller": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"publicKeyMultibase": "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
}],
"authentication": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"assertionMethod": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"capabilityDelegation": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"capabilityInvocation": [
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
],
"keyAgreement": [{
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6LSj72tK8brWgZja8NLRwPigth2T9QRiG1uH9oKZuKjdh9p",
"type": "Multikey",
"controller": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"publicKeyMultibase": "z6LSj72tK8brWgZja8NLRwPigth2T9QRiG1uH9oKZuKjdh9p"
}]
}
These DID always start with `zQ3s`.
did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme
did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2
did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N
did:key:zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCrx6Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h5ypoHjwBb
An example DID Document for a BLS12-381 key is shown below.
did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv
An example DID Document for a P-256 key is shown below.
did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54
An example DID Document for a P-384 key is shown below.
The Working Group would like to thank the following individuals for reviewing and providing feedback on the specification (in alphabetical order):
TBD...