Title: did:klayr Method Specification
Author: Aldo Suhartono Putra <aldhosutra@gmail.com>
Version: 2024.05.21
Version History:
- 2024.05.21: Changed to did:klayr
- 2023.08.29: Add incrementNonce
- 2023.08.27: Add Authorization Factors
- 2023.08.19: Initial release.
Last Modified: May 21, 2024
This document defines the syntax, data model, and operations for the did:klayr
Decentralized Identifier (DID) method, specifically for the Klayr Sidechain.
This specification is under active development at https://github.com/aldhosutra/klayr-did/blob/main/packages/klayr-did-module/did-method-spec.md.
Decentralized Identifiers (DIDs) [1] introduce a novel form of identifiers that facilitate verifiable, self-sovereign digital identity. This Klayr [2] DID method specification outlines a new DID method, namely did:klayr
, and details the on-chain store a of Klayr DIDs and their corresponding DID documents on a Klayr Application sidechain, including the brief sidechain module implementation. Furthermore, the specification provides guidelines for performing operations on Klayr DID documents.
It is essential to highlight that this specification adheres to the prerequisites specified in the DIDs specification presently published by the W3C Credentials Community Group.
Within the Klayr Blockchain ecosystem, Klayr Applications function as independent blockchains built using the Klayr SDK. Klayr Sidechains, on the other hand, are Klayr Applications connected to the Klayr Mainchain through the Klayr Interoperability protocol. These application chains consist of diverse modules responsible for executing distinct on-chain logic.
To enable did:klayr
functionality on a Klayr Sidechain, it is imperative to implement a dedicated Klayr DID Module within the Sidechain. This module incorporates a collection of transactions, methods, hooks, and endpoints, designed to manage a specific set of DID document properties for a given did:klayr
on a particular sidechain.
Detailed information regarding the module's implementation is elaborated in the DID Operations section provided below.
did:klayr
DIDs can take two forms:
did:klayr:<chainspace>:<namespace>:<unique-id>
did:klayr:<chainspace>:<unique-id>
The second form is a simplified version where the <namespace>
is automatically resolved to "address"
. Consequently, the <unique-id>
in the second form must adhere to the valid address format specified in LIP 0018 [3].
In that sense, all components of the primary Klayr DID syntax are essentially required. As a result, the first form will serve as the key to map the DID document on the on-chain stores.
did-klayr = "did:klayr:" method-specific-id
method-specific-id = chainspace [":" namespace] ":" unique-identifier
chainspace = 1*chainchar
namespace = *id-char
unique-identifier = *( *id-char ":" ) 1*id-char
id-char = ALPHA / DIGIT / "." / "-" / "_" / pct-encoded
chainchar = %x61-7A / DIGIT / "!" / "$" / "&" / "_"
pct-encoded = "%" HEXDIG HEXDIG
A DID that adopts the this Klayr DID method MUST commence with the prefix "did:klayr"
. The prefix string MUST be in lowercase.
The did:klayr
method-specific identifier (method-specific-id
) comprises three components: a required chainspace
, an optional namespace
, and a required unique-id
component.
- The
chainspace
is defined as a string that identifies a specific Klayr Application blockchain (e.g."enevti"
,"kruuu"
,"colecti"
) where the DID reference is stored. - The
namespace
is an alphanumeric string that identifies a distinct namespace managed by the application chain's name server module. These namespaces, (e.g.,"address"
,"pos"
,"nft"
,"token"
), indicate theunique-id
context whithin that specific chain. - The
unique-id
is mixed character string that uniquely identifies an identity managed by the application chain under the namespace defined by thenamespace
component.
If the namespace
is not provided, the DID module will automatically resolve the namespace
to "address"
. In such cases, the unique-id
must adhere to a valid address format.
did:klayr
DIDs may also be used in DID-URLs, based on RFC3986 [7]
klayr-did-url = klayr-did [path-abempty] [ "#" fragment ]
path-abempty = *( "/" segment )
segment = *pchar
segment-nz = 1*pchar
segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
fragment = *( pchar / "/" / "?" )
NOTE: did:klayr
does not support query
parts. The path and fragment parts are defined below.
A DID written to the Enevti Blockchain network "nft" namespace
:
did:klayr:enevti:nft:004e4556b3d8553e8962
A DID written to the Kruuu Blockchain network "address" namespace
:
did:klayr:kruuu:address:kly9gxy8ua2n5sj7eqvtp554hvce8m39sy39sjwzu
Above DID will point to the same DID Document as following DID:
did:klayr:kruuu:kly9gxy8ua2n5sj7eqvtp554hvce8m39sy39sjwzu
A DID written to the Kruuu Blockchain network "address" namespace with a encoded public key fragment:
did:klayr:kruuu:address:kly9gxy8ua2n5sj7eqvtp554hvce8m39sy39sjwzu#z6LSqc7Q3MgFLWD39rLg3ZmrWcyN2SyEyVrTFVhNjERyDFkE
The DID document for the did:klayr
method is obligated to conform strictly to the DID Core specifications [4]. This entails the inclusion of the essential DID document
properties, along with verificationMethod
, keyAgreement
, and service
properties.
Given that the Klayr blockchain operates using the Ed25519 signature scheme, the did:klayr
method exclusively supports public key and signing algorithms that are based on EdDSA signatures with the Ed25519 curve.
Klayr DID extends support to multiple controllers and/or keys with diverse Verification Relationship capabilities. The current implementation accommodates four types of verification relationships, namely authentication
, assertionMethod
, capabilityInvocation
, and keyAgreement
.
didDocumentSchema = {
"type": "object",
"required": [
"context",
"id",
"controller",
"verificationMethod",
"authentication",
"assertionMethod",
"capabilityInvocation",
"keyAgreement",
"service"
],
"properties": {
"context": {
"type": "array",
"fieldNumber": 1,
"items": {
"dataType": "string"
}
},
"id": {
"dataType": "string",
"fieldNumber": 2
},
"controller": {
"type": "array",
"fieldNumber": 3,
"items": {
"dataType": "string"
}
},
"verificationMethod": {
"type": "array",
"fieldNumber": 4,
"items": {
"type": "object",
"required": [
"id",
"type",
"controller",
"publicKeyMultibase"
],
"properties": {
"id": {
"dataType": "string",
"fieldNumber": 1
},
"type": {
"dataType": "string",
"fieldNumber": 2
},
"controller": {
"dataType": "string",
"fieldNumber": 3
},
"publicKeyMultibase": {
"dataType": "string",
"fieldNumber": 4
}
}
}
},
"authentication": {
"type": "array",
"fieldNumber": 5,
"items": {
"dataType": "string"
}
},
"assertionMethod": {
"type": "array",
"fieldNumber": 6,
"items": {
"dataType": "string"
}
},
"capabilityInvocation": {
"type": "array",
"fieldNumber": 7,
"items": {
"dataType": "string"
}
},
"keyAgreement": {
"type": "array",
"fieldNumber": 8,
"items": {
"type": "object",
"required": [
"id",
"type",
"controller",
"publicKeyMultibase"
],
"properties": {
"id": {
"dataType": "string",
"fieldNumber": 1
},
"type": {
"dataType": "string",
"fieldNumber": 2
},
"controller": {
"dataType": "string",
"fieldNumber": 3
},
"publicKeyMultibase": {
"dataType": "string",
"fieldNumber": 4
}
}
}
},
"service": {
"type": "array",
"fieldNumber": 9,
"items": {
"type": "object",
"required": [
"id",
"type",
"serviceEndpoint"
],
"properties": {
"id": {
"dataType": "string",
"fieldNumber": 1
},
"type": {
"dataType": "string",
"fieldNumber": 2
},
"serviceEndpoint": {
"dataType": "string",
"fieldNumber": 3
}
}
}
}
}
}
{
"@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:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2",
"controller": ["did:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2"],
"verificationMethod": [
{
"id": "did:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2#z6Mkrgb4BmwobDHr5SV1XwtfFFvJVqVRLnwYtbYFdVRPSACL",
"type": "Ed25519VerificationKey2020",
"controller": "did:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2",
"publicKeyMultibase": "z6Mkrgb4BmwobDHr5SV1XwtfFFvJVqVRLnwYtbYFdVRPSACL"
}
],
"authentication": [
"did:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2#z6Mkrgb4BmwobDHr5SV1XwtfFFvJVqVRLnwYtbYFdVRPSACL"
],
"assertionMethod": [
"did:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2#z6Mkrgb4BmwobDHr5SV1XwtfFFvJVqVRLnwYtbYFdVRPSACL"
],
"capabilityInvocation": [
"did:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2#z6Mkrgb4BmwobDHr5SV1XwtfFFvJVqVRLnwYtbYFdVRPSACL"
],
"keyAgreement": [
{
"id": "did:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2#z6LSdv2JvMoD2dEZDvSxmCJwUMr64ANGA2PWrcBQiiwj6ctE",
"type": "X25519KeyAgreementKey2020",
"controller": "did:klayr:kruuu:klyc9ccbzjt9tvh2h82a3jor3qwmwdhf2hwcuhge2",
"publicKeyMultibase": "z6LSdv2JvMoD2dEZDvSxmCJwUMr64ANGA2PWrcBQiiwj6ctE"
}
]
}
@context
: The serialized value of @context MUST be a JSON Array where the first item is the JSON Stringhttps://www.w3.org/ns/did/v1
and the subsequent items are serialized according to the JSON representation production rules.id
: A did:klayr DID, adhering to the format defined in this document.controller
: A list of fully qualified DID strings. This list contains one or more DIDs, and their verification relationships MUST be considered valid for this DID.verificationMethod
: A list of Verification Methods that define how to authenticate or authorize interactions with the DID subject or its delegatesauthentication
: A list of strings with key aliases or IDs. Keys with this relationship are restricted to be used solely for authentication purposes, indicating that they can convince the other party that they belong to the DID.assertionMethod
: A list of strings with key aliases or IDs. Keys with this relationship are employed for signing credentials during issuance.capabilityInvocation
: A list of strings with key aliases or IDs. These keys possess the ability to modify the DID Document, enabling the addition or removal of new keys, service endpoints, controllers, etc. If a DID has one or more such keys, it is said to "control" itself, signifying that it can modify its own DID Document.keyAgreement
: A list of objects with key aliases or IDs. These keys are used during secure communication to encrypt data for the DID.service
: A set of Service Endpoint maps. Services expressed in the DID document define the means of communication with the DID subject or associated entities.
id
: An URI string following thedid:klayr
syntax, appended by#<key-fingerprint>
. For example:did:klayr:kruuu:address:kly9gxy8ua2n5sj7eqvtp554hvce8m39sy39sjwzu#z6Mkrgb4BmwobDHr5SV1XwtfFFvJVqVRLnwYtbYFdVRPSACL
.controller
: A string with a fully qualified DID. The specified DID must exist.type
: A string indicating the type of verification methodpublicKeyMultibase
: A base58-encoded string adhering to the MULTIBASE [5] encoded public key.
Note: The Ed25519 verification method does not include publicKeyJwk
. For further details, refer to the EdDSA Cryptosuite v2020 specifications by the W3C Community Group [6].
id
: A string representing the ID of the service. The value of theid
property for a Service MUST be a URI conforming to RFC3986 [7]. A conforming producer MUST NOT produce multiple service entries with the same ID. Likewise, a conforming consumer MUST produce an error if it detects multiple service entries with the same ID. The ID can be in one of the following formats:<did-document-id>#<service-alias>
or#<service-alias>
.type
: A string indicating the service type. The service type and its associated properties SHOULD be registered in the DID Specification Registries [8]serviceEndpoint
: A string that adheres to the rules of RFC3986 [7] for URIs.
The operation of did:klayr
DID and their associated DID documents is facilitated through a dedicated Klayr SDK module, encompassing essential components according to LIP 0069 [9] specification, such as configuration settings, transaction handling, method integration, hooks, and endpoints. A comprehensive reference implementation of the Klayr DID Module is available for further examination and utilization.
Within the context of the Klayr Application blockchain, the execution of a Klayr DID operation mandates the payment of a blockchain transaction fee. The specific fee amount is contingent upon the byte length of the transaction, as well as the minimum fee configuration settings [10].
This transaction fee is denominated according to the specific configuration of the network. Consequently, operations involving the creation, updating, and deletion of DIDs necessitate the execution of corresponding transactions that incur these transaction fees.
Furthermore, a Klayr Application sidechain that implements Klayr DID Module needs to configure their chainspace
identifier in the Klayr DID module config.
Please be advised that the accounts utilized to send transactions are separate from the keys associated with the DID. As a result, the DID could have been created using one account, updated with another account, and removed with yet another account.
To account for this, several operation includes a signature
parameter, which indicates the key associated with the DID as the signer
, rather than the sender
. The payload being signed, in this case, consists of the encoded bytes of the parameter appended with the DID's nonce, ensuring a secure signature that is protected from replay attacks. To obtain the DID's nonce from another sidechain module, following getNonce
method can be utilized:
didMethod.getNonce(
context: MethodContext,
did: string,
) => nonce
Similarly, to get DID's nonce from external environment, a did_getNonce
endpoint can be invoked:
did_getNonce(did: string) => nonce
However, if the public key of the actual transaction sender
aligns with the signer
and/or target
in the DID operation transaction, and possesses valid verification methods and relationships in the DID document, the signature
parameter becomes unnecessary. This is because the sender is already authorized within the context of the transaction. Furthermore, there are four distinct scenario for authorized operations:
signature
is provided,signer
is the target's DID subject that havecapabilityInvocation
relationship with target's DID.signature
is provided,signer
is the target's DID controller that haveauthentication
relationship with signer's DID.sender
sends valid transaction with privateKey that havecapabilityInvocation
relationship with target's DID. In this case bothsigner
andsignature
field becomes unnecessary.sender
sends valid transaction withsigner
field which present in target's DID controller, that haveauthentication
relationship with signer's DID. In this casesignature
field becomes unnecessary.- target's DID controller is
sender
DID withaddress
namespace that haveauthentication
relationship available. In this case bothsigner
andsignature
field becomes unnecessary.
Nonetheless, there exists a distinct scenario for authorized deactivate
operations, where the authorized sender
or signer
must be the final controller of the designated target DID. Additionally, sender
or signer
must control the last key, if not, the target DID must have all its available keys removed.
Klayr sidechain modules and external tools can examine the specified AuthorizationFactors
's verification relationship through the provided authorize
method and/or endpoint. This flexibility empowers sidechain developers to craft custom solutions leveraging DID authorization for their specific use cases.
In this case, AuthorizationFactors
can be one of following: publicKey
, publicKeyMultibase
, privateKey
, privateKeyMultibase
, or the combination of challenge
and signature
.
The result of this method and/or endpoint, is an array of AuthorizationResult
that cointains specific properties. Result with at least one item indicate successful authorization. The properties are as follows:
type
: A string that shows relationship between publicKey's controller and the DID document. The value can be"subject"
, or"controller"
.did
: A string representing DID that have relationship with provided authorized keys.relationship
: A list of string that shows verification relationship between provided keys, and the DID document with abovetype
. The value can be"authentication"
,"assertionMethod"
,"capabilityInvocation"
, or"keyAgreement"
;
Following is provided authorize
method, tailored for on-chain usage:
didMethod.authorize(
context: MethodContext,
did: string,
factors: AuthorizationFactors,
) => AuthorizationResult[]
Furthermore, following is provided did_authorize
endpoint, that serves off-chain purposes:
did_authorize(did: string, factors: AuthorizationFactors) => AuthorizationResult[]
In addition, developers have the option to utilize the incrementNonce
method, allowing them to increase the nonce associated with the designated DID subject. This functionality is valuable in scenarios such as changing the nonce value following successful on-chain authorization, thereby mitigating the risk of replay attacks and enhance overall security.
didMethod.incrementNonce(
context: MethodContext,
did: string,
) => void
In order to create a Klayr DID, users must have the capability to initiate a transaction, necessitating the possession of a valid ed25519 private key. There are three distinct scenarios for creating a DID.
The first scenario involves creating a DID with any <namespace>
. To achieve this, users are required to submit a transaction [11] utilizing the did
as module name, and specify create
as the command name, incorporating the asset with the following schema:
createDIDSchema = {
"type": "object",
"required": [
"did",
"keys",
"controllers",
],
"properties": {
"did": {
"dataType": "string",
"fieldNumber": 1
},
"controllers": {
"fieldNumber": 2,
"type": "array",
"items": {
"dataType": "string"
}
},
"keys": {
"type": "array",
"fieldNumber": 3,
"items": {
"type": "object",
"required": ["publicKey", "relationship"],
"properties": {
"publicKey": {
"dataType": "bytes",
"fieldNumber": 1
},
"relationship": {
"type": "array",
"fieldNumber": 2,
"items": {
"dataType": "string",
},
},
},
},
},
}
}
The Klayr SDK provides an inter-module communication method
that facilitates interaction among different modules within the sidechain ecosystem. Specifically, external modules on the sidechain have the capability to invoke the create
method from the Klayr DID Module, utilizing the specified parameters as described above, to initiate the creation of a new Decentralized Identifier (DID).
didMethod.create(
context: MethodContext,
senderPublicKey: bytes,
did: string,
controllers: string[],
keys: { publicKey: bytes; relationship: string[] }[],
) => void
The final scenario involves the creation of a Klayr DID with the designated "address"
as <namespace>
. It is important to note that the "address"
DID cannot be created directly through create
commands or methods above. Instead, the "address"
DID will be automatically generated for any address that does not have an associated DID Document when that address send any transaction on the respective sidechain.
To achieve this functionality, the beforeCommandExecute
hook is employed, with additional autoCreateAddressDID
module configuration. Within the did
module, a validation process is performed by inspecting the chain state for the key "did:klayr:<chainspace>:address:<senderAddress>"
. In cases where the key does not exist, a new DID document is created, thereby ensuring seamless DID generation for the respective address during transaction execution. This behaviour can be changed by setting available module configuration mentioned above.
DIDs created through this scenario will inherently possess all the verification relationships supported by Klayr DID. This is due to the fact that by sending a transaction, the sender has already demonstrated their control over the associated address, thus establishing the necessary verification relationships.
The Klayr DID module employs an endpoint and a method to facilitate DID resolution and verification for both users and other sidechain modules.
Other sidechain modules can utilize the read
method to resolve and verify a DID, by providing the DID syntax outlined in this document as an argument to the method:
didMethod.read(
context: MethodContext,
did: string,
) => DIDDocument
Users can invoke the did_read()
endpoint to resolve and verify a DID by passing the DID syntax specified in this document as a parameter to the endpoint:
did_read(did: string) => DIDDocument
It is important to note that RPC configuration is necessary on the sidechain node to enable successful invocation of the endpoint.
Klayr DID Modules provides several commands and methods to facilitate Update DID operations.
This operation offers a mechanism to append a new keypair to the designated target DID, along with the specified verification relationships. Newly added keys will be controlled by target DID subject. Assets command schema can be defined as follows:
addKeysSchema = {
"type": "object",
"required": [
"target",
"keys",
"signer",
"signature",
],
"properties": {
"target": {
"dataType": "string",
"fieldNumber": 1
},
"keys": {
"type": "array",
"fieldNumber": 2,
"items": {
"type": "object",
"required": ["publicKey", "relationship"],
"properties": {
"publicKey": {
"dataType": "bytes",
"fieldNumber": 1
},
"relationship": {
"type": "array",
"fieldNumber": 2,
"items": {
"dataType": "string",
},
},
},
},
},
"signer": {
"dataType": "string",
"fieldNumber": 3
},
"signature": {
"dataType": "bytes",
"fieldNumber": 4
},
}
}
Similarly, addKeys
method can be invoked using above parameters:
didMethod.addkeys(
context: MethodContext,
senderPublicKey: bytes,
target: string,
keys: { publicKey: bytes; relationship: string[] }[],
signer: string,
signature: bytes,
) => void
This operation offers a mechanism to remove a keypair from the designated target DID, all verification methods associated with the key will also be removed. Assets command schema can be defined as follows:
removeKeysSchema = {
"type": "object",
"required": [
"target",
"publicKeys",
"signer",
"signature",
],
"properties": {
"target": {
"dataType": "string",
"fieldNumber": 1
},
"publicKeys": {
"fieldNumber": 2,
"type": "array",
"items": {
"dataType": "bytes"
}
},
"signer": {
"dataType": "string",
"fieldNumber": 3
},
"signature": {
"dataType": "bytes",
"fieldNumber": 4
},
}
}
Similarly, removeKeys
method can be invoked using above parameters:
didMethod.removeKeys(
context: MethodContext,
senderPublicKey: bytes,
target: string,
publicKeys: Buffer[],
signer: string,
signature: bytes,
) => void
This operation offers a mechanism to add a new controller to the designated target DID. Assets command schema can be defined as follows:
addControllersSchema = {
"type": "object",
"required": [
"target",
"controllers",
"signer",
"signature",
],
"properties": {
"target": {
"dataType": "string",
"fieldNumber": 1
},
"controllers": {
"fieldNumber": 2,
"type": "array",
"items": {
"dataType": "string"
}
},
"signer": {
"dataType": "string",
"fieldNumber": 3
},
"signature": {
"dataType": "bytes",
"fieldNumber": 4
},
}
}
Similarly, addControllers
method can be invoked using above parameters:
didMethod.addControllers(
context: MethodContext,
senderPublicKey: bytes,
target: string,
controllers: string[],
signer: string,
signature: bytes,
) => void
This operation offers a mechanism to remove a controller from the designated target DID. All keys and verification methods associated with the controllers will also be removed. Assets command schema can be defined as follows:
removeControllersSchema = {
"type": "object",
"required": [
"target",
"controllers",
"signer",
"signature",
],
"properties": {
"target": {
"dataType": "string",
"fieldNumber": 1
},
"controllers": {
"fieldNumber": 2,
"type": "array",
"items": {
"dataType": "string"
}
},
"signer": {
"dataType": "string",
"fieldNumber": 3
},
"signature": {
"dataType": "bytes",
"fieldNumber": 4
},
}
}
Similarly, removeControllers
method can be invoked using above parameters:
didMethod.removeControllers(
context: MethodContext,
senderPublicKey: bytes,
target: string,
controllers: string[],
signer: string,
signature: bytes,
) => void
Please be aware that if the specified controllers
set for removal represents the sole and final controllers, this command or method will result in an invalid transaction. This is because removing all controllers equates to deactivating the DID. In such cases, the executor can instead utilize the deactivate
command or method.
This operation offers a mechanism to add a new service endpoint entries to the designated target DID. Assets command schema can be defined as follows:
addServiceEndpointSchema = {
"type": "object",
"required": [
"target",
"endpoint",
"signer",
"signature",
],
"properties": {
"target": {
"dataType": "string",
"fieldNumber": 1
},
"endpoint": {
"type": "object",
"fieldNumber": 2,
"required": ["id", "type", "serviceEndpoint"],
"properties": {
"id": {
"dataType": "string",
"fieldNumber": 1,
},
"type": {
"dataType": "string",
"fieldNumber": 2,
},
"serviceEndpoint": {
"dataType": "string",
"fieldNumber": 3,
},
},
},
"signer": {
"dataType": "string",
"fieldNumber": 3
},
"signature": {
"dataType": "bytes",
"fieldNumber": 4
},
}
}
Similarly, addServiceEndpoint
method can be invoked using above parameters:
didMethod.addServiceEndpoint(
context: MethodContext,
senderPublicKey: bytes,
target: string,
endpoint: {
id: string;
type: string;
serviceEndpoint: string;
};
signer: string,
signature: bytes,
) => void
This operation offers a mechanism to remove a service endpoint from the designated target DID. Assets command schema can be defined as follows:
removeServiceEndpointSchema = {
"type": "object",
"required": [
"target",
"endpointId",
"signer",
"signature",
],
"properties": {
"target": {
"dataType": "string",
"fieldNumber": 1
},
"endpointId": {
"dataType": "string",
"fieldNumber": 2
},
"signer": {
"dataType": "string",
"fieldNumber": 3
},
"signature": {
"dataType": "bytes",
"fieldNumber": 4
},
}
}
Similarly, removeServiceEndpoint
method can be invoked using above parameters:
didMethod.removeServiceEndpoint(
context: MethodContext,
senderPublicKey: bytes,
target: string,
endpointId: string,
signer: string,
signature: bytes,
) => void
To deactivate a Klayr DID, it is sufficient to remove all controllers, verification methods, and verification relationships from the associated DID document, indicating that the DID is no longer active. In this scenario, no authentication method can be utilized to authenticate the holder's identity.
Furthermore, it is essential to understand that deactivating or deleting a Klayr DID results in the irreversible action of rendering the DID unusable. Once deactivated, the DID cannot be re-registered or reactivated again.
To deactivate a DID, transaction with as module name and deactivate
as the command name needs to be submitted, incorporating the asset with the following schema:
deactivateDIDSchema = {
"type": "object",
"required": [
"target",
"signer",
"signature",
],
"properties": {
"target": {
"dataType": "string",
"fieldNumber": 1
},
"signer": {
"dataType": "string",
"fieldNumber": 2
},
"signature": {
"dataType": "bytes",
"fieldNumber": 3
},
}
}
Similarly, deactivate
method can be invoked using above parameters:
didMethod.deactivate(
context: MethodContext,
senderPublicKey: bytes,
target: string,
signer: string,
signature: bytes,
) => void
The Klayr Decentralized Identifier (DID) method, known as did:klayr
, is designed specifically for Klayr Application sidechains. By default, these sidechains inherently ensure a secure chain state by utilizing a proof-of-stake
algorithm. Additionally, the Klayr platform allows for custom consensus algorithm implementations, providing flexibility and adaptability for different level of security attribute.
The Klayr SDK, which is based on L1 Lisk SDK, has been subject to a comprehensive external security audit, successfully validating its security measures. For all did:klayr
DIDs, the initial asset creation and subsequent updates are executed using Ed25519 keys, which are widely recognized as a robust and secure cryptographic mechanism.
Considering privacy concerns, a Decentralized Identifier (DID) can be regarded as pseudonymous. However, users should be aware that the implementation of this Klayr DID, being registered on-chain in a decentralized manner, is not entirely revocable. Additionally, it is essential to acknowledge that a DID document, once registered, can solely be modified by authorized controller as a part of privacy considerations. Hence, Klayr DID documents should be limited to verification methods and service endpoints, and should not store any personal information.
The reference implementation is available here: https://github.com/aldhosutra/klayr-did/blob/main/packages/klayr-did-module
[1] W3C Decentralized Identifiers (DIDs) v1.0, https://w3c.github.io/did-core/
[2] Klayr, https://klayr.xyz
[3] LIP 0018: Use long hash of public key for address and Base32 encoding for UI, https://github.com/KlayrHQ/lips/blob/main/proposals/lip-0018.md
[4] DID Core DID document Representation Specification, https://www.w3.org/TR/did-core/#representations
[5] EdDSA Cryptosuite v2020, https://www.w3.org/community/reports/credentials/CG-FINAL-di-eddsa-2020-20220724/
[5] The Multibase Data Format, IETF, https://datatracker.ietf.org/doc/html/draft-multiformats-multibase-03
[7] RFC3986 Uniform Resource Identifier (URI): Generic Syntax, IETF, https://www.rfc-editor.org/rfc/rfc3986
[8] DID Specification Registries. W3C, https://www.w3.org/TR/did-spec-registries/
[9] LIP 0048: Introduce Fee module, https://github.com/KlayrHQ/lips/blob/main/proposals/lip-0048.md
[10] LIP 0069: Update Klayr SDK modular blockchain architecture, https://github.com/KlayrHQ/lips/blob/main/proposals/lip-0069.md
[11] LIP 0068: Define new transaction schema, https://github.com/KlayrHQ/lips/blob/main/proposals/lip-0068.md