Knowledge Base Home

On-Chain Registry

NOTE: Interaction with the On-Chain Registry Service is a System Admin task that requires some familiarity with basic command line operations and a solid understanding of Ethereum accounts and private key materials.

The Kaleido On-Chain Registry Service is an environment-specific admin utility that allows for a validated organizational identity to be linked with Ethereum account addresses such that transactions can be authoritatively identified by fellow network participants as being tied to a particular organization. The service implements a hierarchical nesting scheme, whereby an organizational admin can register associated user identities and logically bind them to their organization. This allows for external users to sign transactions with their own private key materials, and still be unambiguously associated with the parent organization.

In addition to the organization/user relationship mapping, the Registry Service also serves as a convenience translator between the default nonsensical Ethereum account representation (0x + last 20 bytes of Keccak256 hash of secp256k1 ECDSA public key) and human readable plaintext identity assertions. For example, you could use the registry service to query something like /Kaleido example.user.com, where Kaleido is the parent organization name and user.example.com is a specific member within the org. This would return the registered user’s Ethereum account address and expose a one to one relationship between the member name and the targetable hex string. For example:

{"email":"user.example.com","owner":"0xc526861172fc546457b6e53c3e1e99bfb86d39a6"}

Lastly, the Registry Service provides a fully transparent public state database for key/value storage associated with the on-chain identities. The database, accessed via a profile command, can be used to store any relevant information associated with the parent organization and its registered users. For example, a rotating set of public keys for asymmetric encryption around off-chain transactions or an enumerated list of private constellation addresses for on-chain smart contract invocations. All keys and their associated values maintain a historical snapshot, allowing for the full lifecycle of any uploaded information to be captured indelibly on the blockchain and audited at any point in the future.

Deploying the Service

You can elect for one of two approaches to provision the Registry Service: Kaleido Console UI or Admin API. For users unfamiliar with the Kaleido REST API, the console interface is the recommended happy path. Both approaches will ultimately result in a new service instance and the deployment of two smart contracts (Directory and Profile) within the targeted environment. UI:

  • Navigate to an existing environment, and click the +ADD dropdown in the top right portion of the screen.
  • Select the Add Services option. This will open a new panel exposing the currently available Kaleido Services.
  • Click the ADD button beneath On-Chain Registry.
  • Supply an arbitrary name for the utility and click ADD. Click DONE to finish the deployment.
  • The environment-specific registry will appear under the Services view on your environment dashboard.
  • Click the details dropdown next to the ID Registry Service and select View Dashboard to ascertain the service ID.
  • The ID is the last ten characters of the details URL – {consortia_id}/{environment_id}/{membership_id}/{service_id}. Keep the ID handy, you will need it to programmatically interact with the service.
  • If you have already gone through the process of underpinning a membership with a valid x509 certificate, the ID will appear in an autogenerated YAML file displayed on this screen.

API:

NOTE: The following deployment approach assumes a strong understanding of the Kaleido APIs. Please refer to the Kaleido Resource Model for object relationships, the API 101 topic for sample CRUD operations and Understanding the Kaleido API for detailed descriptions of the various endpoints and routes.

The ID Registry Service is provisioned against the /services API endpoint and exists as an environment-specific utility resource. The orchestration is similar to other services (e.g. HD Wallet), where the object is directly bound to one of the consortium’s membership IDs. However, in contrast to HD Wallet which is a “member” type service, the ID Registry is shared across the environment as a “utility” type service and cannot be deleted once it has been provisioned in a decentralized environment. The binding to a membership ID simply allows fellow members of the environment to identify the org that provisioned the service. It is NOT an indication of ownership.  For centralized orchestrations (where all resources are owned an operated by a single organization), the Registry can be deleted by any organizational admin with access to the Kaleido console or a valid API Key.

To create the service, specify the consortia and environment IDs in the path and POST to the /services endpoint with a name, the service type and membership ID in the body of the call. The forthcoming sample commands assume that the following environment variables have been set as follows:

export APIURL="https://console.kaleido.io/api/v1"
export APIKEY="YOUR_API_KEY"
export HDR_AUTH="Authorization: Bearer $APIKEY"
export HDR_CT="Content-Type: application/json"

If you are targeting an environment outside of the US, make sure to modify your URL accordingly. The ap qualifier resolves to Sydney, while ko resolves to Seoul:

export APIURL="https://console-eu.kaleido.io/api/v1"
export APIURL="https://console-ap.kaleido.io/api/v1"
export APIURL="https://console-ko.kaleido.io/api/v1"

Use the POST method to provision the service and optionally format the output using jq:

# replace the membership_id placeholder with one of your membership IDs
curl -X POST -H "$HDR_AUTH" -H "$HDR_CT" "$APIURL/consortia/{consortia_id}/environments/{environment_id}/services" -d '{"name":"ExampleRegistryService", "service":"idregistry", "membership_id":"{membership_id}"}' | jq

This will return you the service ID. Alternatively, you can call a GET on the /services endpoint to expose all of the environment’s services and manually identify the ID:

curl -X GET -H "$HDR_AUTH" -H "$HDR_CT" "$APIURL/consortia/{consortia_id}/environments{environment_id}/services" | jq

Keep the service ID handy, we will use it in an upcoming step to communicate with the registry.

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: 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.
  • If you intend to produce an externally-signed certificate, you will need to make use of these instructions to ensure compliance with both curves and Distinguished Name information, and then manually upload the raw pem-encoded certificate into the Kaleido console.
  • Once you have uploaded a valid externally-signed certificate, click the dropdown selector at the far right of the corresponding membership and select Edit {Membership_Name}.
  • Click the Change hyperlink next to IDENTITY and select the name corresponding to your uploaded certificate.  Click Done to finish.

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 S3 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:

Command Line Tool for Kaleido resources management

Usage:
  kld [flags]
  kld [command]

Available Commands:
  create      Create various resources: consortium, membership, environment, node, appcreds
  delete      Delete various resources: consortium, membership, environment, node, appcreds
  get         Get details of a resource: consortium, membership, environment, node, appcreds, directory
  help        Help about any command
  list        List various resources this user account owns: consortium, membership, environment, node, appcreds
  profile     Manage on-chain indentity profile
  registry    Manage on-chain indentity registry

Flags:
      --config string   Config file that captures re-usable settings such as API URl, API Key, etc. (default is $HOME/.kld.yaml)
  -h, --help            help for kld
      --verbose int     Verbosity level of output (0 or 1)

Use "kld [command] --help" for more information about a command.

In order to use the kld CLI and successfully interact with the registry service, you need to supply some pertinent configuration parameters. In your $HOME directory create a hidden .kld.yaml file. For example:

cd $HOME && vi .kld.yaml

Use the following example .kld.yaml as a baseline for your configuration:

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-GVjjXDoapUdGC2QY-v1ShCzbSo@zzbhe067l6-zzhwhkkbax-rpc.console.kaleido.io

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 command requires one argument, your asserted name combined with your orgID, which must be the identical values specified in the CN field in your x509 cert. For example, if your certificate’s CN field is u0mvtw57gh-mzxyiuao8h--ABC then you would pass ABC--u0mvtw57gh to this command.  The org creation also 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 ABC--u0mvtw57gh -m abcde12345 -o 0xbbea381c342dfa5aA05d2Ec3Cce8E69d4BC77202 -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 Organizational ID represented as a Keccak256 path hash of the asserted organizational name and parent address.
  • 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 null 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": "0x62d4aad0705fadbcab42aa1ba93b43f364c93d8bcd2e2e441dc1b7db2590bcfa",
   "owner": "0xbbea381c342dfa5aA05d2Ec3Cce8E69d4BC77202",
   "name": "ABC--u0mvtw57gh",
   "parent": "0x0000000000000000000000000000000000000000000000000000000000000000",
   "proof": {
      "headers": [
         "eyJhbGciOiJFUzM4NCIsImtpZCI6IiJ9"
      ],
      "payload": "eyJhZGRyZXNzIjoiMHhiYmVhMzgxYzM0MmRmYTVhYTA1ZDJlYzNjY2U4ZTY5ZDRiYzc3MjAyIiwiZW52SWQiOiJ1MHcxYnZnemk1IiwibmFtZSI6IkFCQy0tdTBtdnR3NTdnaCIsIm5vbmNlIjoiZDk2MDY5NGU0MjkzOTc0MzBiOTQ1ZjQzYmU3NjM0ZDAzNGY3MWEwY2QwYjk2YmI1NDVlOGViMTExNDA3Yjk3ZSIsInByb29mIjoiLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlDSGpDQ0FhVUNDUUQreU5BSDdzd2d3akFLQmdncWhrak9QUVFEQWpCNU1Rc3dDUVlEVlFRR0V3SlZVekVMXG5NQWtHQTFVRUNBd0NUa014RURBT0JnTlZCQWNNQjFKaGJHVnBaMmd4RURBT0JnTlZCQW9NQjB0aGJHVnBaRzh4XG5GREFTQmdOVkJBc01DMFZ1WjJsdVpXVnlhVzVuTVNNd0lRWURWUVFEREJwMU1HMTJkSGMxTjJkb0xYbDJibVEyXG5ObWx6WTNJdExVRkNRekFlRncweE9UQXlNVGd5TURBek1EZGFGdzB5TURBeU1UZ3lNREF6TURkYU1Ia3hDekFKXG5CZ05WQkFZVEFsVlRNUXN3Q1FZRFZRUUlEQUpPUXpFUU1BNEdBMVVFQnd3SFVtRnNaV2xuYURFUU1BNEdBMVVFXG5DZ3dIUzJGc1pXbGtiekVVTUJJR0ExVUVDd3dMUlc1bmFXNWxaWEpwYm1jeEl6QWhCZ05WQkFNTUduVXdiWFowXG5kelUzWjJndGVYWnVaRFkyYVhOamNpMHRRVUpETUhZd0VBWUhLb1pJemowQ0FRWUZLNEVFQUNJRFlnQUV0UmFYXG5aWnpqeEMrL09QTWV2K0ZSYTNPcmNQNVNlcFVwMlpxTi9Zd3dIQy9aWkRHRVhmT1F1eklyV3BZTW12RGJ3ZUhKXG5hTXI5Y0NRR1RTa2VVL0lDMzNqYllEcFBMME1iWkVYalpkS0pYbHBjZkZDZThERjdjUmdGaTNkV3k2WFRNQW9HXG5DQ3FHU000OUJBTUNBMmNBTUdRQ01DVnR4NmJ2OHJWaFRXVkcveTNqTDFUaWdjMThwZWcxWCsrNGJlWnBHT2dPXG5lbTJqbTFQY2N1aEV6cktvVkRVRlpnSXdVbXJWNDBrMENOdGRVODZiM2tPUzVxYU14dFZtb0c4WTZJYlI1azBlXG4ycVNQZTZGMmxrdzFjUzh1Y2xhL0JoUllcbi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS1cbiJ9",
      "signatures": [
         "CjE2hPvSx3Lw3ellKPV2j4s31lEr2EgbJmAyf6ItPCW10rKh_psra0ZQzAFd81xtkvGBfW4cY3IdRLu74aqpYRL4M2FlyuYM6kBOka6Wyrh87TFO1xJFBb5_bpjRGDu8"
      ]
    },
    "name": "ABC--u0mvtw57gh"
}

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 /ABC

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 =  255833

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",
   "email": "example.user.com"
}
----------------------------------------------------------
{"email":"example.user.com","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 --help 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 ABC-Public-Info -v 'example public information meant to be seen by all' -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 0xc526861172fc546457b6e53c3e1e99bfb86d39a6

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 ABC-Public-Info -o 0xc526861172fc546457b6e53c3e1e99bfb86d39a6

You can programmatically interact with the ID Registry Service via the Kaleido CLI.  Please refer to the Technical Info tab for detailed instructions on creating an on-chain identity, registering users and interfacing with the registry key/value store.

Coming soon…

Prev IPFS Next Eth-Connect