13

I'd like to explain what I understand correctly first and if I'm right, please tell me the truth and if I'm mistaken, tell me also that I'm mistaken. My explanation is about how hyperledger network and node sdk works together and how node sdk connects to hyperledger network.

Let's start. When I start hyperledger network, what it does is creates fabric-ca-server docker image and container on port 7054. On that port, it registered an user "admin with the password : "adminpwd". Which means there have also been certificates made for this user. Now let's say I want to create a new user from node sdk. I guess what I need to do is to have the certificate for Admin so that I can sign my request and network knows I'm admin and part of the network. What the code does is it firsts writes getUserContext("admin") and if it doesn't find, then it tries to enroll with the username and password (admin and adminpwd). My understanding is that getUserContext goes to hfc-key-store folder and tries to find the certificate for admin. if it doesn't find it, there happens enrolling and then happens createUser function, which puts certificate derived from fabric-ca-server docker image into hfc-key-store, so that when admin tries to enroll again, it doesn't have to go to fabric-ca-server docker image. Am I right so far? I'll ask my questions now.

Questions :

  1. I understand that when trying to enroll, it doesn't fetch the original certificate for admin from fabric-ca-server docker image, because if it gets stolen, whole network gets screwed up. so what It does is derives some kind of public/private and certificate from the original one with what I can make other operations. Question is : what If someone stole my hfc-key-store folder in which there's admins certificates. he can do operations without enrolling,because getUserContext("admin") would return true and it would let it do anything. What if someone steals that folder? isn't it dangerous?

  2. I don't understand what getUserContext() and setUserContext() and what createUser() functions mean at all. PLease if you can do, just describe them in a very understandable language, because It's been a long time since I've been trying to wrap my head around this but with no luck. Why do we need these functions, what they help us with and so on.

  3. Why is cryptogen tool not used in production but fabric-ca-server usable in production?

arjunkhera
  • 929
  • 6
  • 23
Nika Kurashvili
  • 6,006
  • 8
  • 57
  • 123
  • 3. Cryptogen generates all necessary components of fabric crypto related components ,with this you build the necessary docker system that involves copying your CA_SK to fabric-ca container , this is more manual and also could cause certification issue when you want to run same network in different machine . With Fabric-CA-Server all this gone and you interact with API/ fabric-ca-Client and enroll org to get their respective certificates. – Rangesh Oct 23 '18 at 05:02

3 Answers3

19

It seems a lot of questions there. Let me explain it step to step. Please give your comments if something is wrong or not clear.

Fabric is designed as a Consortium Blockchain System and is widely used in enterprise business scenarios. In a Fabric business network, each org usually contains at least one peer, and optional one ca.

Think of a business scenario like this. Several companies want to do business together. However, they don't trust each other enough. So they decide to use Fabric to solve their pain point. Suppose this network contains 3 companies (orgs) and each company (org) have one peer and one ca.

Now the business network is already setup.

First, let me explain the concept of enroll.

  1. Each org's ca has a bootstrap user, this comes by the username and password, usually the samples would use admin/adminpw. During the ca server setup time, this bootstrap user was write to the CA's db. After setup, the bootstrap user is registered. but not enrolled.
  2. The next thing is enroll the bootstrap user. In this step, fabric-sdk (I will use sdk later) will first, generate a private/public key pairs, then generate a csr (certificate signing request), at last use the private key to sign the csr and send the signed csr to fabric-ca server.
  3. When fabric-ca server received the signed csr. It generate a certificate for this user. The certificate contains the user's public key. Fabric-ca will use its private key to sign this request and append it's signature at the certificate.
  4. The sdk get response (the certificate from 3) from fabric-ca server. fabric-sdk put the certificate and user's private key together (we call it enrollment) as the response of method enroll().
  5. Now the bootstrap user has its enrollment, and can visit fabric network using this enrollment.

We can use the bootstrap user to register and enroll new users in this org. This is why we call the consortium blockchain system as permissioned blockchain system.

Second, let me explain the concepts for sdk KVS (key-value-store).

We already get the user's privateKey and certificate From above steps. So how do we persist these data? There are several choices, store it in a Application layer database, some hardware encrypted wallet, some cloud based HSM, etc.

Fabric-sdk provides a KVS to do this. This is an optional choice, you may choose to use it or not. Frankly speaking, I don't recommend to use this at production system. If you just want to try something or test something, this is good because it is quite simple.

By default, fabirc-sdk-node will use a filesystem KVS. It store the credentials in disk, this is what you mentioned hfc-key-store folder.

So what will happened if the KVS was stolen?

All the enrollments are stolen. All the certificates and privateKeys are stolen. The attacker can use these certificates and privateKeys to visit the blockchain system with the identity in these certificates. It's a disaster.

What is the createUser() used for?

Instead of store these enrollments in filesystem. A better choice to store it in an Application layer database. Each time we want to visit the blockchain system, we can query from the db first and get the certificate and privateKey. Then use the createUser() interface to create a new User instance. This User instance is used as the identity to visit the blockchain system.

At last, let me explain the transaction flow in fabric

We not have a valid user certificate and privateKey. How do we send transaction to fabric network? How does fabric-peer verify the transaction and know who am I?

  1. Each transaction contains the user's identity. If you want to submit a transaction by userA, then you should call setUserContext(userA) before further endorse call.
  2. The transaction proposal contains the user's certificate at message header. And before the transaction was send to fabric-peer, sdk will use the current user's private key to sign this transaction proposal.
  3. At peer side. when peer receives the endorse request, peer will use the root cert of the fabric-ca to verify the certificate in this request, so that peer knows this request is from an identity issued by a known CA, now the certificate is credible. Then the peer will parse the certificate and get the identity's public key, and then use this public key the verify the signature of the transaction (I described above the tx was signed by the private key and now it is verified by the public key), now the transaction is trustable.

From the transaction flow, we learned that a transaction must be send with the user's certificate and signed by the user's private key. This is why we designed the setUserContext() interface at fabirc-sdk.

cryptogen tool

This tool is used to generate private/public key pairs and the corresponding certificates at system setup. After that we need a dynamic add/remove identity mechanism. And the solution is Fabric-ca.

Note, fabric-ca is optional, you may use any other CA.

zhaochy
  • 734
  • 7
  • 12
  • 1
    I just finished reading the first "First, let me explain the concept of enroll.". So you say that each org has its own ca. why is it needed? I think It's because each organisation wants to have its own ca authority so that they don't have to trust the single CA that's used for each organization. Am I right? IF yes, then when sending csr request, you said organization sends csr to fabric-ca. Why does it send csr to fabric-ca and not send csr to its own CA? – Nika Kurashvili Oct 23 '18 at 13:46
  • 1
    Above was my first question. – Nika Kurashvili Oct 23 '18 at 14:24
  • Second Question is : can admin enroll other users? why? why should admin be able to enroll other users? if that's so, enrolling other users from admin will return certificate of other users to admin. and admin will do bad things for those users. – Nika Kurashvili Oct 23 '18 at 14:25
  • Third Question: by enrolling admin many times, each time new certificate gets returned to admin. I checked the database in fabric-ca and certificates get stored. so if I enrolled admin the second time, i get the second certificate, but the first certificate I got when I enrolled for the first time still is saved in fabric-ca database. is it that first certificate that is saved in fabric-ca database useful at all? – Nika Kurashvili Oct 23 '18 at 14:26
  • 1
    Fourth Question: so certificates don't have that much power than username and password have. why is that? if I have username and password or someone steals my username and password , they get a new certificate which is valid. so real power is still in username and password. isn't that bad? – Nika Kurashvili Oct 23 '18 at 14:26
  • 1
    Fivth Question: what does getUserContext("admin") return? does it return User instance? if that's so, I saw fabric-samples code where after getUserContext("admin") , they wrote this code fabric_ca_client.register({enrollmentID: 'user8', affiliation: 'org1.department1',role: 'client'}, admin_user); so why do I have to pass admin_user? I already proved that I'm admin because getUserContext("admin") did the right thing and gave me the user, right? you mentioned that if I do setUserContext(UserA), I can then submit the transaction. why doesn't getUserContext("admin") work the same way? – Nika Kurashvili Oct 23 '18 at 14:26
  • 1
    first question, each org owns its own ca, it might be an instance of fabric-ca or any other ca. The csr was send to each org's own ca – zhaochy Oct 24 '18 at 01:23
  • 1
    second question, in fabric-ca (other CA might be different), each user have its own username and password after register. Admin can not enroll other users because admin don't have this user's username and password. However, if the user provide his username and password to the admin, or the admin saved the user's credentials at register time, then admin can perform the enroll request. – zhaochy Oct 24 '18 at 01:29
  • 1
    third, the previous cert will be invalid after the second enroll. You need to update the CRL at peer side in time after revoke a certificate. – zhaochy Oct 24 '18 at 01:32
  • fourth, certificate is just the user's public key, with the CA's privateKey's signature. Real power is the user's private key. Before asking more question, can you learn some basic knowledges about [PKI](https://en.wikipedia.org/wiki/Public_key_infrastructure). – zhaochy Oct 24 '18 at 01:33
  • fivth, only admin can call register new user (or with the admin's approve) in fabric-ca. so we need to set the admin ctx first – zhaochy Oct 24 '18 at 01:38
  • 1
    fourth question was something else. imagine user knows his username and password. he can enroll again. he doesn't depend on his private key at all. if He knows username and password, he just enrolls again and again and again whenever he wants. so that's why I said more power is in username and password. and I think it's bad. – Nika Kurashvili Oct 24 '18 at 07:22
  • fivth questio: I meant something else. you say that before making a transaction proposal, we must setUserContext(userA) first and after that line of code, we can do anything on behalf of userA. now let's take a look at getUserContext(UserA). if this line returned the correct user, i can also make the transaction proposal right? no need to setUserContext(UserA) right? If I'm right, what fabricar does is getUserContext(admin) first, and then registers new user and passes returned admin object. why to pass at all? we know that getUserContext returned the user and i can do anything on behalf of it – Nika Kurashvili Oct 24 '18 at 07:25
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/182405/discussion-between-nika-khurashvili-and-zhaochy). – Nika Kurashvili Oct 24 '18 at 09:18
  • @NikaKhurashvili i am also struggling in finding the answer related to private key and the keystore thing. Would you please guide me a bit. – Adarsha Jha Jun 12 '19 at 08:36
11

There are multiple parts to your question; I'll try to start from the top.

  1. The Fabric CA is not required in order to run/operate Fabric peer or orderer nodes. The default security mechanism is based on standard X509 PKI using Elliptic Curves (p256 is the default). You can use X509 certificates issued by any means you desire. Fabric CA is provided as one such implementation.

  2. Fabric CA has multiple APIs, but the two main ones are Register and Enroll. Enrollment is the process of issuing X509 certificates. You must first register users/nodes before you can enroll them. When Fabric CA is started for the first time, you must create a "bootstrap" admin user. This user is automatically registered at startup but is not yet enrolled. You enroll with the Fabric CA by generating a private key and certificate signing request and submit this using the enroll ID and Secret. If this is successfully, you then receive your X509 certificate signed by the Fabric CA.

  3. For convenience, the Fabric Node SDK provides a fabric-ca-client package which provides wrapper APIs for registering and enrolling users with the Fabric CA. This allows you to obtain and use credentials from the Fabric CA

  4. The fabric-client package, however, does not require you to obtain credentials from the Fabric CA. You might have your own private key and X509 certificate which was issued by some other authority (or even generated by cryptogen).

  5. The fabric-client provides a "pluggable" key store for storing credentials. The default is a file-based key store.

  6. Internally, the fabric-client actually uses the User class to represent the current user. This is important as there are a few ways to populate this structure:

  7. Once you have a User object, you need to tell the fabric-client to use it. This is where you use Client.setUserContext(). You pass in the User object and by default this will be persisted.
  8. You can then use Client.getUserContext() - which loads the user information from the configured keystore - for future requests when you start up your client application.

As to your question about cryptogen, there's no reason why you can't use the generated crypto materials in production ... it's simply that it's a tool that was really designed to aid in development and testing to bootstrap a network. It is not a PKI infrastructure and does not included things like certificate revocation.

Hope this helps.

Gari Singh
  • 11,418
  • 2
  • 18
  • 41
  • 1
    Hello. Thanks for your answers. I'm so frustrated. Can we have a private chat so that I can understand better? where Can I find you? stackoverflow won't help us a lot. – Nika Kurashvili Oct 23 '18 at 11:24
  • 1
    @Gari Singh how IBM cloud doesn't store certificate and private key as they give an option to view and save the certificates and they say that they don't store these certificates ? – Adarsha Jha Jun 12 '19 at 08:55
  • 1
    I assume you are talking about the new IBM Blockchain service? We generate all of the crypto material on the client / browser side so we never save it on any of our servers (for client crypto material). For peers, orderers and CAs the material is saved on the storage used by the customer's Kubernetes Cluster. The IBM Blockchain team does not have access to this material. – Gari Singh Jun 12 '19 at 10:52
  • 1
    @GariSingh Thank you so much for your quick response, one question more. if i delete hfc-key-store folder and then a user signs transactions will it fail? In my case in order to avoid storing certificates at my node, i should setup CA for every organization on their node so that i don't have any access to it ? – Adarsha Jha Jun 12 '19 at 11:19
  • @GariSingh Actually my problem statement is that i want users to register and download their certificates on their devices or browser and upload it at the time of signing any transaction. I don't want to store the certificates . Can you please guide me on how to achieve that ? – Adarsha Jha Jun 12 '19 at 13:03
4

I love all your questions and I had came across exact same question when I worked on Node SDK for HLF recently.

I will try to answer as per best of my knowledge.

  1. In Blockchain world, securing private keys is the utmost priority. If you loose private key to someone that means you've lost claim to whatever entity your private key unlocks. In Hyperledger Fabric, you have to ensure safety of the keys, be it admin keys or user keys. If its stolen by any means, that means you're compromised. Remember, "with great power comes great responsibility". Also, "getUserContext("admin")" doesn't return 'admin' user context always. I'll explain in next answer.
  2. API documentations explains all technicalities here : getUserContext setUserContext createUser

    All these methods are available on 'client' class on NodeSDK. These methods allows 'user' management. When you say a user in Hyperledger Fabric world, by default it comes with a public and a private key reference. It has all other fields such as affiliation, identity, Role etc. as well. Read more at : User

    createUser creates an instance of User class with all/any of the above mentioned properties provided. This instance will be used to do all the relevant operations. If user has 'admin' access , it can perform 'admin' level function in Hyperledger Fabric world and so for other roles.

    getUserContext and setUserContext gets/sets the client instance's context. By setting appropriate User-context, you're authenticating the client and going forward client instance can use this context to sign requests.

    In addition to this, both these method reads/writes to some persistent store if configured. In case of Node SDK, it's hfc-key-store. If you examine the content of this folder, you'll find all your user identities stored here. If necessary files are not found under this folder (or whichever folder is configured for crypto-suite), getUserContext will fails and then you have to manually read the certificates from file system and create a User out of these certificates and then use it for setUserContext.

  3. cryptogen tool is static in its nature. While Fabric CA server supports communication via REST APIs using Fabric CA Client or Fabric SDKs. This makes it very useful in production environment where you need to generate new identities (read certificates) on the go. Using cryptogen tool can become cumbersome here.

jignesh
  • 182
  • 1
  • 12
  • 1
    Hello. Thanks for your answers. I'm so frustrated. Can we have a private chat so that I can understand better? where Can I find you? stackoverflow won't help us a lot. – Nika Kurashvili Oct 23 '18 at 11:24