Usage via CLI

If you want to manage your own private keys for x509 certificates and Ethereum accounts, you need to use the Kaleido CLI. Using this tool, you can sign transactions with your keys before sending them to one of the On-Chain Registry smart contracts.

Verify a Membership Identity

Before interacting with the Registry Service, ensure that you have successfully validated a membership identity under your organization’s control. A validated membership identity will display a blue ribbon next to its name. For example, Kaleido-engineering below:

Membership Identity List

Successful interaction with the service is reliant on an authenticated x509 certificate that has been bound to a membership ID. The certificate, its corresponding private key, and a fully-controlled Ethereum account will serve as the basis for your root organizational identity in the Registry Service. Refer to the below instructions if you have not yet established your off-chain identity proof. If you already have a validated membership identity, jump ahead to the next section.

  • Navigate to the landing page of the consortia containing the membership identity you wish to validate.
  • Click the dropdown selector at the far right of the membership name, and select Confirm Identity.
  • The two options for identity verification are: Self-Signed and Externally-Signed. Self-signed certs are generated by Kaleido, while externally-signed certs make use of key material controlled by the end user.
  • Follow the instructions in the popup modals to generate your desired certificate type. Self-signed certs will be automatically generated and appended to the selected identity. Externally-signed certs will require you to create the cert, then manually upload the raw pem-encoded certificate into the Kaleido console.

Establish an Ethereum Identity

As stated above, an on-chain identity in the Registry Service is comprised of authenticated PKI materials and a user-controlled Ethereum account. Note that the default Ethereum accounts that come with a Kaleido node are generally unsuitable for this exercise, as Kaleido does not expose the private key materials associated with the node. You would need to integrate an Backup with your node and manually retrieve the private key in order to use the node account. As a result, it’s recommended to instead use an external tool (e.g. Geth) to generate separate, fully-controlled accounts and key materials.

Alternatively, if you have existing accounts and keys these can be utilized as well. We’ll use the Geth Command Line tools and the convenient helper functions to quickly generate some local accounts and key materials. If you don’t have the client installed, you can do so here. Existing accounts can be leveraged, however the key materials must be imported to your local Ethereum instance via a geth account import process, as Geth is currently the only Registry-compatible wallet. Therefore, for the sake of simplicity, we will stick with the default Geth account creation commands.

First, make sure your client is functioning as expected. This should return an extensive list of commands and options:

geth --help

Next, create a local Ethereum account and private signing key:

geth account new

Supply a passphrase to the account and then verify the passphrase. This will return you the address for your newly created account. For example:

Address: {8d852be5543d776fbd85b0c5795eb89a780dd08f}

You can follow this basic command and create as many accounts as you wish. The accounts and their key material will live on your machine at $HOME/Library/Ethereum/keystore. We will use this path in the upcoming steps to specify the location of relevant addresses and key materials.

Build the Interface and Apply Configurations

Use the kaleido-sdk-go repo to build the kld CLI on your local machine or download the platform-specific binary. Refer to the Golang documentation for assistance with installing Go and properly setting your GOPATH and GOROOT environment variables. This interface will abstract the Ethereum JSON/RPC API and greatly simplify interaction with the Registry Service and its deployed smart contracts. Ensure that the interface has been properly built prior to continuing:

./kld -h

Specifically, make sure you see commands for registry and profile. For example:

Configure the CLI

First ensure you have installed the Kaleido CLI

api:
  url: https://conosle.kaleido.io/api/v1
  key: zzvv5lfdv9-5DCMSM3HT7Xo+6LAkPFdVK+RUwiABoqm7gm/ZG5lV5E=
  debug: true
services:
  idregistry:
    id: zzuraidnux
networks:
  url: https://zzvdtbvme9:lPb18K7C0EqrJmSS-GVjjXDoapUdG

Now edit the following fields accordingly:

  • If you are targeting resources in the US, leave the API URL unchanged.
  • If you are targeting resources in the EU or AP, adjust the URL to specify your targeted region.
    • For example, https://console-eu.kaleido.io/api/v1 to target EU resources.
  • Replace the sample key with a valid APIKEY for your Kaleido Organization.
  • Replace the sample idregistry id with the Registry Service ID you retrieved earlier.
  • Replace the networks url with a fully-qualified node endpoint.

Save the file and navigate back to the repo containing your kld CLI.

Environment Variables and Key Encryption

The last piece of housekeeping before interacting with the Registry Service involves the private key materials for both the x509 certificate and the local Ethereum accounts. First, navigate to the directory containing the private key associated with the validated certificate. Now convert this key into PKCS 8 syntax and optionally supply a passphrase to encrypt the key. For example, if the targeted key was saved as private.key then you would pass the following to convert the key to PKCS 8 and name it private.pk8:

# you will be prompted for a passphrase after issuing this call
openssl pkcs8 -topk8 -in private.key -out private.pk8 -v2 des3

To convert the key without encryption, pass the following. Note that this approach presents a potential attack vector and is thus NOT recommended:

openssl pkcs8 -topk8 -in private.key -out private.pk8 -v2 des3 -nocrypt

If you elected to encrypt your key, optionally export the passphrase as an environment variable in the directory where you are running the kld CLI (valuable for scripting scenarios). If you choose not to specify an environment variable, you will be interactively prompted for the passphrase when running the kld commands. For example, if your passphrase was 123 you would set the following:

export KLD_PKCS8_SIGNING_KEY_PASSPHRASE="123"

Similarly, if your local Geth wallet is passphrase protected, optionally set an environment variable in the kld CLI directory to unlock the keystore. For example, if your Ethereum account passphrase was 123 you would set the following:

export KLD_GETH_KEYSTORE_PASSWORD="123"

Establish your Organizational Identity in the Registry Service

Use the ./kld registry create org command to bind your verified organizational identity (i.e. the validated x509 cert) with an Ethereum account and establish an on-chain organizational identity. Use the --help flag to see the required fields. For example:

./kld registry create org -h

The org creation requires the enumeration of the four fields listed below. The consortia and environment IDs can be withheld, as they are extracted from the service definition:

-m, --memberid string          Membership ID of the org
-o, --owner ethereum-address   Ethereum address for the owner of the organization
-k, --pkcs8-key string         Path to a key that should be used for signing the payload for registration
-p, --proof string             Path to identity certificate used when identifying organization on Kaleido

The Ethereum address is the locally controlled account that you are binding the organizational identity to. The proof is your off-chain validated x509 certificate that is available for inspection by fellow members of the consortia. The PKCS8 key will be used to sign this request and to validate that you are in fact the rightful owner of the supplied certificate (only the true owner will possess the certificate’s corresponding private key). If the PKCS 8 private key is encrypted, the kld CLI will leverage the KLD_PKCS8_SIGNING_KEY_PASSPHRASE environment variable to decrypt before using it to sign the payload. You can set this variable now if you have not yet done so. If the environment variable is not set, you will be interactively prompted by the CLI for the passphrase. An example org creation call might resemble the following:

./kld registry create org -m zzbyhad7ub -o 0x33c3bcd74baed4ce14b68c849be0d4fcf8d38a8b -k /Users/johndoe/PKI/private.pk8 -p /Users/johndoe/PKI/certificate.pem

A successful call will return a JSON object containing the following:

  • id: The Membership ID represented as a Keccak256 path hash.
  • owner: The Ethereum account address bound to the organization.
  • name: The asserted organizational name derived from the CN field in the supplied x509 certificate and specified in plaintext.
  • parent: The name hash of the parental organization. Returns 0x0000000000000000000000000000000000000000000000000000000000000000 for organizational creation as this action is at the top of the tree.
  • headers: A base64 encoded representation of the Signing Algorithm used to sign the payload.
  • payload: A based64 encoded payload containing: the environment ID, generated nonce, Ethereum address for the org, the organizational name and supplied x509 certificate.
  • signature: A signature over the payload using the x509 certificate’s private key with the corresponding signing algorithm.

For example:

{
   "id": "0x6c853be033e8bd82f2189174fbebc91e238e6e80ecdf42aef44fd2a0e4a578ba",
   "owner": "0x33c3bCd74BaEd4CE14B68C849bE0d4fCF8d38a8b",
   "parent": "0x0000000000000000000000000000000000000000000000000000000000000000",
   "proof": {
      "headers": [
         "eyJhbGciOiJFUzM4NCIsImtpZCI6IiJ9"
      ],
      "payload": "eyJhZGRyZXNzIjoiMHgzM2MzYmNkNzRiYWVkNGNlMTRiNjhjODQ5YmUwZDRmY2Y4ZDM4YThiIiwiZW52SWQiOiJ6enhqeTRrdzllIiwibWVtSWQiOiJ6emJ5aGFkN3ViIiwibmFtZSI6IkthbGVpZG9UZXN0LXp6YnloYWQ3dWIiLCJub25jZSI6IjlhMDE5OGYyYWQ1Yzg5MGYyN2ViNTY5OTQ5YTAzYmVkNzdkOTUyZTcyMmRhNDAzNzRhYmE4OGJiMzY1MGJlYmQiLCJwcm9vZiI6Ii0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLVxuTUlJQ01UQ0NBYmNDQ1FDaW1XblBSWWJCeURBS0JnZ3Foa2pPUFFRREFqQ0JnVEVMTUFrR0ExVUVCaE1DVlZNeFxuQ3pBSkJnTlZCQWdNQWs1RE1SQXdEZ1lEVlFRSERBZFNZV3hsYVdkb01SQXdEZ1lEVlFRS0RBZExZV3hsYVdSdlxuTVJRd0VnWURWUVFMREF0RmJtZHBibVZsY21sdVp6RXJNQ2tHQTFVRUF3d2llbnBqZVdkamNtVXlOQzFuY1cxMlxuTjNaNmR6YzFMUzFMWVd4bGFXUnZWR1Z6ZERBZUZ3MHhPVEExTVRNeE9ETTVNVGhhRncweU1EQTFNVEl4T0RNNVxuTVRoYU1JR0JNUXN3Q1FZRFZRUUdFd0pWVXpFTE1Ba0dBMVVFQ0F3Q1RrTXhFREFPQmdOVkJBY01CMUpoYkdWcFxuWjJneEVEQU9CZ05WQkFvTUIwdGhiR1ZwWkc4eEZEQVNCZ05WQkFzTUMwVnVaMmx1WldWeWFXNW5NU3N3S1FZRFxuVlFRRERDSjZlbU41WjJOeVpUSTBMV2R4YlhZM2RucDNOelV0TFV0aGJHVnBaRzlVWlhOME1IWXdFQVlIS29aSVxuemowQ0FRWUZLNEVFQUNJRFlnQUVleTBmMStlbnF6NGMxVjBFdThLTFhBSHBqSnFpZDBQZ2RTMU1sbm42emo1NlxuUVBycTErdWZEM0pnWEhuR0JBRmp0TDV0dk03WTNJc0wyM3gzc2hpMmJPTTQ1d1VmM2MwT3E0TUhZeDVKUDlGOVxuYzh3VTBsSEliWjM5aGJKU2Yra2NNQW9HQ0NxR1NNNDlCQU1DQTJnQU1HVUNNUUNocWNCSHMvdFZNWXorK3hLcVxuN1FlWlZMcnlLRmNBMEtqWTZ4bUtHQVBab2R6RE1MYWpsc0M2aTIxUm1BUzNJWFVDTUJad0p0cG15QWoraGxtNFxuRTBrc0RVaTR5dklCU0U4TnUwMTMrNXRFVEljV1N5anY1cCtqZS9tdHVRM2Q3TDBlRHc9PVxuLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLVxuIn0",
      "signatures": [
         "IQhgVwkmSlRvNr3watSMe52khF9XV3LBmADhrvjApCggeuDofVLqHRnH1e1rs62W41NmcLunNLdMhiipHcKpU59wKLuS8CHJFAEULwaf-erpwF6sW4wn3mcG7ic8OoIy"
      ]
   },
   "name": "zzbyhad7ub"
}

To view the newly created org, call the get org command and pass the org name as a path argument. This call will return the same JSON object displayed on the org creation. For example:

./kld registry get org /zzbyhad7ub

To view all orgs in the Registry Service, call the get orgs command with no arguments. This call will simply return the Organizational Names and corresponding IDs, after which you can call get org /{Org_Name} to retrieve additional information for a specified org. For example:

./kld registry get orgs

Register a User Against the Organization

Once the organizational identity has been established in the Registry Service, you can proceed to register users against the on-chain identity by means of the create user command. Use the --help flag to see the required fields. For example:

./kld registry create user -h

This command takes one argument, an email address for the user, and requires the enumeration of the four fields listed below. As is the case with org creation, the consortia and environment IDs can be withheld as these are derived from the service definition:

-k, --keystore string           Keystore path so accounts can be used to sign tx
-o, --owner ethereum-address    Ethereum account that the user owns
-p, --parent string             Path to the parent org or group
-s, --signer ethereum-address   Account to use to sign tx

If your local Ethereum keystore is passphrase protected, the kld CLI will leverage the KLD_GETH_KEYSTORE_PASSWORD environment variable to access the private signing keys. You can set this variable now if you have not yet done so. If an environment variable is not set, you will be interactively prompted by the CLI for the passphrase. An example user creation call might resemble the following:

# use the Ethereum account bound to the parent identity as the signer
./kld registry create user example.user.com -p /ABC -k /Users/johndoe/Library/Ethereum/keystore -o 0x66262e2ce2036be94e955f7183d60cdf4410999c -s 0xc526861172fc546457b6e53c3e1e99bfb86d39a6

A successful user creation call will return a transaction notification. For example:

tx sent: 0x59001d14ed3bbfd8784466f7d0af00a00b6fcde4e4950be80c6aa30ee279c5ff
waiting for tx to be minded (may take a few seconds)...
tx receipt, stats 1 gas used =410650

Now to view the newly created user, call the get user command and specify the registered email and parent organization. For example:

./kld registry get user example.user.com -p /ABC

This will return a JSON object containing the user’s email, user ID, Ethereum account and Org ID. For example:

BODY   :
{
   "userId": "0x4eb932039ecce6bf23e53c304ca61de0d55d28f233db7138fee6ea10bf1c7402",
   "orgId": "0xa9880f803104f6c827738712bb16e3689bcf9c83bf163b20f496f337b3a3fdb2",
   "owner": "0x66262e2ce2036bE94e955f7183d60CDf4410999C",
   "name": "example.user.com"
}
----------------------------------------------------------
{"name":"example.user.com","orgId":"0xa9880f803104f6c827738712bb16e3689bcf9c83bf163b20f496f337b3a3fdb2","userId":"0x4eb932039ecce6bf23e53c304ca61de0d55d28f233db7138fee6ea10bf1c7402","owner":"0x66262e2ce2036bE94e955f7183d60CDf4410999C"}

To see all users for a given organization, call the get users command and simply specify the parent organization. For example:

./kld registry get users -p /ABC

Note that you cannot retrieve a phonebook listing of all users in the registry. The broadest macro search exists against an organizational ID.

Create a Key/Value Entry in the Profile Database

The publicly shared Registry database can be used to upload keys and corresponding values for Organizations and/or users by means of the profile set key command. The key/value pairs have a one to one correlation with an Ethereum account that has been registered with the ID Service. Use the -h flag to see the required fields. For example:

./kld profile set key -h

This command takes one argument, a string for the key, and requires the enumeration of the three fields listed below. As is the case with org and user creation, the consortia and environment IDs can be withheld as these are derived from the service definition:

-k, --keystore string          Keystore path so accounts can be used to sign tx
-o, --owner ethereum-address   Account of the profile owner
-v, --value string             Value for the key

In identical fashion to user creation, if the local Ethereum keystore is passphrase protected, the kld CLI will leverage the KLD_GETH_KEYSTORE_PASSWORD environment variable to access the private signing keys. An example key/value entry might resemble the following:

./kld profile set key 'Public Info' -v 'interesting details' -o 0xc526861172fc546457b6e53c3e1e99bfb86d39a6 -k /Users/johndoe/Library/Ethereum/keystore

To view the keys for a given Ethereum account, call the get keys command and specify the targeted account. For example:

./kld profile get keys -o 0x33c3bCd74BaEd4CE14B68C849bE0d4fCF8d38a8b

To view a specific key for a given Ethereum account, call the get key command, specify the targeted account and supply the key of interest as an argument. For example:

./kld profile get key 'Public Info' -o 0x33c3bCd74BaEd4CE14B68C849bE0d4fCF8d38a8b

Upload a Destination Certificate to the Profile Database

If your membership is underpinned with an externally-signed x509 certificate then you need to use the CLI to inject your destination certificate into the Profiles smart contract. This applies to both Kaleido-generated destination certificates and manually-generated destination certificates with user-controlled private key material. You are responsible for proving ownership of the Ethereum account’s private key; Kaleido does not have this stored.

Follow the same approach as you would with a standard key/value pair and substitute the key with your destination URI and the value with the pem-encoded x509 destination certificate. The syntax is as follows:

./kld profile set key DESTINATION_URI -v 'DESTINATION_CERTIFICATE' -o ETHEREUM_ADDRESS -k PATH_TO_ETHEREUM_ADDRESS_PRIVATE_KEY

An actual call would resemble something similar to the following:

./kld profile set key kld://app2app/m/zzgjsrbg8g/e/zzid2g9aq7/s/zzb6ev55x8/d/example_destination -v '-----BEGIN CERTIFICATE----- MIIC3jCCAcYCCQCNXY+BRc107DANBgkqhkiG9w0BAQsFADAxMS8wLQYDVQQDDCZh cHAyYXBwLXp6YjZldjU1eDgtZXhhbXBsZV9kZXN0aW5hdGlvbjAeFw0xOTA1MTQy MTM3NDRaFw0yMDA1MTMyMTM3NDRaMDExLzAtBgNVBAMMJmFwcDJhcHAtenpiNmV2 NTV4OC1leGFtcGxlX2Rlc3RpbmF0aW9uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEA8cM3hDTB5zT6xP1cJJEacN2C+yS5vOyMGZ3SDZ9hyrHh29beSFyf 0BYNXebMTEtzRsOn/bS28EBcY3dntI7qL6Apn9cK+HHdtU4Hw5RcZpdOxvnYxxQL sNp+wu7xW/igI1Zsd/T67K0jDdrxj/4nCdSBqKCNlPD61PoJQIsfKiVCihdnEy4H Z2ScLQJLTxbLXXYZIK5H7b93SIPg7xhSbdc1j2Q/U2/EfrtQO/jef7cy9gvCLxoq 4BFm2Kf8xZjrso9D1HzaosWsylRO/WI/odSEUy35VuZFHSXXFC06DrFmkMsoOayX FuXX9FE4PsNlc+bJyR9gfkBHFDmW015+TQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB AQC28//H8Ziri3tP8utr+IsAXD5l6tUFNjsTqoA0nadgWIDS/kuB4c0bMs/JnIvT zD8E4wknAytInBR1UbwrItH4KBD5OWg9NUppTo2M/JFEjE+7MZMqznbwqbE/8VRR w6y5Abif7CJwInImbhj3qhN30k7KcXAKRgPATkCZ/Q4cD84NQBw4Sejs4gp34G2u C/nHkFeDbJ/99gnYo4xWvtlR02uoJkId0rJCiN5D3ew535unXSX0pwe3MEnNn16f EWLzDFx3sA08jH2SEJHfMjm8HUBk0a8A65XQ6XkLu+0FV68KRagUFEwNl36ZK2/G H7l2tF+kCe0umTsyKw/6J7sb -----END CERTIFICATE-----' -o 0x6ace4f2166ae8f1920791fd584aa6a84ca0b29e9 -k /Users/johndoe/Library/Ethereum/keystore

If the transaction is successful you should output similar to the following in your terminal:

Detected version 2.0.0 of the deployed smart contracts.
This version of the CLI is compatible.
Password needed to unlock keystore:
tx sent: 0xf96f834caa3b8cf33954624b29beb86663dfe5287821d44b4bfdae6cc296a9ce
waiting for tx to be mined (may take a few seconds)...
tx receipt, stats 1 gas used = 1038160