This document is licensed under a Creative Commons Attribution 4.0 License.
Decentralized Identifiers (DIDs) are a new type of identifier for verifiable, decentralized digital identity. These new 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. 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.
This document is draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organization.
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.
This section is non-normative.
Decentralized Identifiers (DIDs) [DID-CORE] are a new type of identifier for verifiable, decentralized digital identity. These new 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. For example, a DID that will only be used for a single, ephemeral interaction might not need to be registered, updated, or deactivated, or where private keys are protected by software or hardware isolation. These are a few of the cases where using did:key might offer unique benefits.
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 method, the operations it supports, 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-CORE]
specification and is simple. It consists of the did:key prefix,
followed by a Multibase [MULTIBASE] base58-btc encoded value that is a
concatenation of the Multicodec [MULTICODEC] 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]+
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-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 § 2. The did:key Format. 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",
"https://w3id.org/security/suites/ed25519-2020/v1",
"https://w3id.org/security/suites/x25519-2020/v1"
],
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"verificationMethod": [{
"id": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"type": "Ed25519VerificationKey2020",
"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": "X25519KeyAgreementKey2020",
"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 JsonWebKey2020 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 MAY be overridden by the caller of this algorithm. A document
is the resulting output.
:) as the delimiter, split the identifier into its
components: a scheme, a method, a version, and a
multibaseValue. If there are only three components set the
version to the string value 1 and use the last value as the
multibaseValue.
did. If this requirement fails, an invalidDid error MUST be raised.
The method MUST be the value key. If this requirement fails, a
methodNotSupported error MUST be raised. The version MUST be convertible
to a positive integer value. The multibaseValue MUST be a string and begin
with the letter z. If any of these requirements fail, an invalidDid error MUST be raised.
invalidDid error MUST be raised.
verificationMethod property in document to an array
where the first value is the signatureVerificationMethod.
authentication, assertionMethod, capabilityInvocation,
and the capabilityDelegation properties in document to an array
where the first item is the value of the id property in
signatureVerificationMethod.
true:
verificationMethod
array.
keyAgreement property in document to an array where
the first item is the value of the id property in
encryptionVerificationMethod.
@context property in document to the result of
passing document and options to the
§ 3.1.7 Context Creation Algorithm.
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) |
0x1202 |
?? bytes | p521-pub - P-521 public key (compressed) |
0x1205 |
?? bytes | rsa-pub - RSA public key. DER-encoded ASN.1 type RSAPublicKey according to IETF RFC 8017 (PKCS #1) |
invalidPublicKeyLength error MUST be raised.
invalidPublicKey error MUST be raised.
#), and the multicodecValue.
If verificationMethod.id is not a valid DID URL, an invalidDidUrl
error MUST be raised.
unsupportedPublicKeyType error MUST be raised.
false and
publicKeyFormat is not Multikey, JsonWebKey2020, or
Ed25519VerificationKey2020, an invalidPublicKeyType error MUST be raised.
invalidDid
error MUST be raised.
Multikey or Ed25519VerificationKey2020,
set the verificationMethod.publicKeyMultibase value to
multibaseValue.
JsonWebKey2020, set the
verificationMethod.publicKeyJwk value to the result of
passing multicodecValue and rawPublicKeyBytes to
§ 3.1.4 Encode JWK Algorithm.
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.
BLS12381 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.
kty, crv, n,e
values for the JWK representation of the key type identified by multicodecValue.
y is required member of the public key,
perform elliptic curve expansion by applying
decompression algorithm specified here.
to obtain y and x.
Otherwise simply encode x according to the associated RFCs.
d is NOT present.
Address RSA encoding for DER encoded RSA keys.
Address BLS12381 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 |
invalidPublicKeyLength error MUST be raised.
#), and the multibaseValue.
If verificationMethod.id is not a valid DID URL, an invalidDidUrl
error MUST be raised.
unsupportedPublicKeyType error MUST be raised.
false and
publicKeyFormat is not Multikey, JsonWebKey2020, or
X25519KeyAgreementKey2020, an invalidPublicKeyType error MUST be raised.
invalidDid error MUST be raised.
Multikey or X25519KeyAgreementKey2020,
set the verificationMethod.publicKeyMultibase value to
multibaseValue.
JsonWebKey2020, set the
verificationMethod.publicKeyJwk value to the result of
passing multicodecValue and rawPublicKeyBytes to
§ 3.1.4 Encode JWK Algorithm.
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.
0xed, derive a public X25519 encryption
key by using the rawPublicKeyBytes and the
algorithm defined in [OSCORE] for Curve25519 in
Section 2.4.2: ECDH with Montgomery Coordinates and set
generatedPublicEncryptionKeyBytes to the result.
0xec.
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, if it doesn't already exist, according to the following table:
type value |
Context URL |
|---|---|
Ed25519VerificationKey2020 |
https://w3id.org/security/suites/ed25519-2020/v1 |
X25519KeyAgreementKey2020 |
https://w3id.org/security/suites/x25519-2020/v1 |
JsonWebKey2020 |
https://w3id.org/security/suites/jws-2020/v1 |
Multikey |
There is currently no JSON-LD Context that defines the Multikey type. This is expected to be defined by the VC2WG in 2022 or 2023. |
Reading a did:key value is a matter of deterministically expanding the value to a DID Document. This process is described in Section § 3.1 Create.
This DID Method does not support updating the DID Document.
This DID Method does not support deactivating the DID Document.
This section is non-normative.
For a full list of test vectors see test vectors.
We provide only the verificationMethod section of the DID Document in these examples.
This section is non-normative.
These DID always start with z6Mk.
...
"verificationMethod": [
{
"id": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp",
"type": "JsonWebKey2020",
"controller": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp",
"publicKeyJwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik"
}
},
{
"id": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6LShs9GGnqk85isEBzzshkuVWrVKsRp24GnDuHk8QWkARMW",
"type": "JsonWebKey2020",
"controller": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp",
"publicKeyJwk": {
"kty": "OKP",
"crv": "X25519",
"x": "W_Vcc7guviK-gPNDBmevVw-uJVamQV5rMNQGUwCqlH0"
}
}
],
...
...
"verificationMethod": [
{
"id": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp",
"type": "Ed25519VerificationKey2020",
"controller": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp",
"publicKeyMultibase": "z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp"
},
{
"id": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6LShs9GGnqk85isEBzzshkuVWrVKsRp24GnDuHk8QWkARMW",
"type": "X25519KeyAgreementKey2020",
"controller": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp",
"publicKeyMultibase": "z6LShs9GGnqk85isEBzzshkuVWrVKsRp24GnDuHk8QWkARMW"
}
],
...
did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp
did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG
did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf
This section is non-normative.
These DID always start with z6LS.
did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F
did:key:z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha
did:key:z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ
This section is non-normative.
These DID always start with zQ3s.
did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme
did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2
did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N
This section is non-normative.
These DID always start with zUC7.
did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY
did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW
This section is non-normative.
These DID always start with zDn.
did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169
did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv
This section is non-normative.
These DID always start with z82.
did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9
did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54
This section is non-normative.
These DID always start with z2J9.
did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7
did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f
This section is non-normative.
See also RSA Public Key Representation.
This section is non-normative.
These DID always start with z4MX.
did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i
This section is non-normative.
These DID always start with zgg.
did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2
This section is non-normative.
There are a number of security and privacy considerations that implementers will want to take into consideration when implementing this specification.
This section is non-normative.
The did:key method is a purely generative method, which means that updates are not supported. This can be an issue if a did:key is expected to be used over a long period of time. For example, if a did:key is ever compromised, it is not possible to rotate the compromised key. For this reason, using a did:key for interactions that last weeks to months is strongly discouraged.
This section is non-normative.
The did:key method is a purely generative method, which means that deactivations are not supported. This can be an issue if a did:key is expected to be used over a long period of time. For example, if a did:key is ever compromised, it is not possible to deactivate the DID to stop an attacker from using it. For this reason, using a did:key for interactions that last weeks to months is strongly discouraged.
This section is non-normative.
Some implementations might utlize a key derivation function when converting from
an ed25519 public key to a Curve25519 ECDH key, used in the
keyAgreement verification method. It is expected that this is a
relatively safe operation, but implementers might consider that there exists no
mathematical proof that confirms this assumption.
This section is non-normative.
Since there is no support for update and deactivate for the did:key method, it is not possible to recover from a security compromise. For this reason, using a did:key for interactions that last weeks to months is strongly discouraged.
This section is non-normative.
An RSA public key for did:key is represented as a DER-encoded
RSAPublicKey data structure as specified in
RFC
3447 (PKCS #1), as registered in the Multicodec table (code
0x1205).
DER is a canonical encoding of ASN.1 values. For the aid of implementers who do not fully support ASN.1/DER, the following subsections describe the public key representation for RSA public keys that use some common parameters.
This section is non-normative.
A public key with 2048-bit modulus modulus and public exponent 65537 is represented by the concatenation of the following octet sequences:[48, 130, 1, 10, 2, 130, 1, 1, 0][0] if and only if the
most-significant bit of modulus is set.[2, 3, 1, 0, 1]See also the example 2048-bit test vector.
This section is non-normative.
A public key with 4096-bit modulus modulus and public exponent 65537 is represented by the concatenation of the following octet sequences:[48, 130, 2, 10, 2, 130, 2, 1, 0][0] if and only if the
most-significant bit of modulus is set.[2, 3, 1, 0, 1]See also the example 4096-bit test vector.
This section is non-normative.
The Working Group would like to thank the following individuals for reviewing and providing feedback on the specification (in alphabetical order):
TBD...