Getting Started with IOTA Identity

IOTA Identity is an open-source, permissionless, free-to-use protocol, explore its functionality and systems with a step-by-step technical guide.

Getting Started with IOTA Identity

by Pascal Gottret

Introduction

After reading the first few articles from the Tangle Labs Blog, you should now have a good idea of what SSI (self-sovereign identity) is, how it can help to solve the problems of the “Web2” world, and some of the use cases where SSI can provide novel solutions. In this article, we will explain the technical details of how SSI and its elements work. We will also discuss how to get started with the technology using the IOTA Identity Protocol (a framework built by the IOTA Foundation).

As described in the introduction to SSI, SSI is about shifting control of data from a central organisation and verifier to the identity subject (i.e., an entity, a person, organisation, or object for whom the identity is created). They (the subject) can then control how their data is shared and used. Achieving this crucial step towards privacy requires accurate application of the basic building blocks of SSI. These blocks include verifiable data registries (VDR), the trust triangle (issuer, holder, and verifier), digital wallets and agents, decentralised identifiers (DIDs), verifiable credentials (VCs), and the governance framework. While the trust triangle, wallets, and governance framework are already covered in other articles, this article focuses on the technical explanation and application of the VDR, DIDs, and VCs.

Explaining VDR, DIDs and VCs

The verifiable data registry and introduction to the IOTA DLT

For an SSI ecosystem involving different actors communicating with one another, it is crucial to have a common public storage location to retrieve important information about identities. In SSI terms, a public storage is called a verifiable data registry (VDR).

There are several ways to set up a VDR. For instance, you can build a conventional database or you may use a distributed ledger technology (DLT) implementation such as a blockchain or the IOTA Tangle. The latter refers to a:

"...distributed network of participants that replicate, share, and synchronize digital data and value spread across many different locations. Unlike with a centralized database, there is no central administrator."
- Permissionless Innovation - How to enhance your business with IOTA, 2022

One of the emerging DLTs, although not a classical blockchain, is the IOTA protocol. It uses a different technical basis, called a directed acyclic graph (DAG), that allows parallel processing of transactions. Its main goal is to provide a generally usable, scalable, interoperable and energy-efficient network, with its main difference compared to classical blockchain protocols is the absence of miners and thus third-party validators collecting transaction fees. IOTA is a secure permissionless network which allows users to make data transfers as well as value transfers. In the context of SSI, this allows you to write identities on the public ledger without using tokens.

Preukschat and Reed (2021) evaluated the possibility of using DLT towards achieving SSI as follows: DLT solves “a problem that has never had a solution in the history of cryptography: how a globally distributed database can serve as a source of truth for public keys without being subject to single points of failure or attack.”

The permissionless, feeless and secure nature of the IOTA protocol is a perfect fit for a VDR to store decentralized identifiers (DID) in a secure and tamper-proof manner on the ledger without relying on a central trusted authority.

Decentralized identifiers

A Decentralized Identifier (DID) is basically a new type of a globally unique identifier. You can compare it to the URL we use when browsing on the internet, e.g, https://tanglelabs.io. Each actor - people, organizations, things - in the SSI ecosystem will have its own DID. This DID is a text string containing the scheme, the DID method (resolving to the VDR; for example, IOTA in our example below), and a unique string within that method.

Figure 2 Example of a decentralized identifier on IOTA

A DID always includes a public and private key. While the public keys of a DID, which signs credentials is stored on the VDR (i.e. the IOTA DLT), the private key is stored in the holder’s wallet. With this combination, the holder – and only the holder – is able to cryptographically prove that they are the controller of the DID. The identifier is strongly tied to them.

Figure 3: an example how the DID controls the private and public key

So far we have learned that the DID is a unique identifier, but how can other parties use, or “resolve” in SSI-terms, this identifier? How can the verifier obtain the issuer's public key to verify the issuer's signature and what proof does the verifier have that the public key belongs to the issuer?

To achieve this, each DID controls one signed DID document and publishes it to the VDR, proving that the DID is in control of the public key. This is where the VC completes a full circle: the public key is strongly bound to the identifier. The verifier (verifying a particular credential) resolves the issuer’s DID document on the VDR, receives information about the public key and the verification method, and is able to cryptographically verify the signature in the VC.

did:iota:GYmbp6c5G77NhGSJJ5byNUj62nQEuGHAzQ2ikSGMr1jD
{
  "doc": {
    "id": "did:iota:GYmbp6c5G77NhGSJJ5byNUj62nQEuGHAzQ2ikSGMr1jD",
    "capabilityInvocation": [
      {
        "id": "did:iota:GYmbp6c5G77NhGSJJ5byNUj62nQEuGHAzQ2ikSGMr1jD#sign-0",
        "controller": "did:iota:GYmbp6c5G77NhGSJJ5byNUj62nQEuGHAzQ2ikSGMr1jD",
        "type": "Ed25519VerificationKey2018",
        "publicKeyMultibase": "zAs84e72rbkhdCtAgLGsqEVSq3Kv7dYzjAwmhBRcdi6KS"
      }
    ]
  },
  "meta": {
    "created": "2022-04-05T19:52:52Z",
    "updated": "2022-04-05T19:52:52Z"
  }
}

Compared with other unique identifiers, such as DNS, DIDs come with four core properties that set them apart:

  1. A DID is a permanent identifier
  2. A DID is publicly resolvable
  3. A DID is cryptographically verifiable (proof of control using cryptography)
  4. A DID is decentralized (no central registry is required)

People might mistakenly think that DIDs have the same functionality as traditional Public Key Infrastructure (PKI) solutions. Upon closer inspection, you will see that the four core principles listed above matter a lot in fully trusted environments. While traditional PKI-solutions rely on trusted third parties (TTP) and central authorities (CA), such as X.509 certs, DIDs do not. To ensure that the counterpart is trustworthy, DIDs solve two core problems:

  1. How do you strongly bind the identifier to the controller of the identity?
  2. How do you strongly bind the public key to the identifier?

In other words, DID enables a trusted environment without the need for third-party intervention.

A further advantage of DID is the possibility to update the public key in the DID Document by uploading the new version of the DID Document (to the VDR) and signing it with the former private key. Changing public keys is a strong method for enhanced security. especially in the event of data breaches.

Verifiable credentials

As explained in the introduction article, credentials are a set of claims about the DID subject of the credential and, in terms of SSI, are issued in in form of a verifiable credential (VC) that is cryptographically signed by its issuer. Digital credentials are intended to provide information about who issued the credential, whether it contains the data required by the verifier, whether it has been tampered with, and whether it is still valid.

As of today, there are primarily four data formats for verifiable credentials (VC):

  • JSON Web Token (JWT)
  • JSON-LD with LD-Signatures
  • Zero Knowledge Proofs (ZKP) with Camenisch-Lysyanskaya Signatures (ZKP-CL)
  • JSON-LD ZKP with BBS+ Signatures

Each of these formats comes with advantages and disadvantages regarding:

  • Simplicity: Programming and readability.
  • Selective disclosure: is the holder able to prove only parts of a VC or do they have to reveal the full VC?
  • ZKP: A method used in cryptography to prove that something is known without directly revealing the known information. ZKPs are indirect evidence that can be used to prove that you know a secret without ever revealing the secret to another person.
  • Reveal persistent identifier: Necessity to include the identifier of the holder (DID) in order to prove the legitimacy of the VC.
  • Semantic disambiguation: is the VC semantically interpretable?

Characteristics

JSON Web Token (JWT)

JSON-LD

ZKP-CL

JSON-LD ZKP with BBS+

Simplicity

Simplest among all

Relatively simple

Most complicated among all

Complicated

Privacy Preserving

No

No

Yes

Yes

Selective Disclosure

No

No

Yes

Yes

Zero-Knowledge-Proof

No

No

Yes

Not yet

Need to reveal persistent identifier

Yes

Yes

No

No

Semantic Disambiguation

No

Yes

No

Yes

Figure 4: Comparison table for current formats of Verifiable Credential.

Privacy preservation is what SSI aims to achieve. VC formats with support of ZKP are able to prove a set of claims without disclosing its actual content. Each claim gets its own cryptographic signature. On the other hand, VC formats without support of ZKP do not hide its content and the cryptographic signature signs the full VC.

Does this mean that only VC with ZKP support shall be applied, since the other formats do not support privacy sufficiently? No, not necessarily. There are situations where legal frameworks require an audit trail of credentials used, such as in the finance sector with “Know Your Customer”.

Currently, the IOTA Identity Protocol supports JSON-LD. With ZKP-CL and JSON-LD with BBS+ signatures under research and prototyping.

Example of a verification process

Let’s look at an example of how the procedure of verifying a credential might look like. Imagine you are applying for a new apartment and the landlord requires the tenant to have a regular income. Therefore, you need to provide a certificate of employment from your employer. Using SSI (DIDs and VC), the procedure is as follows:

  1. You create a new identity (DID) in your digital wallet (on your cell phone) and store the DID document on the IOTA ledger.
  2. You establish an encrypted peer-to-peer connection with your employer, who in turn has stored his own DID in a public ledger.
  3. The employer creates a VC for your DID (specifying that you indeed work at that particular company) and signs it with her private key, and your mobile wallet safely stores the credential inside it.
  4. You want to show the credential to the landlord, who is the verifier of your credential. You first create an encrypted peer-to-peer connection with him. Afterwards, your mobile wallet creates a VP with the necessary information. The VP is signed by your private key and presented to the verifier.
  5. Your landlord scans the credential. His mobile wallet first checks the signature of the VP to make sure that you are the holder of the DID. He then reads the DID of the issuer (i.e., your employer) and resolves its DID Document. His wallet is now able to verify that the credential contains the necessary information and that the signature is valid, by looking up the issuer’s public key and verification method.
  6. Because the verifier has a proof of integrity of the credential, meaning he can know for sure that the credential is genuine, you can now sign the rental agreement – and you are the legitimate tenant for the apartment. No need to mention that this comes with a VC from the landlord to your mobile wallet!

Revoking a VC

A credential might need to be revoked for various reasons: the credentials might be expiring, certain VCs might have been issued in error, or for any other reason that an issuer sees fit. Therefore, it is necessary to include functionalities in the SSI framework that allows the verifier to verify a revocation without having to contact the issuer.

There are several ways to accomplish this goal (cryptographic accumulators, revocation list, credential status, etc.). One way to revoke a VC is to change the verification method (public key) within the DID document. If the issuer’s public key has been changed, the verifier will no longer be able to verify the VC’s signature, indicating to the verifier that the credential is no longer valid.

How to use IOTA Identity

Now that you have a technical overview of how VDR, DIDs, and VCs are connected, let's see how we can use this technology atop the IOTA distributed ledger. To do this, we'll use the IOTA identity protocol. First, we have to install all prerequisites on our computer. Next, we create our own identity using pre-made examples, resolve it in the IOTA ledger, and make an update. Finally, we can create a VC.

Preparation

In order to use the IOTA Identity framework, we need a machine running on Windows, Linus or MacOS – the following process is explained assuming we’re operating on a Linux machine.

The IOTA Identity framework is available on Github at https://github.com/iotaledger/identity.rs (v. 0.5). There are two ways to install and use it: Either with the programming language RUST or with the built-in WASM bindings, which allows us to run all the commands in JavaScript.

In the repository, an encrypted storage called IOTA Stronghold is included. In a real world case, a secure key storage solution is important to support the safe storage of your keys. You can learn more about the IOTA stronghold here https://blog.iota.org/iota-stronghold-6ce55d311d7c/. In this guide we want to include the opportunity to include the secure storage in our examples.

Please follow the instructions after having connected to your machine:

  1. If not installed already, install git:
sudo apt-get install git

2. Navigate to the folder where you want to install the IOTA Identity repository. In our case, we use

cd /var/lib/

3. Install the IOTA Identity framework

sudo git clone https://github.com/iotaledger/identity.rs


For RUST installation, continue here. For WASM please jump to step 7.

4. Install Rust and Cargo: run

sudo curl https://sh.rustup.rs -sSf | sh 

this install might take some time, for further information, visit https://www.rust-lang.org/tools/install.

5. Go into the identity.rs folder

cd identity.rs

6. Build the cargo

cargo build

to download all dependencies please ensure you have the necessary authorizations; if you get a “permission denied” error, go back to /var/lib/ and execute

sudo chmod 777 identity.rs

WASM binding (JavaScript)

7. Do not forget to update your existing packages.

sudo apt-get update

8. In some cases, fixes are needed.

sudo apt --fix-broken install

9. Install Node.js and npm. Make sure that at least v. 16.0.0. is installed. Visit https://github.com/nodesource/distributions/blob/master/README.md for further instructions on how to update Node.js.

sudo apt install nodejs
sudo apt install npm

10. Install the libraries for WASM and Stronghold.

npm install @iota/identity-wasm
npm install @iota/identity-stronghold-nodejs

11. Go into folder bindings/wasm/

cd bindings/wasm/

12. Install the necessary dependencies.

npm install

13. Build the bindings for node.js.

npm run build:nodejs

14. In the folder /examples/src replace

@iota/identity-wasm

imports with

@iota/identity-wasm/node

for Node.js.

You are now ready to work with the IOTA Identity framework.

Creating a DID (without safely storing the private key)

Now that you have installed all the prerequisites, you will be able to create your own identity.

In Shell, run (RUST)

cargo run --example create_did

or (JavaScript)

npm run example:node -- create_did

Further dependencies might be necessary and will be downloaded and compiled automatically. After a while, you should see your DID Document. The output looks like the example shown below.

DID Document Transaction: https://explorer.iota.org/mainnet/message/d26cbf4e298a521e97eae1ecb195cf8fc43ed0d0eeb9763dcebea5c187e88d27

Explore the DID Document: https://explorer.iota.org/mainnet/identity-resolver/did:iota:9zZZvvMaRXK2dKXxCi2BKnqCpBKE5hS8UK8eAZEKJQui

Ok > {
	key: {
		type: 'ed25519',
		public: '9a1Mmkqav6ePZMb1WdAxgBCNBdAZx1srXorhMBMhd9FE',
		private: '...'
		 },
	doc: {
		doc: {
			id: 'did:iota:9zZZvvMaRXK2dKXxCi2BKnqCpBKE5hS8UK8eAZEKJQui',
			capabilityInvocation: [Array]
		 },
	meta: {
		created: '2022-04-05T20:24:02Z',
		updated: '2022-04-05T20:24:02Z',
	proof: [Object]
		  }
},
receipt: {
	network: 'main',
	messageId: 	'd26cbf4e298a521e97eae1ecb195cf8fc43ed0d0eeb9763dcebea5c187e88d27',
	networkId: 1454675179895816200,
	nonce: 2236363
	}
}

Congratulations! You have successfully created your first identity.

This action generates your public and private keys.

Creating DID (with safely storing the private key)

In the folder

bindings/stronghold-nodejs

create a new file

create_did.js

and paste the following code (replacing the password):

const { AccountBuilder, ExplorerUrl } = require('@iota/identity-wasm/node')
const { Stronghold } = require('@iota/identity-stronghold-nodejs')

async function main() {

	// Stronghold settings for the Account storage.
	// This will load an existing Stronghold or create a new one 	automatically.
	const filepath = "./example-strong.hodl";
	const password = "my-password";
	const stronghold = await Stronghold.build(filepath, password);

	// This generates a new keypair stored securely in the above Stronghold,
	// constructs a new DID Document, and publishes it to the IOTA Mainnet.
	let builder = new AccountBuilder({
	storage: stronghold,
	});
	let account = await builder.createIdentity();

	// Print the DID of the newly created identity.
	const did = account.did();
	console.log(did.toString());

	// Print the local state of the DID Document.
	const document = account.document();
	console.log(JSON.stringify(document, null, 2));

	// Print the Explorer URL for the DID.
	console.log(`Explorer URL:`, ExplorerUrl.mainnet().resolverUrl(did));
}
main()

Now run the command

sudo node create_did.js

Your DID will be created and the private key safely secured in the file

example-strong.hodl


Resolving a DID

In order to resolve a DID, run (RUST)

cargo run --example resolve

or (JavaScript)

npm run example:node -- resolution

Please note that this example first creates a new DID document, which is then resolved. To use the same DID you first created, edit the example above to safely store your keys and retrieve them to resolve a DID.

Updating DID

In order to update DID, run (RUST)

cargo run --example manipulate_did

or (JavaScript)

npm run example:node -- manipulate_did

Again, change the examples to reuse your DID accordingly.

Create a VC

This example includes a University Degree credential in JSON format. Feel free to change it in any other form of credential.

In order to create a VC, run (RUST)

cargo run --example create_vc

or (JavaScript)

npm run example:node -- create_vc

Again, change the examples to reuse your DID accordingly.

Conclusion

A demonstration of the easily accessible nature of Identity, this article has highlighted, from a technical perspective, how the key elements of an SSI ecosystem (VDR, VC and DID) can function and interact with each other, using the IOTA Identity Protocol. Illustrating the accessible nature of the open technology, through just a few easy-to-follow steps it is available for anyone, anywhere to integrate and use in their developments. This simplicity and free use of open-source solutions such as IOTA Identity provides a solid foundation for a gradual achievement of market maturity towards the more widely adopted use of SSI. Why not give it a go!?