Store Hyperledger Fabric certificates and keys in CouchDB | by Shubham Chadokar | Towards Data Science

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. 😩
Originally published at https://schadokar.dev
In Hyperledger Fabric, this storage is known as Wallet.
There are three types of wallet:
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.
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
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:
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.
The crypto store is used to store the public and private key of the identity.
To configure the couchdb as wallet:
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.
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.
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.
I am using the balance transfer fabric sample as a reference.
I am assuming that you know how to run the balance transfer.
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)
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
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 hfcvar hfc = require("fabric-client");// Instead of Clientconst 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"}]]
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.
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. 😉
https://developer.ibm.com/tutorials/store-fabric-certificates-keys-ibm-cloudant-fabric-node-sdk/
https://stackoverflow.com/questions/53639061/hyperledger-fabric-what-is-the-difference-between-state-store-and-crypto-store
https://stackoverflow.com/questions/54305378/hyperledger-fabric-client-credential-store-using-couchdb
https://stackoverflow.com/questions/58371858/hyperledger-fabric-client-credential-store-using-couchdbcouchdbkeyvaluestore
Originally published at https://schadokar.dev.