11 - Identities#
DIP: 0011 Title: Identities Author(s): Ivan Shumkov, Anton Suprunchuk, Samuel Westrich, Cofresi Special-Thanks: thephez Comments-Summary: No comments yet. Status: Proposed Type: Standard Created: 2020-09-30 License: MIT License Replaces: 5
Table of Contents#
Abstract#
DIP0005 introduced the concept of Blockchain Users. These Blockchain Users were to be implemented using special transactions that were mined into blocks on the Dash core chain. This approach had a number of pitfalls that will be discussed in this document. Further research in the last few years led to the development of Dash Platform which will be covered in further documentation. Dash Platform enables a distributed state to be in consensus thus facilitating the introduction of Identities. Identities encompass and expand on the idea of Blockchain Users while decoupling themselves from the names they are associated with. These names are attached to their Identity via the Dash Platform Name Service (DPNS) covered in DIP0012.
Motivation#
Cryptographic identities have long drawn substantial attention in the blockchain space. Various solutions and iterations have been proposed inside of Dash’s development circle over the years. In this document we propose a novel approach made possible due to the accompanying introduction of Dash Platform. Dash Platform will be the subject of multiple DIPs in addition to this one. In brief, Dash Platform consists of a collection of state data that is created and altered with state transitions using a practical byzantine fault tolerant consensus system. It also provides access to this state data with a decentralized HTTP API (DAPI) that is hosted on all masternodes.
There are multiple advantages to storing Identities on Dash Platform rather than having them directly in the core chain. The first and most obvious stems from the fact that miners decide what they include in core chain blocks. Miners could decide to exclude Identities arbitrarily or maliciously. Another disadvantage is that mining fees could be extremely variable. Registering an Identity would use more data than a standard transaction; if Dash blocks were full then the fees could be non-negligible and represent a barrier to entry into the system.
Another big advantage is that the life cycle of an Identity exists directly inside the Platform consensus. If this was not the case then it would be very difficult to ensure consensus between Identities and their actions on Platform documents. For example, if an Identity was disabled, but a state transition that the Identity had signed was submitted at roughly the same time.
The Blockchain Users document (DIP0005) aimed to lay out a foundational transformation of how end users would interact with one another. The underlying Blockchain User transactions represented a starting point for this interaction. Blockchain Users would have then been discoverable by querying their associated usernames. At a stark difference from DIP0005, Identities are decoupled from their associated usernames. Instead of registering an Identity with a username, the username is added to the Identity after it is created. A resolver called Dash Platform Name Service (DPNS) is then used to retrieve Identities by names. This approach leads to a much more robust system where names for Identities are contextual. For example an Identity can have a name for DashPay, an associated URL for their personalized website and a link to a social media website.
Prior Work#
Decentralized Identities#
Decentralized Identities have gained prominence in the blockchain space more recently. They represent a decentralized and verifiable digital identity. In theory they should be able to identify any subject such as a person, an organization, an electronic device or even concepts like a data model or an abstract entity. In our first iteration of Identities we will be more focused on when the Decentralized Identifier represents a singular person using our system and expand them over time with more and more use cases.
Messages emanating from Decentralized Identities must be verifiable. All messages created by the Identity must possess integrity, authentication and non repudiation, properties all achieved by using asymmetric keys to provide digital signatures. Keys are statically bound to an Identity during the Identity creation process. Additional keys can also be added via an update of the Identity. This is covered more in detail in the Keys section of this document.
In our system each Decentralized Identity will be associated with a pseudo-randomly generated 256-bit unique identifier. The exact specification of the generation of this unique identifier will be covered in an upcoming DIP. In brief we will use a verifiably random aggregate signature as a source of entropy to ensure uniqueness. This random beacon will guarantee the non-grindable nature of the unique identifiers (i.e the bits of the unique identifier should follow a random equiprobable distribution). This means that users cannot create other Identities that would alter the proof size when verifying an Identity.
In a decentralized environment with potentially byzantine actors, it is not enough to just return Decentralized Identities when they are queried; proofs must also be returned to ensure that the Decentralized Identity is already in consensus. Verifying such proofs is essential for clients. They guarantee that an attacker cannot forge an Identity or mimic a valid Identity. The verification of such proofs will be covered in a subsequent document that is focused on platform state proofs.
It is best practice to not show unique identifiers to end users and instead rely on DPNS as a resolver. However if a unique identifier must be displayed, it is recommended to display it in Base58. Advantages of doing this are twofold: Base58 is URL compatible and it is also less prone to spoofing.
Identity Life Cycle#
The life cycle of an Identity is built with multiple different underlying state transitions. However before an Identity can be created, a special transaction that transforms Dash into credits must take place. This transaction is called an “Asset Lock Transaction” and will be covered in a succeeding DIP. Identities spend credits for all transitions that are included in platform blocks. The Asset Lock Transaction is a way to fund the creation of the Identity while also leaving the Identity with enough credits to use in subsequent transitions.
Identities come into existence when an Identity Create Transition is successfully executed in consensus. The result of this state transition is the persistence of the Identity in the Platform State. At this point the Identity, alongside its credit balance and public keys, will be cryptographically verifiable.
Once an Identity has been created, it can sign state transitions. In addition to the more common document state transitions, Identities can also create transitions that register Data Contracts. At the time of writing of this DIP, Data Contracts are immutable and cannot be altered. Once a Data Contract has been validated and approved in consensus, Identities can create document state transitions based on the document types defined in the contract.
As of v1, Identities must own all Documents and Data Contracts that are created and updated by state transitions that they sign. Each document has an ownerId
field which corresponds to the Identity unique identifier.
Identities pay for the network cost of their transitions and resulting state changes using credits. There are two transitions that supply credits to Identities from Dash; the initial Identity Create Transition and the Identity TopUp Transition. The same Asset Lock Transactions that can fund Identity creations are used for topups. Applications should encourage end users to maintain a healthy balance of credits for their Identities.
As more applications come into existence, keys that are only used for a specific application, a group of applications (e.g., from a single developer) or to support a specific use-case can be added to an Identity. This is done using an Identity Update Transition. Identities can use this state transition to create and disable keys. This will be covered in depth in the keys section of this document.
If an Identity has become compromised, the only recourse for its owner is to deactivate it using an Identity Disable Transition. The transition that deactivates an Identity can be signed using keys disabled within a defined period of time after the key in question was disabled. This is because an attacker that gains control of a compromised Identity could immediately change the Identity keys. The real owner would then be left with only disabled keys. These disabled keys can only deactivate the Identity and not sign any other state transitions on behalf of the Identity. More complex recovery mechanisms for Identities will be the subject of a future DIP.
Identity Credits#
Each time an Identity performs a state transition, its credit balance will be updated by subtracting the network cost of the transition. When a state transition first arrives at a Dash Platform node, the node in question must first check the balance of the Identity and make sure the Identity has enough credits to pay for this transition. If the Identity does and the transition is valid and properly signed, then the node will broadcast the state transition to other nodes. All nodes must redo these verifications when receiving the state transitions. Each time a node proposes a block it must redo these verifications as well, as to not submit state transitions from Identities with an insufficient balance.
A future DIP will explain the Dash credit system in further detail.
Keys#
Dash Platform uses state transitions to update its state and all state transitions come from Identities that pay credits for these operations. These state transitions must be verifiable Dash Platform messages and hence must possess integrity, authentication and non-repudiation. To support this, Identities will hold asymmetric keys to provide digital signatures.
Identity authentication keys can be used for various reasons. Since all transitions on Dash Platform are signed by keys, it is easy to imagine that some of these transitions are mundane and could not result in loss of value, whereas some could result in heavy loss of value or reputation. Thus there is a need for a variety of security levels for authentication keys. Clients should use various degrees of required authentication to adequately protect the private keys they hold.
Identities can also register encryption and decryption keys. While these keys are essential for features used by contracts, they can also be used for direct messages between users or any other application need.
We can define the following levels of security and purpose for keys:
Purpose | Security Level | Examples | Worst Result if Compromised |
Authentication | Master | Managing Dash Identity. | Loss of Identity. |
Authentication | Critical | Exchange of assets (e.g., a property deed). | Loss of funds/assets. |
Authentication | High | Publishing a message on a social network.
Sending a contact request in Dashpay. |
Loss of reputation. Risk of inducing spam. |
Authentication | Medium | Routine background transitions for application metadata. | Loss of credits. Loss of anonymity. |
Encryption | Medium | Encryption of a DashPay encrypted extended public key. | Ability to decrypt private sent messages. Loss of privacy. |
Decryption | Medium | Decryption of a DashPay encrypted extended public key. | Ability to decrypt private received messages. Loss of privacy. |
The master authentication key is the sole key that can sign Identity updates or disable the Identity.
Clients should use different practices for allowing access to these keys. A key with a critical or master security level should always require a user to authenticate when signing a transition. A key with a high security level should be available as long as the user has authenticated at least once during a session, this can be at the beginning of the session. A key with a medium security level should not require user authentication but must require access to the device. Clients should make use of these different security levels to give an ideal experience to end users and only ask them to authenticate when appropriate.
Identities must be created with at least one authentication key in each security level. Keys can only be disabled if another valid key is enabled in the same security level. This can happen atomically in the same state transition. Contracts can define for each document type the minimal security level required for signing. Only keys of a higher security level can be used. If no such field is present then all keys except the medium security level keys can be used. Contracts are encouraged to use the security level the most appropriate for each document type.
Encryption Keys#
Encryption and decryption keys are not valid for document signing. A key’s purpose can be both for encryption and decryption simultaneously. While Identities must be registered with at least one authentication key in each security level, this is not the case for encryption and decryption keys. However, it is required that an Identity be registered and maintain at least one encryption key at a high security level and one decryption at a medium security level. Contracts that use encrypted fields should identify for each of these fields the key exchange protocol used, the hash function used in the key exchange and the encryption mechanism. Key exchange protocols could be such as elliptic curve Diffie-Hellman (ECDH) and if no key exchange protocol is set ECDH should be used as the default.
When encrypting a field that is intended to be decrypted by a recipient, the owner of the document should use the private key of one of his encryption keys and a public decryption key valid on the recipient’s Identity for the key exchange. On the recipient’s side, the private key of the referenced decryption key and the referenced sender’s encryption public key must be used.
At the last step of a Diffie-Hellman key exchange, in accordance with NIST specification, the x and y coordinates are hashed along with a nonce. This ensures non-reuse of keys. Non-reuse of shared encryption keys for Dash Platform is vital among various contracts with multiple applications and development teams. Data contracts should either have a field in the document type that provides this nonce or should use the contractId and the document type name for this nonce. If a Contract Document Type does not specify an encryption mechanism, the default should be :
Shared_Key = SHA256_2(x || y || contractId || UTF8(document_type_name))
It is important to use a hash function that is non-susceptible to key extension attacks. Double SHA256 and single SHA3 both are non-susceptible.
Using the contractId and the document type name will reuse keys but only in the selected relationship for a specific document type. This is fine if keys are properly used with a secure encryption mechanism as the number of document encryptions required for an attacker to break the shared encryption key is very high. While this number might decrease with more advanced research, it would still be orders of magnitude more than the number of documents that would be created in one document type.
It is recommended that encryption should use a secure variant of AES, either CBC, CTR or GCM mode, though specialized contracts might want to use other variants. AES-CBC on 256 bits should be the default if no encryption mode is provided in the contract.
Authentication keys can be queried in Dash Platform and doing so will return the Identity that owns the key. In order to achieve this feature and also to ensure non-repudiation among Identities, all authentication keys must be unique in Dash Platform. Having unique keys requires that all Identities registering keys must prove control over the key. This is to prevent an attack where an Identity would attempt to register a key while a second Identity would maliciously try to register the same key. The attacker would attempt to do this before the original user’s transition would have been added to a Platform block. His purpose would be to get his state transition to be executed first, thus preventing the first Identity from successfully registering the key.
Encryption and decryption keys are not guaranteed to be unique in Dash Platform. This is because there could be situations where having the same decryption or encryption keys among multiple Identities could be useful. Dash Platform does not support querying of encryption or decryption keys to resolve owner Identity.
Specification#
This section defines the Identity data model, the steps for signing transitions and the four Identity state transitions. Complementing this are validation rules and execution logic that together represent version 1 of the Identity protocol which is a part of Dash Platform Protocol.
There are different ways to represent data depending on specific use cases. Thus all definitions of data structures are described independent of any particular representations. Structures defined below are maps of properties which are name-value pairs. Abstract data types are used to describe property values. The details on how structures and data types are implemented are described in the representations section below.
Data Model#
In Dash Platform Protocol, the Identity Data Model is defined by Identity and Identity Public Key structures.
Identity#
The Identity Data Model represents the decentralized identifier entity in Dash Platform Protocol.
Properties#
protocolVersion
Identity protocol version.
Required
Must be an integer
Must be set to the current valid protocol version
id
256-bit unique identifier.
Required
Must be a byte array
Must have length of 32 bytes
publicKeys
A list of public keys associated with the Identity.
Required
Must be a list
Must contain Identity Public Keys
Must contain only unique items
Must have minimum length of 5
Must have maximum length of 4096
balance
Balance in Platform Credits.
Required
Must be an integer
Must be greater than or equal to 0
revision
Identity update revision is used for optimistic concurrency control. Incremented by one with each new update so that the update will fail if the underlying data is modified between reading and writing.
Required
Must be an integer
Must be greater than or equal to 0
isEnabled
A boolean flag that indicates if the Identity is enabled or disabled. A disabled Identity cannot be updated, used for state transition signing or any other operations.
Required
Must be a boolean
Identity Public Key#
The Identity Public Key represents the Identity public key entity in Dash Platform Protocol. This structure is used as a sub-model in the Identity and various state transitions described below.
Properties#
id
Identifier of public key for Identity. Used together with Identity ID to point to the exact key that was used for signing and other operations.
Required
Must be an integer
Must be greater than or equal to 0
Must be unique for the Identity public keys
type
Public key type.
Required
Must be an integer
Possible values
0 - EC Secp256k1
1 - BLS 12-381
purpose
Public key purpose.
Required
Must be an integer
Possible values
0 - Authentication
1 - Encryption
2 - Decryption
3 - Encryption and Decryption
level
Public key associated security level.
Required
Must be an integer
Possible values
0 - Master
1 - Critical
2 - High
3 - Medium
data
Raw public key.
Note: For authentication using a public key hash can provide security benefits if the key is a single-use key, like in payment addresses, but provides no benefit when a key is used multiple times over its lifespan. Since the keys associated with an Identity are intended to be used repeatedly over an extended period of time, a raw public key is used instead of a public key hash.
Required
Must be a byte array
Must have a length of
33 bytes for key type 0 (compressed format for EC Secp256k1 key)
48 bytes for key type 1 (BLS 12-381)
ownershipProof
The proof of ownership for this key. This proof of ownership must sign the owner’s Identity unique id.
Required
Must be a byte array
Must have a length of
65 bytes for key type 0 (compressed format for EC Secp256k1 key)
96 bytes for key type 1 (BLS 12-381)
disabledAt (optional)
Timestamp indicating that the key was disabled at a specified time. Although disabled keys cannot be updated, they can be used for signature verification and signing Identity Disable Transitions.
Must be an integer
Must be greater than or equal to 0
Must not be more than 5 minutes before or 5 minutes after the current platform chain block time at the moment of disabling
Signing of Transitions#
There are two types of state transition signing. The first type is used when the transfer of funds is involved, i.e. for registering a new Identity or topping up the balance of an existing one.
To sign such a state transition, the following steps are performed:
Set the signature field to be equal to null
Serialize the state transition into its binary form using CBOR; Canonical CBOR must be used in order to be able to produce a deterministic (predictable and immutable) result
Hash the binary from step 2
Sign the hash using the private key corresponding to the public key in the funding transaction. Signing the state transition with this private key ensures that the person registering the Identity owns the funds from the funding transaction
Insert the resulting signature into the signature of the state transition
The second type is used for state transitions that perform an update to the state of the Identity, i.e. updating the state transition itself by adding/disabling keys of the Identity. This type is also used for signing state transitions that change the platform state - i.e. document state transitions and Data Contracts.
The mechanism for the second type is largely the same as for the first type, with some differences. Such state transitions also have a signaturePublicKeyId alongside the signature itself, which points to a key of the Identity that was used to sign a state transition.
To sign this type of state transition, the following steps are performed:
Set the signature and signature public key id fields to be equal to null
Serialize state transition into its binary form using CBOR; Canonical CBOR must be used in order to be able to produce a deterministic (predictable and immutable) result
Hash the binary from step 2
Sign the hash using the private key corresponding to the public key from the Identity
Insert the resulting signature into the signature of the state transition
Set the public key id field to be equal to the id of the key that was used to sign the transition
State Transitions#
Identity Create Transition#
Identity creation requires two actions:
Creating an Asset Lock transaction on the core chain to pay for the Identity Create Transition fees and populate the Identity balance with Platform Credits
Broadcasting an Identity Create Transition that references the Asset Lock transaction on the platform chain
The Asset Lock output must include a public key hash that can be used to verify that the submitter of the Identity Create Transition is authorized to spend the output of the Asset Lock. The key used to create this hash must be an ECDSA key and should only be used once.
The Identity Create Transition should be submitted to Dash Platform once the Asset Lock transaction it references is finalized. The Identity Create Transition must reference the Asset Lock transaction outpoint (tx hash + output index) to be spent. This transition must include a signature by the single-use key used to create the public key hash found in the Asset Lock transaction. A raw public key is not explicitly included as it can be derived from the signature.
Fees for the Identity Create Transition are deducted from the Asset Lock output amount. The initial Identity balance will therefore be:
balance = (Asset Lock output amount) - (fees for the Identity Create Transition)
The Asset Lock transaction will be described in more detail in an Asset Lock DIP.
Properties#
protocolVersion
Identity protocol version.
Required
Must be an integer
Must be set to the current valid Identity protocol version
type
Type of state transition. Identity Create Transition is type 2.
Required
Must be an integer
Must have a value of 2
assetLockOutpoint
Asset Lock transaction outpoint.
Required
Must be a byte array
Must have a length of 36 bytes
The Asset Lock transaction must be finalized
An
OP_ASSET_LOCK
output must be present in the transactionThe output must be used only once
The output amount must be > ST fee + credits dust
publicKeys
A list of public keys associated with the Identity.
Required
Must be a list
Must contain Identity Public Keys
Must contain only unique items
Must have minimum length of 5
Must have maximum length of 4096
signature
Cryptographic signature of the state transition.
Required
Must be a byte array
Must have a length of 65 or 96 bytes
Must be created by the key corresponding to the public key hash in the
OP_ASSET_LOCK
of the Asset Lock Transaction specified in assetLockOutpoint
Execution#
This state transition creates an Identity as defined in the Data Model section. Values for the Identity’s properties are assigned as described in the table below:
Property name | Property value |
protocolVersion | protocolVersion from the state transition |
id | assetLockOutpoint from the state transition |
publicKeys | publicKeys from the state transition |
balance | Asset Lock output amount minus fees for the state transition |
revision | 0 |
isEnabled | true |
Identity Update Transition#
The Identity Update Transition allows users to update their public keys. This state transition must be signed with one of the Identity’s ECDSA public keys.
Properties#
protocolVersion
Identity protocol version.
Must be an integer
Must be set to the current valid Identity protocol version
type
Type of state transition. Identity Update Transition is type 4.
Required
Must be an integer
Must have value of 4
identityId
Unique identifier of the Identity to be updated.
Must be a byte array
Must have a length of 32 bytes
An Identity with the specified ID must exist and be enabled
revision
Identity Update revision number.
Must be an integer
Must be incremented by one with each update to the Identity
addPublicKeys (optional)
Public key(s) to add to the Identity.
Must be a list
Must contain Identity Public Keys
Must contain unique items
Must have minimum length of 1
Must have maximum length of N (N = 4096 - current keys count)
disablePublicKeys (optional)
Identity Public key ID(s) to disable for the Identity.
Must be a list
Must contain Identity Public Key IDs
Must be an integer
Must be greater than or equal to 0
Must exist and be enabled in the Identity being updated
Must contain unique items
Must have a minimum length of 1
Must have a maximum length of 4096
publicKeysDisabledAt (optional)
Timestamp when keys were disabled.
Must be an integer
Must be greater than or equal to 0
Required if and only if
disablePublicKeys
is presentMust not be more than 5 minutes before or 5 minutes after the current platform chain block time at the moment of disabling
signature
Cryptographic signature of the state transition.
Required
Must be a byte array
Must have a length of 65 bytes
Must be created by the key specified in
signaturePublicKeyId
signaturePublicKeyId
The ID of public key used to sign the state transition.
Required
Must be an integer
Must be greater than or equal to 0
Must exists in the specified Identity (
identityId
)
Execution#
This state transition updates the specified Identity (identityId
). Values for the Identity’s properties are updated as described in the table below:
Property name | Property value |
protocolVersion | protocolVersion from the state transition |
id | Remains unchanged |
publicKeys | Add new keys from the state transition's addPublicKeys
Disable the keys specified in disablePublicKeys:
|
balance | The current balance minus fees for the state transition |
revision | revision from the state transition |
isEnabled | Remains unchanged |
Identity Topup Transition#
The Identity Topup Transition is used to increase the Identity’s balance. Similar to the Identity Create Transition, the top up value comes from Dash in an Asset Lock transaction. Fees for this state transition are deducted from the top up amount in the same way as in the Identity Create Transition. Signature validation should be performed in the same way as in the Identity Create Transition.
Properties#
protocolVersion
Identity protocol version.
Must be an integer
Must be set to the current valid Identity protocol version
type
Type of state transition. Identity TopUp Transition is type 3.
Required
Must be an integer
Must have a value of 3
identityId
Unique identifier of the Identity to top up.
Must be a byte array
Must have a length of 32 bytes
Identity with the specified ID must exist and be enabled
assetLockOutpoint
Asset Lock transaction outpoint.
Required
Must be a byte array
Must have a length of 36 bytes
The Asset Lock transaction must be finalized
An
OP_ASSET_LOCK
output must be present in the transactionThe output must be used only once
The output amount must be > ST fee + credits dust
signature
Cryptographic signature of the state transition.
Required
Must be a byte array
Must have a length of 65 bytes
Must be created by the key corresponding to the public key hash in the
OP_ASSET_LOCK
of Asset Lock Transaction specified inassetLockOutpoint
Execution#
This state transition increases the specified Identity’s (identityId
) balance. Values for the Identity’s properties are updated as described in the table below:
Property name | Property value |
protocolVersion | Remains unchanged |
id | Remains unchanged |
publicKeys | Remains unchanged |
balance | The current balance amount plus the Asset Lock output amount minus fees for the state transition |
revision | Increased by one |
isEnabled | Remains unchanged |
Identity Disable Transition#
The Identity Disable Transition allows an Identity owner to permanently deactivate their Identity. Data previously signed by a disabled Identity can still be verified, but any new state transitions signed by the Identity will be considered invalid. This state transition must be signed by one of their currently enabled keys or a key disabled within the last ninety days. The age of disabled keys is calculated by comparing the key’s disable timestamp with the current time. This latter consideration is to prevent account hijacking attacks. For example, if an attacker obtains an Identity owner’s private key and disables the owner’s public key via the Identity Update Transition, the legitimate user can still disable the Identity with their old key. This can be used to remove the attacker’s ability to access the Identity and associated data.
Properties#
protocolVersion
Identity protocol version.
Must be an integer
Must be set to the current valid Identity protocol version
type
Type of state transitions. Identity Disable Transition is type 5.
Required
Must be an integer
Must have a value of 5
identityId
Unique identifier of the Identity to be disabled.
Must be a byte array
Must have a length of 32 bytes
The Identity with the specified ID must exist and be enabled
signature
Cryptographic signature of the state transition.
Required
Must be a byte array
Must have a length of 65 bytes
Must be created by the key specified in
signaturePublicKeyId
signaturePublicKeyId
The ID of public key used to sign the state transition.
Required
Must be an integer
Must be greater than or equal to 0
Must exist in the specified Identity (
identityId
)
Execution#
The state transition disables the specified Identity (identityId
). Values for the Identity’s properties are updated as described in the table below:
Property name | Property value |
protocolVersion | Remains unchanged |
id | Remains unchanged |
publicKeys | Remains unchanged |
balance | Remains unchanged |
revision | Increased by one |
isEnabled | false |
JSON Schema#
Dash Platform Protocol implementations use JSON Schema Draft 7 to define data structures. JSON Schema for each described structure may be found attached to this DIP:
Copyright#
Copyright (c) 2020 Dash Core Group, Inc. Licensed under the MIT License