DCTRL-0001: The `did:decentrl` DID Method
Self-contained DID method that embeds public keys and mediator endpoint directly in the identifier string.
| Field | Value |
|---|---|
| RFC | DCTRL-0001 |
| Title | The did:decentrl DID Method |
| Status | Draft |
| Created | 2026-03-14 |
| Version | 0.1 |
Abstract
This document specifies did:decentrl, a Decentralized Identifier (DID) method for the Decentrl Protocol. A did:decentrl identifier is entirely self-contained: it encodes the identity's cryptographic public keys and mediator relationship directly in the DID string, enabling immediate resolution without registry lookups or network requests. This method is designed for lightweight, short-lived identities suitable for privacy-preserving communication in decentralized networks.
Status of This Document
This is a draft specification. It is subject to change as the Decentrl Protocol evolves.
Table of Contents
- Introduction
- Terminology
- DID Method Name
- DID Method-Specific Identifier
- DID Document
- CRUD Operations
- Resolution
- Security Considerations
- Privacy Considerations
- References
1. Introduction
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119].
The did:decentrl method provides self-contained decentralized identifiers for the Decentrl Protocol. Unlike methods that require registry services or HTTP resolution of external documents, a did:decentrl identifier embeds all information necessary for secure communication directly in the DID string:
- An Ed25519 public signing key for authentication and message verification
- An X25519 public pre-key for bootstrapping encrypted communication contracts
- A mediator DID that specifies the identity's message routing infrastructure
This design enables immediate use without infrastructure dependencies. Any party that possesses a did:decentrl string can extract the identity's public keys, determine its mediator, and initiate communication — all without network requests.
The did:decentrl method is intentionally designed for short-lived, disposable identities. It does not support key rotation, mediator changes, or DID document updates. Users are expected to generate new identities periodically and migrate relationships through new communication contracts. This deliberate constraint simplifies implementation while providing strong privacy benefits through frequent identity rotation.
1.1 Conformance
A conforming implementation MUST support all REQUIRED features described in this specification. A conforming implementation MAY support OPTIONAL features.
A conforming DID resolver MUST be able to parse any valid did:decentrl identifier and produce the corresponding DID document as specified in Section 5.
2. Terminology
Identity — A participant in the Decentrl network identified by a did:decentrl identifier and in possession of the corresponding private keys.
Signing Key — An Ed25519 key pair used for digital signatures, authentication, and identity verification.
Pre-Key — An X25519 key pair used exclusively for bootstrapping new communication contracts. The public pre-key is embedded in the DID and published in the DID document. It is NOT used for ongoing encryption.
Storage Key — A 256-bit AES symmetric key generated at identity creation, stored only on the local device, and never published or shared. Used for encrypting events at rest. The storage key is NOT part of the DID or DID document.
Mediator — A network participant that provides message routing and encrypted storage services. Identified by its own DID (typically did:web).
Multibase — An encoding scheme that prefixes encoded data with a character identifying the encoding algorithm. This specification uses two multibase encodings: base58btc (prefix z) and base64 (prefix m).
Communication Contract — A bilateral cryptographic agreement between two identities that establishes a secure communication channel. Defined in [DCTRL-0002].
3. DID Method Name
The method name for this DID method is: decentrl
A DID using this method MUST begin with the prefix did:decentrl:. The remainder of the DID is the method-specific identifier defined in Section 4.
4. DID Method-Specific Identifier
4.1 Syntax
The did:decentrl method-specific identifier is composed of four colon-separated segments:
did:decentrl:<alias>:<signing-key>:<pre-key>:<mediator-did>In ABNF notation:
did-decentrl = "did:decentrl:" alias ":" signing-key ":" pre-key ":" mediator-did
alias = multibase-base64
signing-key = multibase-base58btc
pre-key = multibase-base58btc
mediator-did = multibase-base64
multibase-base64 = "m" 1*BASE64CHAR
multibase-base58btc = "z" 1*BASE58CHAR
BASE64CHAR = ALPHA / DIGIT / "+" / "/" / "="
BASE58CHAR = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
/ "A" / "B" / "C" / "D" / "E" / "F" / "G" / "H" / "J"
/ "K" / "L" / "M" / "N" / "P" / "Q" / "R" / "S" / "T"
/ "U" / "V" / "W" / "X" / "Y" / "Z"
/ "a" / "b" / "c" / "d" / "e" / "f" / "g" / "h" / "i"
/ "j" / "k" / "m" / "n" / "o" / "p" / "q" / "r" / "s"
/ "t" / "u" / "v" / "w" / "x" / "y" / "z"4.2 Segment Definitions
4.2.1 alias
A human-readable name for the identity. The alias is a UTF-8 string encoded as bytes, then encoded using multibase base64 (prefix m).
Encoding procedure:
- Take the alias as a UTF-8 string (e.g.,
"alice") - Convert to bytes using UTF-8 encoding
- Encode the bytes using standard base64
- Prepend the multibase prefix
m
Example: "alice" → UTF-8 bytes [97, 108, 105, 99, 101] → base64 "YWxpY2U=" → multibase "mYWxpY2U="
The alias has no maximum length constraint but implementations SHOULD keep it under 64 bytes (before encoding) for practical DID string length.
The alias is NOT used for identity verification or routing. It is informational only and MAY be displayed in user interfaces.
4.2.2 signing-key
The Ed25519 public signing key for this identity, encoded using multibase base58btc (prefix z).
Encoding procedure:
- Take the 32-byte Ed25519 public key
- Encode using base58btc (Bitcoin alphabet)
- Prepend the multibase prefix
z
Example: z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
The signing key MUST be exactly 32 bytes before encoding. Implementations MUST reject DIDs where the decoded signing key is not exactly 32 bytes.
4.2.3 pre-key
The X25519 public pre-key for this identity, encoded using multibase base58btc (prefix z).
Encoding procedure:
- Take the 32-byte X25519 public key
- Encode using base58btc (Bitcoin alphabet)
- Prepend the multibase prefix
z
Example: z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc
The pre-key MUST be exactly 32 bytes before encoding. Implementations MUST reject DIDs where the decoded pre-key is not exactly 32 bytes.
The pre-key serves a single purpose: protecting the privacy of communication contract establishment. When a party initiates a contract, they encrypt the contract request using X25519(initiator_ephemeral_private, recipient_pre_key). This ensures that mediators cannot read contract details. Once a contract is established with its own ephemeral keys, the pre-key is no longer involved.
4.2.4 mediator-did
The DID of the mediator that provides message routing and storage services for this identity. The mediator DID string is encoded as UTF-8 bytes, then encoded using multibase base64 (prefix m).
Encoding procedure:
- Take the mediator DID as a UTF-8 string (e.g.,
"did:web:mediator.example.com") - Convert to bytes using UTF-8 encoding
- Encode the bytes using standard base64
- Prepend the multibase prefix
m
Example: "did:web:mediator.example.com" → multibase "mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ=="
The mediator DID MUST itself be a valid DID. In version 0.1 of the Decentrl Protocol, the mediator DID MUST use the did:web method.
4.3 Example DID
did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==4.4 Parsing
To parse a did:decentrl identifier, implementations MUST:
- Verify the string begins with
did:decentrl: - Remove the prefix
did:decentrl: - Split the remainder on
:(colon) - Verify exactly 4 segments exist
- Decode each segment using multibase:
- Segment 0 (alias): verify prefix
m, decode base64, interpret as UTF-8 string - Segment 1 (signing-key): verify prefix
z, decode base58btc, verify result is exactly 32 bytes - Segment 2 (pre-key): verify prefix
z, decode base58btc, verify result is exactly 32 bytes - Segment 3 (mediator-did): verify prefix
m, decode base64, interpret as UTF-8 string, verify result is a valid DID
- Segment 0 (alias): verify prefix
If any step fails, the DID is invalid. Implementations MUST return an error and MUST NOT produce a DID document.
4.5 Validation
A valid did:decentrl identifier MUST satisfy all of the following:
- The string MUST begin with
did:decentrl: - The method-specific identifier MUST contain exactly four colon-separated segments
- The first segment (alias) MUST be a valid multibase base64 string (prefix
m) - The second segment (signing-key) MUST be a valid multibase base58btc string (prefix
z) that decodes to exactly 32 bytes - The third segment (pre-key) MUST be a valid multibase base58btc string (prefix
z) that decodes to exactly 32 bytes - The fourth segment (mediator-did) MUST be a valid multibase base64 string (prefix
m) that decodes to a valid DID string
5. DID Document
5.1 Production
Resolving a did:decentrl identifier produces a DID document synthetically — no network fetch is required for the DID document itself. The document is constructed from the data embedded in the DID string.
A conforming implementation MUST produce a DID document with the following structure:
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/jws-2020/v1"
],
"id": "<the full did:decentrl string>",
"alias": ["<decoded alias string>"],
"controller": "<the full did:decentrl string>",
"verificationMethod": [
{
"id": "<did>#signing",
"type": "Ed25519VerificationKey2020",
"controller": "<did>",
"publicKeyMultibase": "<signing-key segment as-is from the DID>"
}
],
"authentication": ["<did>#signing"],
"keyAgreement": [
{
"id": "<did>#prekey",
"type": "X25519KeyAgreementKey2020",
"controller": "<did>",
"publicKeyMultibase": "<pre-key segment as-is from the DID>"
}
],
"service": [
{
"id": "#mediator-service",
"type": "DecentrlMediator",
"serviceEndpoint": {
"uri": "<resolved mediator HTTP endpoint>"
}
}
]
}5.2 Required Properties
5.2.1 @context
MUST be exactly ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/jws-2020/v1"].
5.2.2 id
MUST be the full did:decentrl string being resolved.
5.2.3 alias
MUST be an array containing the decoded alias string from the DID. The alias is decoded from the first segment using multibase base64 and interpreted as UTF-8.
5.2.4 controller
MUST be the full did:decentrl string. The identity is self-controlled.
5.2.5 verificationMethod
MUST contain exactly one entry:
| Property | Value |
|---|---|
id | <did>#signing |
type | Ed25519VerificationKey2020 |
controller | <did> (the full DID string) |
publicKeyMultibase | The signing-key segment from the DID (already in multibase base58btc format) |
The fragment identifier for the signing key MUST be #signing.
5.2.6 authentication
MUST contain exactly one entry: a string reference to the signing verification method: "<did>#signing".
5.2.7 keyAgreement
MUST contain exactly one entry:
| Property | Value |
|---|---|
id | <did>#prekey |
type | X25519KeyAgreementKey2020 |
controller | <did> (the full DID string) |
publicKeyMultibase | The pre-key segment from the DID (already in multibase base58btc format) |
The fragment identifier for the pre-key MUST be #prekey.
5.2.8 service
MUST contain exactly one entry:
| Property | Value |
|---|---|
id | #mediator-service |
type | DecentrlMediator |
serviceEndpoint.uri | The HTTP endpoint of the mediator, obtained by resolving the mediator DID |
The mediator HTTP endpoint is obtained through the resolution process described in Section 7.2.
5.3 Verification Method Types
This specification uses two verification method types from the W3C DID specification:
Ed25519VerificationKey2020 — Used for the signing key. The publicKeyMultibase value is a multibase base58btc-encoded 32-byte Ed25519 public key.
X25519KeyAgreementKey2020 — Used for the pre-key. The publicKeyMultibase value is a multibase base58btc-encoded 32-byte X25519 public key.
5.4 Service Types
DecentrlMediator — A Decentrl mediator service. The serviceEndpoint object MUST contain a uri property with the HTTP(S) endpoint URL of the mediator.
6. CRUD Operations
6.1 Create
A did:decentrl identifier is created locally by the identity owner. The creation process:
- Generate an Ed25519 key pair (signing key). The private key MUST be stored securely on the local device.
- Generate an X25519 key pair (pre-key). The private key MUST be stored securely on the local device.
- Generate a 256-bit random storage key. This key MUST be stored securely on the local device and MUST NOT be published, shared, or included in any DID document or protocol message.
- Choose a mediator and obtain its DID string (e.g.,
did:web:mediator.example.com). - Choose an alias string.
- Construct the DID string:
alias_encoded = "m" + base64(UTF8_encode(alias))
signing_key_encoded = "z" + base58btc(signing_public_key)
pre_key_encoded = "z" + base58btc(pre_key_public_key)
mediator_encoded = "m" + base64(UTF8_encode(mediator_did))
did = "did:decentrl:" + alias_encoded + ":" + signing_key_encoded + ":" + pre_key_encoded + ":" + mediator_encodedNo network interaction is required to create a did:decentrl identifier. The identity exists as soon as the key material is generated and the DID string is constructed.
However, to receive messages, the identity MUST register with its mediator by establishing a communication contract with the mediator's DID (see [DCTRL-0002]).
6.2 Read (Resolve)
Resolution of a did:decentrl identifier is defined in Section 7.
6.3 Update
The did:decentrl method does NOT support updates. A did:decentrl identifier is immutable once created. The public keys and mediator relationship encoded in the DID string cannot be changed.
To rotate keys, change mediators, or update any aspect of the identity, the owner MUST create a new did:decentrl identifier and re-establish communication contracts with their contacts.
This is a deliberate design decision that simplifies implementation and improves privacy through identity rotation.
6.4 Deactivate (Delete)
The did:decentrl method does NOT support explicit deactivation. A did:decentrl identifier becomes effectively deactivated when:
- The identity owner stops using it and destroys the private keys, OR
- All communication contracts associated with the DID expire, OR
- The mediator ceases operation
There is no protocol mechanism to broadcast deactivation. Contacts discover that an identity is no longer active when communication contracts expire and are not renewed.
7. Resolution
7.1 DID Document Resolution
Resolving a did:decentrl identifier produces a DID document without fetching the document itself from the network. The resolution algorithm:
Input: A did:decentrl string.
Output: A DID document as specified in Section 5, or an error.
Algorithm:
1. Parse the DID string (see Section 4.4)
- If parsing fails → return invalidDid error
2. Decode the alias (segment 0):
alias_string = UTF8_decode(multibase_decode(segment[0]))
3. Extract the signing key (segment 1):
signing_key_multibase = segment[1]
signing_key_bytes = multibase_decode(segment[1])
- If length ≠ 32 bytes → return invalidPublicKey error
4. Extract the pre-key (segment 2):
pre_key_multibase = segment[2]
pre_key_bytes = multibase_decode(segment[2])
- If length ≠ 32 bytes → return invalidPublicKey error
5. Decode the mediator DID (segment 3):
mediator_did = UTF8_decode(multibase_decode(segment[3]))
- If mediator_did is not a valid DID → return invalidDid error
6. Resolve the mediator HTTP endpoint (see Section 7.2):
mediator_uri = resolve_mediator_endpoint(mediator_did)
- If resolution fails → return notFound error
7. Construct the DID document as specified in Section 5.1,
using: did, alias_string, signing_key_multibase, pre_key_multibase, mediator_uri
8. Return the DID documentImplementations SHOULD cache resolved DID documents with a TTL of 10 minutes. The cache key is the full DID string.
7.2 Mediator Endpoint Resolution
The mediator DID embedded in a did:decentrl identifier MUST be resolved to obtain the mediator's HTTP endpoint. In version 0.1, the mediator DID uses the did:web method.
Algorithm:
1. Verify the mediator DID starts with "did:web:"
- If not → return unsupportedDidMethod error
2. Convert the did:web DID to an HTTP URL:
a. Remove the "did:web:" prefix
b. Split the remainder on ":"
c. URL-decode the first segment to get the domain
d. Determine the protocol:
- If domain contains "localhost" → use "http"
- Otherwise → use "https"
e. If only one segment (domain only):
→ URL = "{protocol}://{domain}/.well-known/did.json"
f. If multiple segments:
→ path = join remaining segments with "/"
→ URL = "{protocol}://{domain}/{path}/did.json"
3. Fetch the URL with HTTP GET:
- Set Accept header to "application/json"
- Timeout: 10 seconds
- If request fails → return notFound error
4. Parse the response body as JSON
- Validate against the DID document schema (Section 5)
- If validation fails → return invalidDidDocument error
5. Extract the mediator service endpoint:
a. Find a service entry with type "DecentrlMediator"
b. Return serviceEndpoint.uri
- If no matching service → return serviceNotFound errorExamples:
| Mediator DID | Resolution URL |
|---|---|
did:web:mediator.example.com | https://mediator.example.com/.well-known/did.json |
did:web:example.com:mediators:alice | https://example.com/mediators/alice/did.json |
did:web:localhost | http://localhost:{port}/.well-known/did.json |
7.3 Resolution Metadata
Conforming implementations SHOULD return the following resolution metadata alongside the DID document:
| Property | Value |
|---|---|
contentType | application/did+json |
created | Not available (no creation timestamp in the DID) |
updated | Not available (DID is immutable) |
deactivated | Not determinable (no deactivation mechanism) |
8. Security Considerations
8.1 Key Compromise
If the signing key private key is compromised, the attacker can impersonate the identity by signing commands and events. However, they cannot decrypt existing communication contracts (which use independent ephemeral keys) or access stored events (which use the storage key).
If the pre-key private key is compromised, the attacker can decrypt new inbound communication contract requests. Existing contracts are unaffected because they use ephemeral keys independent of the pre-key.
Remediation: Since did:decentrl does not support key rotation, the only remediation for key compromise is to create a new identity and re-establish communication contracts. This is consistent with the method's design as a short-lived identity format.
8.2 Immutability
The self-contained nature of did:decentrl means the DID string is immutable. This provides strong guarantees:
- The public keys associated with a DID cannot change over time
- The mediator relationship is fixed for the lifetime of the identity
- There is no risk of a registry or resolver returning a tampered DID document
However, this also means that key rotation and mediator migration require creating a new identity entirely.
8.3 No Revocation
There is no mechanism to revoke a did:decentrl identifier. If an identity is compromised, the owner cannot broadcast a revocation to the network. Instead, the owner must:
- Create a new
did:decentrlidentifier - Establish new communication contracts with their contacts using the new DID
- Destroy the private keys associated with the compromised DID
Contacts will eventually stop using the old DID as existing communication contracts expire.
8.4 Mediator Trust
The mediator DID embedded in a did:decentrl identifier identifies the mediator but does not establish trust in that mediator. The Decentrl Protocol's security model does not rely on mediator confidentiality — all payloads are end-to-end encrypted and all commands are signed.
A malicious mediator can:
- Refuse to deliver messages (denial of service)
- Observe metadata (sender/recipient DIDs, timestamps, message sizes)
A malicious mediator cannot:
- Read message contents (encrypted with contract root secrets)
- Forge messages (requires the sender's signing key)
- Tamper with messages (event-level signatures prevent this)
8.5 Correlation
A did:decentrl identifier contains the identity's public keys, which are unique. Any party that observes the same DID in different contexts can correlate those observations to the same identity. Frequent identity rotation mitigates this risk.
The mediator DID embedded in the identifier also reveals which mediator the identity uses, which can be used for correlation and traffic analysis.
8.6 DID String Length
Because all identity information is embedded in the DID string, did:decentrl identifiers are significantly longer than registry-based DIDs. A typical did:decentrl string is approximately 150-250 characters depending on the alias and mediator DID lengths. Implementations MUST handle DID strings up to 1024 characters.
9. Privacy Considerations
9.1 Self-Contained Identity Disclosure
Sharing a did:decentrl identifier inherently discloses the identity's public signing key, public pre-key, and mediator. This is by design — the DID is intended to contain all information needed for communication. However, parties should be aware that sharing their DID reveals their infrastructure choices.
9.2 Identity Rotation
The did:decentrl method encourages frequent identity rotation. Creating a new identity and migrating communication contracts provides:
- Forward privacy: old identities cannot be linked to new ones without cooperation
- Key freshness: regular key generation limits the exposure window of any compromise
- Mediator migration: changing mediators is as simple as creating a new identity
Implementations SHOULD provide mechanisms for automated identity rotation and contract migration.
9.3 Alias Privacy
The alias is human-readable and may contain personally identifying information. Users SHOULD choose aliases that do not reveal more information than intended. Implementations MAY warn users when aliases contain potentially identifying information.
9.4 Mediator Privacy
The mediator DID is visible to anyone who possesses the did:decentrl string. This reveals:
- Which mediator the identity uses
- The mediator's domain (from the
did:webmediator DID) - Potentially the geographic jurisdiction of the mediator
Users who require maximum privacy SHOULD consider operating their own mediator.
10. References
10.1 Normative References
- [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
- [W3C-DID-CORE] W3C, "Decentralized Identifiers (DIDs) v1.0", W3C Recommendation, July 2022. https://www.w3.org/TR/did-core/
- [DID-WEB] W3C Credentials Community Group, "did:web Method Specification". https://w3c-ccg.github.io/did-method-web/
- [MULTIBASE] Multiformats, "Multibase: Self-identifying base encodings". https://github.com/multiformats/multibase
- [Ed25519] Bernstein, D.J., et al., "High-speed high-security signatures", Journal of Cryptographic Engineering, 2012.
- [X25519] Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves for Security", RFC 7748, January 2016.
10.2 Informative References
- [DCTRL-0002] "Communication Contracts" (planned). Specifies the bilateral cryptographic agreement protocol used for establishing secure communication channels.
- [DCTRL-0003] "Mediator Protocol" (planned). Specifies the mediator HTTP API, command wire format, and WebSocket protocol.
- [BASE58BTC] Bitcoin Wiki, "Base58Check encoding". Uses the Bitcoin alphabet:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz.
Appendix A: Complete Resolution Example
Given DID:
did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==Step 1 — Parse segments:
segment[0] = "mYWxpY2U=" (alias)
segment[1] = "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK" (signing key)
segment[2] = "z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc" (pre-key)
segment[3] = "mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==" (mediator DID)Step 2 — Decode:
alias = base64_decode("YWxpY2U=") = "alice"
signing_key = base58btc_decode("6Mkha...") = <32 bytes>
pre_key = base58btc_decode("6LSby...") = <32 bytes>
mediator_did = base64_decode("ZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==")
= "did:web:mediator.example.com"Step 3 — Resolve mediator endpoint:
did:web:mediator.example.com
→ GET https://mediator.example.com/.well-known/did.json
→ Extract service with type "DecentrlMediator"
→ mediator_uri = "https://mediator.example.com"Step 4 — Produce DID document:
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/jws-2020/v1"
],
"id": "did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==",
"alias": ["alice"],
"controller": "did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==",
"verificationMethod": [
{
"id": "did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==#signing",
"type": "Ed25519VerificationKey2020",
"controller": "did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==",
"publicKeyMultibase": "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
}
],
"authentication": [
"did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==#signing"
],
"keyAgreement": [
{
"id": "did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==#prekey",
"type": "X25519KeyAgreementKey2020",
"controller": "did:decentrl:mYWxpY2U=:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK:z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc:mZGlkOndlYjptZWRpYXRvci5leGFtcGxlLmNvbQ==",
"publicKeyMultibase": "z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc"
}
],
"service": [
{
"id": "#mediator-service",
"type": "DecentrlMediator",
"serviceEndpoint": {
"uri": "https://mediator.example.com"
}
}
]
}Appendix B: Identity Creation Pseudocode
function createDecentrlIdentity(alias, mediatorDid):
// 1. Generate cryptographic key material
signing_keypair = Ed25519_generate_keypair() // 32-byte private, 32-byte public
pre_keypair = X25519_generate_keypair() // 32-byte private, 32-byte public
storage_key = secure_random_bytes(32) // 256-bit AES key
// 2. Encode DID segments
alias_encoded = "m" + base64_encode(UTF8_encode(alias))
signing_key_encoded = "z" + base58btc_encode(signing_keypair.public)
pre_key_encoded = "z" + base58btc_encode(pre_keypair.public)
mediator_encoded = "m" + base64_encode(UTF8_encode(mediatorDid))
// 3. Construct DID string
did = "did:decentrl:" + alias_encoded + ":"
+ signing_key_encoded + ":"
+ pre_key_encoded + ":"
+ mediator_encoded
// 4. Store private keys securely
secure_store(signing_keypair.private)
secure_store(pre_keypair.private)
secure_store(storage_key) // NEVER share or publish
return {
did: did,
signing: signing_keypair,
pre_key: pre_keypair,
storage_key: storage_key
}Appendix C: Base58btc Alphabet
The base58btc encoding uses the Bitcoin alphabet, which excludes visually ambiguous characters (0, O, I, l):
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyzThis alphabet contains exactly 58 characters. Leading zero bytes in the input are encoded as leading 1 characters in the output.