JLINX DID Method Specification

version 1 - September 25, 2023

Abstract

This document specifies a method for creating and editing Decentralized IDs (DIDs). It conforms to the requirements specified in the DID specification currently published by the W3C Credentials Community Group.

Our goal is to provide a DID method that allows for key rotation, while remaining agnostic to persistence mechanisms and communication protocols.

The did:jlinx method defines a key rotation technique as well as the operations required by DID Core, and is interoperable across any comm protocol that allows for receiving and emitting JSON objects. A relying party should be able to resolve DIDs that are using HTTP, IPFS, Hypercore, Ceramic, Holochain, or any other such open protocol or blockchain, without having to have recourse to any “universal” resolver service.

We acknowledge with gratitude ideas from did:web and from KERI that partly inspired this effort.

© Portable Data Corporation 2023

Table of Contents

  1. Notation and Conventions
  2. Definitions
  3. Overview
  4. Method Name
  5. Format
    5.1. Scheme abbreviations
    5.2. DID document schema
    5.3. Example
  6. Operations
    6.1. Inception (creation)
    6.1.1 Inception via agent
    6.1.2 JWS header
    6.1.3 JWS payload
    6.1.4 JWS signature
    6.2. Resolution
    6.3. Update
    6.4. Revoke
  7. Security Considerations
  8. Privacy Considerations

1. Notation and Conventions

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.

2. Definitions

3. Overview

This specification defines the JLINX methods for creating, resolving and modifying DID documents. It is only partially conforming to the requirements specified in the DID specification currently published by the W3C Credentials Community Group, in that the DID url and resolution methods are non-conforming, and it uses unregistered property extensions.

4. Method Name

The namestring that shall identify the JLINX DID method is: jlinx.

A DID that uses this method MUST begin with the following prefix: did:jlinx. Per the DID specification, this string MUST be in lowercase.

5. Format

The JLINX DID has the following ABNF format:

jlinx-did = "did:jlinx:" scheme ":" host ":" id-string
scheme = 1* scheme-char
host = * host-char
id-string = 1* idchar
scheme-char = ALPHA / DIGIT
host-char = ALPHA / DIGIT / "-" / "."
idchar    = ALPHA / DIGIT / "." / "-" / "_" / pct-encoded
pct-encoded = "%" HEXDIG HEXDIG

The idchar consists of the characters in the BASE64 UrlSafe character set defined in RFC 4648 as base64url without padding.

5.1. Scheme Abbreviations

For the sake of compactness abbreviating the scheme name is recommended. The following abbreviations are standard for this DID method and will be updated from time to time.

Abbreviation Scheme
h https
i ipfs
hyp hypercore
c ceramic

For some schemes, for example hypercore, the host name is not required, as the idchar is all that is necessary for resolution.

In the case of the https scheme, the “h:” is transformed to “https://” and subsequent colons are replaced with “/” characters to form the request URL.

Example:
did:jlinx:h:did.jlinx.io:0fil1CNmwie8TevnTJckrvqsk9nyvo8U_3YRLeagAhI

5.2. DID document schema

The DID document MUST contain the following properties:

@context: the array [“https://www.w3.org/ns/did/v1”, “https://didspec.jlinx.io/v1/ctx.jsonld”]

version: an integer - version 1 includes the base64url encoding format for keys and hashes, the Ed25519 algorithm for public/private keys, and the Blake2b hashing algorithm

id: the jlinx DID that is the subject of this document

incp: an ISO 8601 formatted timestamp with milliseconds denoting the DID’s inception time

modf: an ISO 8601 formatted timestamp with milliseconds denoting the DID’s modification time, optional unless DID has been modified

actv: an object, containing at least - {sign: ***, ctrl: ***} - denoting the active signing and control keys

next: an object, containing at least - {sign: ***, ctrl: ***} - denoting hashes of the next signing and control keys in key rotation

prev: an object containing at least - {sign: ***, ctrl: ***, end: *** } - denoting the most recently superseded signing and control keys and an ISO 8601 formatted timestamp with milliseconds denoting the time the keys were superseded, optional unless DID has been superseded

The document MAY contain a service property conforming to the DID core specification

5.3. Example

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://didspec.jlinx.io/v1/ctx.jsonld"
  ],
  "version": 1,
  "id": "did:jlinx:h:did.jlinx.io:be54d07f06f2b70f04a24c1133ee4bcb",
  "incp": "2023-03-12T19:33:16.643Z",
  "actv": {
    "sign": "MzoJvNtBNX4b5xltYpdBk07ztb2OyxMiKqOnRdWRGSc",
    "ctrl": "HccjhsDiu7QNg_8ehFvTqroV5NTV1Cuk-TeMjn99tBY"
  },
  "next": {
    "sign": "B5SFPJMKu9H-XWQtAOYVtR3aj5xSPSo1Z0mOkrWmO9k",
    "ctrl": "kco5Oz6GKeoe6jqu-Xd8my_MzbWZIhYrK8t5ODwLNBU"
  },
  "service": [
    {
      "id": "did:jlinx:h:did.jlinx.io:be54d07f06f2b70f04a24c1133ee4bcb#linked-domain",
      "type": "LinkedDomains",
      "serviceEndpoint": "https://link.example.com"
    }
  ]
}

6. Operations

For some schemes, it is necessary to create a container for the DID document first, in order to get the address that will be the unique id-string of the DID. Otherwise a strong cryptographic hash of the inception controlling key is recommended for the id, in order to insure global uniqueness. For non content-addressed schemes, the address (e.g. the host name in the https scheme) MUST be considered part of the DID id.

6.1. Inception (DID creation)

First create an object in accordance with the schema above, and add in any other desired properties. If a service section is desired it SHOULD conform to the DID core spec for that section.

The signing and controlling keys, as well as the nextsigning and nextcontrolling keys are the public key portions of the result of:

{publickey, privatekey} = createKeypair()

All of the private keys SHOULD be carefully persisted. In particular the next private keys SHOULD be persisted in the most secure manner possible.

The signing and controlling public keys and the hashes of the “next” public keys are then entered into the document as described above.

Once complete, the object MUST be encoded into JSON.

The next inception step depends on whether the DID document is being sent directly to the storage from where it will be made available, i.e. the DID controller is acting as their own agent, or alternatively the DID document is being transmitted to an agent for storage and retrieval.

If the DID controller is acting as their own agent, then they must implement whatever procedure is required to create and/or update documents on the desired storage resource (e.g. IPFS or Ceramic).

If the controller is acting via an agent, the agent MUST implement the following procedure.

6.1.1 Inception via agent

If the DID document is being transmitted to an agent, then rather than transmitting the document in raw JSON form, it SHOULD be encapsulated in a JWS as described below.

6.1.2 JWS header

The JWS header MUST take the following form, with each field being required:

Property Value
alg One of the values described in JWS Web Algorithms or JWA Elliptic Curve.
NB: The “none” algorithm type MUST NOT be used.
typ The string “JWT”
jwk A JSON web key as described in JWK. Care should be taken not to include any private key material.
The JWK SHOULD include a “kid” field which SHOULD be set to the DID id value.
The public key represented in the JWK MUST be that of the DID controller.

Example:

alg: 'EdDSA',
typ: 'JWT',
jwk: {
  kty: 'OKP',
  crv: 'Ed25519',
  x: 'HccjhsDiu7QNg_8ehFvTqroV5NTV1Cuk-TeMjn99tBY',
  kid: 'did:jlinx:h:did.jlinx.io:k-c_YNhjMkTtyPcCsfbks4VYRTQWyQfZf5XBhQQtsXU'
}

6.1.3 JWS payload

The JWS payload MUST include the JWT standard properties “iss” (issuer identified as a DID), “iat” (issuance date/time in ISO 8601 format), and “jti” (JWT ID - a unique ID, MAY be a UUID). Other JWT standard properties MAY be included.

Two non-standard properties MUST be included:

  1. an “action” property that instructs the recipient what action is intended by the agent.
    This value MUST be one of “register”, “update”, or “revoke”.
  2. a “diddoc” property containing the DID document to be registered, updated or revoked, in JSON format.

Example:

iss: 'did:jlinx:h:did.jlinx.io:k-c_YNhjMkTtyPcCsfbks4VYRTQWyQfZf5XBhQQtsXU',
iat: '2023-03-12T19:33:16.643Z',
jti: '542beb17-8646-4088-a673-aed748c26771',
action: 'register',
diddoc: '{...}'

6.1.4 JWS signature

The JWS signature MUST be created with the DID controller’s private key as represented in both the DID document and the header JWK. The recipient SHOULD verify that these are both the same corresponding public key, as well as of course that the signature is valid.

6.2. Resolution

For content-addressed schemes, for example IPFS, the idchar is all that is necessary for resolution.

In the case of the https scheme, the “h:” is transformed to “https://” and subsequent colons are replaced with “/” characters to form the GET request URL. The responding server MAY return the raw JSON object representing the DID document, in which case it should use the standard HTTP content-type header “application/json”.

The responding server MAY instead return a signed JWS object encapsulating the JSON formatted DID document, signed by the “well-known” key of the responding server. In this case, the JWS SHOULD be formatted as described in 6.1.2 and 6.1.3 above, but with the “action” property replaced with “status” which MUST be one of “valid”, “updated” or “revoked”, and the “iat” property SHOULD represent the date/time at which the current status was established. For the HTTP content-type header it is recommended to use “application/jose”.

6.3 Update

Updates may include key rotation and/or updates to the service section or other parameters. The method is the same as described in 6.1 except that the “action” value MUST be “update”. In the case of a key rotation event, the JWS MUST be signed with the “next” controller key.

6.4 Revoke

The revocation method is the same as described in 6.1 except that the “action” value MUST be “revoke”. In the case of an agent initiated action, the JWS MUST be signed with the “next” controller key.

7. Security Considerations

All private keys must be held via secure methods, in particular the controller private keys which are used to make updates to the DID document, and most particularly the “next” private key which is required in order to rotate the DID’s keys in the event of a security breach. It is recommended that, if possible, the “next” private key be held securely offline until use.

8. Privacy Considerations

In order to avoid cross-party correlation and subsequent breach of pseudonymity, it is recommended, use-case permitting, that a new pair-wise DID be created by each party for each relationship that they enter into using DIDs.