Store Hyperledger Fabric certificates and keys in CouchDB

Saturday, February 8, 2020 β€’ 5 minutes to read

Photo by Micah Williams on Unsplash

Hyperledger Fabric is all about permissions. These permissions are provided in the form of certificates and keys. In broad term, it is known as Identities.

When an application interacts with the Hyperledger Fabric Network, it uses this identity to authenticate itself. Fabric network validates the identity and authorizes the application to interact.

In short, identities are very important and if you don't save them properly, then it may turn into a headache. 😩

Where can I store the Identities? πŸ’Ό

In Hyperledger Fabric, this storage is known as Wallet.

There are three types of wallet:

  • File System

    This is a simple folder. A local storage wallet. It is a good default choice for wallets. In fabric-samples/balance-transfer, the file system is the default wallet. When you run the balance-transfer it creates a fabric-client-kv-orgName folder and saves all the identities in it. This configuration is defined in the orgname.yaml link.
  • In-Memory

    A wallet in application storage. Use this type of wallet when your application is running in a constrained environment without access to a file system; typically a web browser. It’s worth remembering that this type of wallet is volatile; identities will be lost after the application ends normally or crashes. - Documentation
  • CouchDB

    Using couchdb as a wallet. This option is best for production.

In this tutorial, we will configure the CouchDB as the Wallet. πŸ‘¨πŸ»β€πŸ’»

For the demonstration, I am using Fabric Node SDK and fabric/samples/balance-transfer.

The wallet uses 2 stores to save the certificates and keys:

1. State Store:

The state store is used to store the certificates of the enrolled identity. It stores the basic information of the identity:

{
  "name": "test",
  "mspid": "org1",
  "roles": null,
  "affiliation": "",
  "enrollmentSecret": "<ENROLLMENT_SECRET>",
  "enrollment": {
    "signingIdentity": "<PRIVATE_KEY_NAME>",
    "identity": {
      "certificate": "<SIGN_CERT>"
    }
  }
}

❗️ Note: The signingIdentity is the pointer or the address of the private and public key stored in the crypto-store.

2. Crypto Store:

The crypto store is used to store the public and private key of the identity.


To configure the couchdb as wallet:

Step 1

Import the CouchDBKeyValueStore library, which is provided by the Node SDK.

const CDBKVS = require("fabric-client/lib/impl/CouchDBKeyValueStore.js");

Do read the CouchDBKeyValueStore.js it is worth reading.

Step 2

Set the state store.

let stateStore = await new CDBKVS({
  url: "https://<USERNAME>:<PASSWORD>@<URL>",
  name: "<DB_NAME>"
});

const Client = require("fabric-client");

const client = Client.loadFromConfig("path of network.yaml");

client.setStateStore(stateStore);
  • <USERNAME> is the username of the couchdb.
  • <PASSWORD> is the password of the couchdb.
  • <URL> is the couchdb URL.
  • <DB_NAME> (OPTIONAL) is the dbname to use as state store. The default dbname is userdb. It creates the DB if it doesn't exist.

Client is the interface between the user and the fabric network.

Step 3

Set the crypto store.

const cryptoSuite = Client.newCryptoSuite();

let cryptoKS = Client.newCryptoKeyStore(CDBKVS, {
  url: "https://<USERNAME>:<PASSWORD>@<URL>",
  name: "<DB_NAME>"
});

cryptoSuite.setCryptoKeyStore(cryptoKS);

client.setCryptoSuite(cryptoSuite);

You have to update the client according to the above steps to make it use the couchdb.
In the next section, we'll implement the above steps in the balance-transfer fabric sample.


Implementation of CouchDB in Balance Transfer

I am using the balance transfer fabric sample as a reference.

I am assuming that you know how to run the balance transfer.

Start the balance transfer network

Follow the balance transfer instructions to start the network.

It will start the network with:

  • 2 CAs
  • A SOLO Orderer
  • 4 peers (2 peers per Org)

Start a couchdb for the wallet

This step is optional if you're using the cloud based couchdb.

Docker-based Couchdb

docker run --name couch-userdb -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -p 5984:5984 -d couchdb

Above command will pull the docker image of the couchdb from the docker hub if it doesn't exist.

CouchDB Details:
  • Container Name: couch-userdb
  • CouchDB Username: admin
  • CouchDB Password: password
  • URL: localhost:5984

The CouchDB connection URL is

https://<USERNAME>:<PASSWORD>@<URL>

https://admin:password@localhost:5984

Update the client in the balance-transfer

Open the app/helper.js and update the getClientForOrg.

In the below code, we just replaced await client.initCredentialStores(); with the above couchdb config steps.

The changes we made,

  • Line 13: Import the CouchDBKeyValueStore. Step 1 from above.
  • Line 31-52: Set the state store and crypto store. Step 2 & 3.

There is a minor change in the above code.

// Client variable is used as hfc
var hfc = require("fabric-client");

// Instead of Client
const Client = require("fabric-client");

It is not necessary that db(dbname) of state store and crypto store is the same. Both the stores can have their separate dbs. It depends on the requirement. You can have state store and crypto store db as orgName-state-store and orgName-crypto-store respectively.

Each organization must have their state-store and crypto-store db, else it will throw the Authentication Error.

Error: fabric-ca request register failed with errors [[{"code":20,"message":"Authentication failure"}]]

Register a new user in the balance transfer

Once you register a user, you can check the state-store and crypto-store using the couchdb apis.

For Example: Register a user

I used the below arguments to register a user. For org1, I used the same db org1db for both state-store and crypto-store.

  • Name: alice
  • Org: org1
  • DBNAME: org1db
  • CouchDB URL: http://admin:password@localhost:5369

Open the browser, go to http://localhost:5369/org1db/_all_docs. It returns all the docs saved in the org1db.

The indexes 0, 1, 2 are the certificates of the admin.

The index 3 is the alice certificate stored in the state-store.
The indexes 4-5 are the alice's public and private keys stored in the crypto-store.

Go to http://localhost:5369/org1db/alice. It returns all the details of the alice stored in the state store.

Check the signingIdentity.

"signingIdentity":"d37a97a8c2377c21537801ec1a929d81905ae57963a2f6c8ba0308931a7fc791"

Now, check the id of the indexes 4 & 5 in the above image. Both are same.

If you remember, signingIdentity field is a reference of the private and public keys of the identity stored in the crypto store.

Conclusion

CouchDB wallet is a great choice for a production use case. You can try with other dbs but in that case, you have to write the library accordingly like CouchDBKeyValueStore.js.


Below are the references I found helpful.
If you find any resource which you think can be added here, don't feel shy to share. πŸ˜‰


References πŸ“Œ


TutorialBlockchainhyperledger-fabriccouchdbtutorial

Understand Quicksort the easy way

Use Environment Variable in your next Golang Project