Tezos is an open-source blockchain protocol that has a formalized process for upgrades and uses a virtual machine language called Michelson, which is designed to support formal verification using proof assistants. It can be used for DID creation and management compatible with the issuance, storage, and verification of Verifiable Credentials, achieving a pragmatic balance across privacy, decentralization, and accessibility for general purpose use in Internet scale consumer and B2B applications.

Introduction

Problem statement

did-core specifies that DIDs are required to implement DID Resolution. As per the DID Decentralized Rubric, properties of a DID method may range from:

We seek to specify a DID method with pragmatic trade-offs across privacy, decentralization, and accessibility, suitable for use in Internet scale consumer and B2B applications. To accomplish this, the DID method resolves across tiered layers of data storage, each with different characteristics, but all at the ultimate control of the user.

In this document, we specify the syntax for Tezos DIDs, architecture of tiered resolution, and the four basic CRUD operations (create, read, update, deactivate) required by did-core. We also provide discussion on privacy implications, code snippets, and guidelines for implementers.

Why a Tezos DID Method?

For purposes of DID management, the relevant properties provided by the Tezos blockchain are:

Tezos Settlement Finality

Implementations of the Tezos blockchain exist across several instances, with the instance called mainnet concentrating economic incentives and therefore stability to ensure properties useful to DID management. The cost of a 51 percent attack on Tezos mainnet to disrupt these properties was approximately (USD) $1,000,000,000 at the time of writing (February 2021). This economic incentives-based security model has maintained the system's integrity over two years, since its launch on September 2018.

Design Criteria

Design criteria are the explicit goals that a project must achieve in order to be successful. The Design Criteria of the Tezos DID Method are the following:

Tezos DID Scheme

The namestring that shall identify this DID method is: tz. A DID that uses this method MUST begin with the prefix did:tz. As per the DID specification, this string MUST be in lowercase.

Syntax and Interpretation

The full Tezos DID scheme is defined by the following ABNF:


tezos-did   = "did:tz:" [ network ":" ] address
network     = 1*(lower-char / digit)
address     = prefix 33*33base58-char
prefix      = "tz1" / "tz2" / "tz3" / "KT1"
base58-char = "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"
lower-char  = %x61-7A  ; a-z
digit       = %x30-39  ; 0-9
			

All Tezos DIDs use base58 encoding for the address rule. base58 is an encoding scheme similar to base64, first used by Bitcoin, disallowing characters that may be misinterpreted by the human eye, specifically O (uppercase 'o'), 0 (the digit zero), I (uppercase 'i'), and l (lowercase 'L').

The network rule MAY be used to indicate which Tezos instance the DID references. If it is not present, then the instance is assumed to be mainnet. Other known test networks include dalphanet, carthage, and labnet. The number of test networks is expected to grow.

Note: registry for testnets?

What is the process for registering a new test network? Is there any existing registry of testnets, and how to access them? How can this be official and community-managed? Tezos User Group?

Note: account character length not documented

We assume the account portion is 36 bytes, 3 bytes for the prefix and 33 bytes for the suffix, but this is not known to be guaranteed at this time within the Tezos documentation.

Background on Tezos Addresses

Tezos addresses can exist as either accounts or smart contracts. Tezos accounts are generated from public keys. The three character prefix, tz1, tz2, or tz3, indicate which signature system and elliptic curve are used. The prefix of KT1 denotes a Tezos smart contract, which do not have an implied public-private key pair. (Note that this specification does not support the prefix btz1 used for blinded accounts.) Tezos supports three public key signature systems for its accounts, each with a different elliptic curve:

Prefix Curve Description
tz1 Ed25519 This is a public key signature system that uses Curve25519 with the EdDSA signature scheme and SHA-512. It is under consideration for inclusion in official NIST recommendations. Note that with EdDSA, it is not possible to recover the public key from a signature as is the case with ECDSA.
tz2 secp256k1 This curve is used in Bitcoin's public-key cryptography, and is defined in Standards for Efficient Cryptography (SEC). It is also used by Ethereum. In Tezos, this curve is used with ECDSA.
tz3 P-256 This is a NIST standard curve and one of the most widely used, also referred to as secp256r1 in IETF literature. It is currently supported in the Apple CryptoKit, Android KeyStore, and is widely used in TLS. In Tezos, this curve is used with ECDSA. The cryptography community has raised concerns around its use.
KT1 N/A Tezos smart contracts differ from Tezos accounts in that they are not directly associated with a public/private key pair at the protocol level.

Note: signature system not documented

While Ed25519 does specify the use of Curve25519 with SHA-512 and EdDSA, it is not currently specified in the Tezos documentation that secp256k1 or P-256 are necessarily used with ECDSA. This is just the implied case with existing implementations. The latter two are technically curves and not public key signature systems, as is the case with Ed25519. We should move to document signature systems for purposes of interoperability and fostering diversity in compliant Tezos shell implementations.

Note: account generation algorithm is undocumented

All known major Tezos implementations (e.g., pytez, Tezos shell, and TezEdge) use blake2b to hash the public key with a digest size of 20 bytes. This hash is then base58 encoded. While this methodology is canonical across implementations, it is not specified in the Tezos documentation as required. For example, use of the sha512 that is base58 encoded is a plausible representation as per the documentation alone. This is related to the note about variable account character length as a possible direct cause.

Note: btz1 "blinded" signatures are undocumented

There is scarce mention of btz1 "blinded" account prefixes other than a few loose strands of documentation and historical mentions from around 2018. It is assumed that they are not in active use today and therefore not relevant to this specification. We have an opportunity to document this and its historical significance to reduce future confusion.

Examples

did:tz:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8.

Architecture

The objective for the Tezos DID Method is to utilize Tezos accounts and smart contract addresses in a coherent manner to manage DID documents while adhering to this document's Design Criteria, including security, privacy, and simplicity. For simplicity, Tezos DIDs only support a single active public key and service endpoint at a time. In this section, we describe major architectural patterns utilized in its DID operations.

Tiered DID Resolution

DID resolution occurs sequentially across the following ordered layers of data sources, known as resolution layers:

  1. Implied DID Document.
  2. Corresponding on-chain smart contract known as a DID Manager.
  3. Corresponding off-chain DID document signed updates.

DID resolvers must move sequentially through all resolution layers to incrementally build a DID document, and they fail upon the first encountered inconsistency, producing an error result and no DID document. Success can only be achieved after processing all resolution layers.

Absence of data sources

The absence of a data source is not considered an inconsistency, and the resolver simply disregards the absent data source, moving on to the next data source in the sequence. An example of an inconsistency is a signed JSON patch that fails an integrity check or uses an unexpected key.

Tezos addresses: accounts vs. smart contracts

A Tezos address may represent either an account, beginning with tz1, tz2, or tz3, or a smart contract, beginning with KT1. When they populate the address ABNF rule in DIDs, they are known as account address-based DIDs and smart contract address-based DIDs, respectively.

Smart contracts do not come with implied key pairs, so their implied DID document is absent. Furthermore, they cannot have off-chain signed updates without deployment, as currently, smart contract addresses cannot be known prior to deployment. Therefore, smart contract address-based DIDs must always be deployed prior to use.

Implied DID Document

For Tezos account address-based DIDs with addresses starting with tz1, tz2, or tz3, DID document resolution is possible without committing any Tezos blockchain transactions to preserve privacy and save costs. Because all mainnet blockchain transactions are public, immutable, and fee-based, it is recommended to exercise extreme caution and store the absolute minimum amount of information on-chain.

Deriving DID Documents

At this resolution layer, DID document is derived by implying values from a Tezos account address-based DID, such as did:tz:mainnet:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8, which matches the account and optional network rules in the DID Scheme ABNF. This value is then used within the DID document authentication section as the blockchainAccountId as specified in the Security Vocab. A DID resolver could take the example DID and generate the following DID document without incorporating any data from blockchain transactions:

{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:tz:mainnet:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8",
  "authentication": [{
    "id": "did:tz:mainnet:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8#blockchainAccountId",
    "type": "Ed25519PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021",
    "controller": "did:tz:mainnet:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8",
    "blockchainAccountId": "tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8@tezos:mainnet"
  }]
}
				

However, the DID resolver must then check the live specified Tezos blockchain instance for a DID Manager, which is defined in the next section.

Note: undefined LD-Proof signature suites ("type") for tz1/tz2/tz3

This is related to the example entries found for blockchainAccountId. We need to define the type for use with Ed25519-based tz1 Tezos accounts. We should also consider inclusion of tezosAddress for the secp256k1/ECDSA-based tz2 into the EcdsaSecp256k1RecoverySignature LD-Proof signature suite. We still need to figure out how the P-256-based tz3 fits into existing signature suites, if any.

DID Manager Smart Contract

DID Managers are smart contracts on the Tezos blockchain that implement TZIP-19, with Michelson annotations satisfying the following abstract function interface:

rotateAuthentication :: (VerificationMethod, RotationSignature) => ()
getAuthentication :: () => VerificationMethod
rotateService :: (Service, RotationSignature) => ()
getService :: () => Service
			

rotateAuthentication updates the verification method used for authentication, such as a public key or public key digest along with its verification method type. It may be called by anyone, but requires a valid RotationSignature. This function is used by the update operation to modify the authentication property in a DID document.

rotateService updates the single service endpoint, which is a URI with a service endpoint type. It may be called by anyone, but requires a valid RotationSignature. This function is used by the update operation to modify the service property in a DID document.

The RotationSignature input parameter contains the signature of the data produced by concatenating the byte representations of the current value's message digest, next value, current chain identifier, and current rotation count. Including the chain identifier prevents impersonating the controller on a different chain. The current rotation count is defined as the sum total of successfully executed calls to both rotateAuthentication and rotateService to date. For example, if each function were successfully executed exactly once, the current rotation count would be two.

getAuthentication returns the verification method for authentication. This result is used to populate the authentication section in the DID document during resolution.

getService returns the single service endpoint. This result is used to populate the service section in the DID document during resolution.

Identifying the DID Manager

The process for reliably identifying the corresponding DID Manager will differ between account address-based DIDs and smart contract address-based DIDs. In both cases, the address is first extracted from the DID using the address ABNF rule.

Account address-based DIDs: In the case of an account address, the DID Manager smart contract is defined as the first smart contract that (1) is deployed by the account and (2) implements TZIP-19. The resolver must exhaustively query for any matching smart contract by either by (recommended) using a Tezos transaction indexer or scanning all Tezos transactions directly.

Smart contract address-based DIDs: In the case of a smart contract address, the smart contract itself is the DID Manager, and must therefore implement TZIP-19. If it does not implement TZIP-19, then resolution will fail.

Deriving DID Documents

The verification method used for authentication is produced by calling the getAuthentication smart contract function. No input parameters are required. The single service endpoint and its type is retrieved by calling the getService smart contract function. These values are the only smart contract-sourced data used for Tezos DID resolution, and are substituted into a valid DID document.

{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:tz:mainnet:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8",
  "authentication": [{
    "id": "did:tz:mainnet:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8#blockchainAccountId",
    "type": "Ed25519PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021",
    "controller": "did:tz:mainnet:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8",
    "blockchainAccountId": "tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8@tezos:mainnet"
  }],
  "service": [{
    "id": "did:tz:mainnet:tz1TzrmTBSuiVHV2VfMnGRMYvTEPCP42oSM8#discovery",
    "type": "TezosDiscoveryService",
    "serviceEndpoint": "tezos-storage://KT1QDFEu8JijYbsJqzoXq7mKvfaQQamHD1kX/listing"
  }]
}
				

Off-Chain DID Document Updates

Off-chain updates to the DID document are possible by specifying one or more signed patches in the DID resolution input metadata property named updates containing an array. If updates are present, they must all be of the same type.

The two allowed types for updates are (1) unsigned Tezos transactions with valid RotationSignature parameter values that would correctly update the DID Manager if signed and cleared in a block and (2) signed-ietf-json-patch restricted to changes possible through the DID Manager abstract function interface. These two types of updates have different privacy and security implications.

Unsigned Tezos transaction updates

signed-ietf-json-patch updates

Operations

This section is a WIP, please refrain from commenting until this message is gone.

Create (Register)

Tiered creation across DID resolution layers:

  1. DID document is implied
  2. Deploy DID manager smart contract
  3. Create off-chain DID document updates

Read (Resolve)

Tiered resolution across DID resolution layers:

  1. Imply DID document from address
  2. Lookup and apply on-chain DID manager
  3. Apply any off-chain DID document updates

Update (Replace)

Tiered replace across DID resolution layers:

On-chain DID manager

  1. Lookup on-chain DID manager
  2. Create rotation event
  3. Ask for the user's signature
  4. Apply the rotation by calling the appropriate entrypoint of the DID manager

Off-chain DID document updates

Apply any off-chain DID document updates.

Delete (Deactivate)

The Tezos DID manager contract can be updated to remove services and verification methods. Although inactive in DID resolution, these data would live on the blockchain indefinitely due to its append-only nature.

On-chain DID manager

Update the DID manager with empty verification methods and services.

Off-chain DID document updates

Null rotation

Security & Privacy

Security Considerations

Eavesdropping

All exchanged data is public, except for off-chain rotations, which will conform to the unspecified underlying architecture and its modes of communications.

Replay

All signed rotation events contain the chain ID, so an attacker is unable to deploy and replay the DID manager on a different chain.

Message Insertion

Rotation events are signed. However, if using the unsigned transaction option with pre-signed rotation events, anyone may submit the updates to the Tezos blockchain if they receive access to the rotation events. This behavior can be eliminated by using signed JSON patches instead of unsigned transactions, which have use cases such as desired transaction submission by a third party without key sharing or multisig.

Deletion

With the lack of real deletion, it means that the history of rotations (and thus previous verification methods and services) will stay public on the blockchain.

Modification

Similarly to the deletion, as the DID manager resides on a blockchain, it means that previous rotations will be forever public.

Man-in-the-Middle

When a third party creates or update the DID manager, the event has to have a valid signature, meaning the user is in control of any change. However, if an attacker obtains an uncleared valid transaction with a signed rotation event, the third party can choose the timing of the transaction submission.

Denial of Service

The only remote request made during DID resolution is the DID management interactions, and as it is a smart contract it benefits from the Tezos blockchain's guarantees of consistency and availability. If Tezos nodes and indexing services are compromised, so will be this DID method. Furthermore, if using unsigned transactions with valid rotation event signatures, it is possible for an attacker who obtains these transactions to clear them to the Tezos blockchain even if the original DID controller wished to pursue an alternate rotation history.

Residual Risks

The system's overall security and integrity can only as good as the DID controller's key management ability, which is known to be a hard problem for enterprises and especially individuals.

Privacy Considerations

The DID method specification's Privacy Considerations section MUST discuss any subsection of section 5 of [RFC6973] that could apply in a method-specific manner. The subsections to consider are: surveillance, stored data compromise, unsolicited traffic, misattribution, correlation, identification, secondary use, disclosure, exclusion.

Surveillance

Surveillance may be possible through a combination of compromised Tezos full nodes and indexer services supporting TZIP-19 resolution. This may be mitigated by choosing full nodes and indexer services that are trusted or self-hosted.

Stored data compromise

All stored data in the DID manager is considered public (at the time of rotation). Stored data in the off-chain rotation events are subject to the underlying system architectures and constraints, which are not specified in this document.

Unsolicited traffic

It is possible that DID controllers populate a service endpoint in a smart contract containing a service not desired to be publicized by its owner. It is also possible that populating a service endpoint causes unsolicited traffic from unintended parties due to its public nature and ability to be indexed and explored on a block explorer.

Misattribution

For the resolution and updates with respect to the DID Document itself, there is very little risk of attributing activity to the wrong key pair due to the cryptographic requirements for authentication and authorization of rotations.

Correlation

The DID could be correlated to on-chain Tezos activity and other activity such as the issuance, presentation, storage, and verification of Verifiable Credentials if an attacker has access to those data. It is therefore important for DID users to carefully consider what the use cases of their DID. It may be beneficial for users to generate new Tezos DIDs as frequently as per transaction if wallets support this direction such as by using hierarchical deterministic (HD) wallet algorithms.

Identification

The user could add a service that would link to another of their identities.

Secondary use

Disclosure

Exclusion

Reference Implementations

github.com/spruceid/did-tezos

Resources