The issue of cryptogen and Fabric CA certificate interoperability in Hyperledger

This article takes Fabric 1.4.6 as an example to briefly introduce the issue of cryptogen and Fabric CA certificate interoperability. Enabling a test network in the most efficient way is to run in the Fabric first-networkof ./byfn.sh up(version 2.0.0 use more than test-networkreplaced first-network, similar to the method used here, do not speak). However, when using the script, the cryptogentool is used to generate the identity by default , but the number of accounts (certificates) generated by the tool is fixed. Although you can change crypto-config.yamlthe settings in, change the number of additional users to a number greater than 1. But this change happens before the network is started, once the network is started, it cannot be changed. Therefore, we still need a mechanism to dynamically add users, and here it is CA's turn to appear.

To prepare, install the official original Fabric 1.4.6, Fabric Samples 1.4.6 and Fabric CA 1.4.2 according to the official documents Install Samples, Binaries, and Docker Images .

Tips: You can also write your own scripts, use CA directly instead of cryptogen to generate the identity and then start the network (see fabric-samples version 2.0.0 and above), so that there will be no intercommunication issues. But this article is mainly to talk about intercommunication, so we still use Fabric 1.4.6 version.

1. Start the test network and CA

To use the CA issuing identity, you need to start the CA server. You can start it manually with a command, or you can use a byfn.shscript to start a docker container. We use a script to minimize the work.

Switch to the fabric-samplesfollowing first-networkdirectory and run the following script:

./byfn.sh down
./byfn.sh up -a

The -aoption here is to start a CA at the same time when starting the network, see byfn.shthe introduction at the beginning of the script for details.

After the network deployment is completed, there will be a prompt. At this time, let's check the running container:

➜  fabric-samples git:(337f82c) ✗ docker ps -a
CONTAINER ID        IMAGE                                                                                                  COMMAND                  CREATED             STATUS                      PORTS                              NAMES
63334fdbdd15        dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b   "chaincode -peer.add…"   43 minutes ago      Up 43 minutes                                                  dev-peer0.org2.example.com-mycc-1.0
7e2df103a97c        dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9   "chaincode -peer.add…"   46 minutes ago      Up 46 minutes                                                  dev-peer0.org1.example.com-mycc-1.0
27c9e9e18e16        dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab   "chaincode -peer.add…"   15 hours ago        Exited (0) 55 minutes ago                                      dev-peer1.org2.example.com-mycc-1.0
3f4f0dbc9c9e        hyperledger/fabric-tools:latest                                                                        "/bin/bash"              15 hours ago        Up 55 minutes                                                  cli
fb080f3a877c        hyperledger/fabric-ca:latest                                                                           "sh -c 'fabric-ca-se…"   15 hours ago        Up 55 minutes               0.0.0.0:7054->7054/tcp             ca_peerOrg1
98be2c8c32b7        hyperledger/fabric-peer:latest                                                                         "peer node start"        15 hours ago        Up 55 minutes               0.0.0.0:7051->7051/tcp             peer0.org1.example.com
3f36dbf02ed1        hyperledger/fabric-peer:latest                                                                         "peer node start"        15 hours ago        Up 55 minutes               0.0.0.0:8051->8051/tcp             peer1.org1.example.com
789e6006049a        hyperledger/fabric-orderer:latest                                                                      "orderer"                15 hours ago        Up 55 minutes               0.0.0.0:7050->7050/tcp             orderer.example.com
1a4e27bc675f        hyperledger/fabric-peer:latest                                                                         "peer node start"        15 hours ago        Up 55 minutes               0.0.0.0:10051->10051/tcp           peer1.org2.example.com
7f4adb26061e        hyperledger/fabric-ca:latest                                                                           "sh -c 'fabric-ca-se…"   15 hours ago        Up 55 minutes               7054/tcp, 0.0.0.0:8054->8054/tcp   ca_peerOrg2
87c6b79f7292        hyperledger/fabric-peer:latest                                                                         "peer node start"        15 hours ago        Up 55 minutes               0.0.0.0:9051->9051/tcp             peer0.org2.example.com
➜  fabric-samples git:(337f82c)

From NAMESthat we can see, we start the CA server container two organizations, ports, respectively 7054, and 8054the corresponding org1 and org2. The work of this article is to use the CA of org1 to add a User2.

Let's take a look at the directory structure of the corresponding part after the identity is generated, mainly for User1:
Insert picture description here
you can see that we have generated an organization administrator Admin and a user User1, now let us generate a user without restarting the network User2.

2. Establish Fabric CA client

For convenience, we will operate in the fabric-samples directory. Run the following command to switch to the fabric-samplesdirectory and create a working directory:

cd ..
mkdir fabric_ca_test
cd fabric_ca_test
cp ../bin/fabric-ca-client ./

You can see that we fabric-ca-clientcopied this Fabric CA client tool to this directory. Because TLS is enabled by default when the script starts the CA, we need the TLS certificate of the CA Server. In first-networkthe directory of docker-compose-ca.yamlyou you can see the certificate path:
- FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem. Note that this is a virtual directory, and the real directory is volumesmapped in:

volumes:
  - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config

Here, according to the format of the certificate, it can be seen that the domain name of the CA is: ca.org1.example.com.

An environment variable that needs to be noted here is set to - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/${BYFN_CA1_PRIVATE_KEY}. It sets the private key of Fabric CA Server to the private key cryptogengenerated by the tool. If the private key is the same, the generated certificates are consistent. This is the prerequisite for the interoperability of certificates generated by different tools.

Run the following command to copy this TLS certificate:

mkdir tls-root-cert
cp ../first-network/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem tls-root-cert/tls-ca-cert.pem

As you can see, we have also renamed the file for convenience.

Now that we have the client and TLS certificate, we can request the CA Server to issue the identity.

3. Issuing CA to guide users

The first step in issuing an identity is to issue a guide user (equivalent to a CA administrator, not an organization administrator). The account password of the guide user is determined when the CA Server is started. See docker-compose-ca.yamlthe startup command in:
command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/${BYFN_CA1_PRIVATE_KEY} -b admin:adminpw -d'

For specific CA usage, you can read the official document , which is not explained here. As you can see from the above command, the username adminand password of the leading user are adminpw.

Mentioned earlier, CA's domain name: ca.org1.example.com, because we are here not no server-side configuration files, you can not use localhost, you also need /etc/hoststo add one 127.0.0.1to ca.org1.example.comthe resolution.

Run the following command to issue guide users:

export FABRIC_CA_CLIENT_HOME=$PWD
./fabric-ca-client enroll -u https://admin:[email protected]:7054 --tls.certfiles tls-root-cert/tls-ca-cert.pem --csr.hosts localhost --mspdir admin/msp

You will get similar output:

2020/08/22 12:05:43 [INFO] Created a default configuration file at /Users/likai/fabric/fabric-samples/fabric_ca_test/fabric-ca-client-config.yaml
2020/08/22 12:05:43 [INFO] TLS Enabled
2020/08/22 12:05:43 [INFO] generating key: &{
    
    A:ecdsa S:256}
2020/08/22 12:05:43 [INFO] encoded CSR
2020/08/22 12:05:43 [INFO] Stored client certificate at /Users/likai/fabric/fabric-samples/fabric_ca_test/admin/msp/signcerts/cert.pem
2020/08/22 12:05:43 [INFO] Stored root CA certificate at /Users/likai/fabric/fabric-samples/fabric_ca_test/admin/msp/cacerts/ca-org1-example-com-7054.pem
2020/08/22 12:05:43 [INFO] Stored Issuer public key at /Users/likai/fabric/fabric-samples/fabric_ca_test/admin/msp/IssuerPublicKey
2020/08/22 12:05:43 [INFO] Stored Issuer revocation public key at /Users/likai/fabric/fabric-samples/fabric_ca_test/admin/msp/IssuerRevocationPublicKey

Indicates that the guide user is successfully issued, and the relevant information is located in the admin/mspdirectory.

Four, use guide users to register and issue User2

1. Registration

You must register before issuing an identity. Run the following command to register:

./fabric-ca-client register --id.name User2 --id.secret User2pw --tls.certfiles tls-root-cert/tls-ca-cert.pem --mspdir admin/msp/

There will be output similar to the following:

2020/08/22 12:09:39 [INFO] Configuration file location: /Users/likai/fabric/fabric-samples/fabric_ca_test/fabric-ca-client-config.yaml
2020/08/22 12:09:39 [INFO] TLS Enabled
2020/08/22 12:09:39 [INFO] TLS Enabled
Password: User2pw

2. Issue

Use the username and password just registered to issue the identity:

./fabric-ca-client enroll -u https://User2:[email protected]:7054 --tls.certfiles tls-root-cert/tls-ca-cert.pem --csr.hosts localhost --mspdir users/User2/msp

There will be output similar to the following:

2020/08/22 12:13:13 [INFO] TLS Enabled
2020/08/22 12:13:13 [INFO] generating key: &{
    
    A:ecdsa S:256}
2020/08/22 12:13:13 [INFO] encoded CSR
2020/08/22 12:13:13 [INFO] Stored client certificate at /Users/likai/fabric/fabric-samples/fabric_ca_test/users/User2/msp/signcerts/cert.pem
2020/08/22 12:13:13 [INFO] Stored root CA certificate at /Users/likai/fabric/fabric-samples/fabric_ca_test/users/User2/msp/cacerts/ca-org1-example-com-7054.pem
2020/08/22 12:13:13 [INFO] Stored Issuer public key at /Users/likai/fabric/fabric-samples/fabric_ca_test/users/User2/msp/IssuerPublicKey
2020/08/22 12:13:13 [INFO] Stored Issuer revocation public key at /Users/likai/fabric/fabric-samples/fabric_ca_test/users/User2/msp/IssuerRevocationPublicKey

We can use the treecommand to view the directory structure just generated:

 tree users/User2/

The resulting structure is as follows:

users/User2/
└── msp
    ├── IssuerPublicKey
    ├── IssuerRevocationPublicKey
    ├── cacerts
    │   └── ca-org1-example-com-7054.pem
    ├── keystore
    │   └── 6f097b265f17e3bcab411a9ea3e328c62e851f9948ad4af7298d4e57535cb471_sk
    ├── signcerts
    │   └── cert.pem
    └── user

5 directories, 5 files

Our User2 has been generated. At this time, you can compare the directory structure of User1 in vscode and find that there are still some differences. Our next step is to copy the newly issued User2 certificate and key to first-networkthe corresponding directory structure in.

Five, add User2 tofirst-network

Run the following command to copy the directory structure of User1 to User2:

cd ../first-network/crypto-config/peerOrganizations/org1.example.com/users/
mkdir [email protected]
cd [email protected]
cp -r ../[email protected]/tls ./
cp -r ../[email protected]/msp ./
rm -f msp/keystore/*

Choose y here, delete User1's key, and then run:

rm -f msp/signcerts/*

Also select y to delete User1's certificate.

We copy User2's key and certificate:

cp ../../../../../../fabric_ca_test/users/User2/msp/keystore/* msp/keystore/
cp ../../../../../../fabric_ca_test/users/User2/msp/signcerts/cert.pem  msp/signcerts/[email protected]

Finally, we copy the CA root certificate of User2 (can be omitted)

cp ../../../../../../fabric_ca_test/users/User2/msp/cacerts/ca-org1-example-com-7054.pem msp/cacerts/ca.org1.example.com-cert.pem

Why can it be omitted here, because the target file already exists, it is copied from User1. Because we have two ways cryptogenand Fabric CAuse the same private key, so the trusted root certificate must be the same, otherwise there is no way to communicate. Interested readers can check whether the contents of the last copied source file and target file are exactly the same. If they are inconsistent, it will indicate what went wrong.

At this point, our new user User2has successfully released.

Here is a pit that the author encountered, that is, when registering User2, do not specify --id.typeit, clientjust let it default to .

Six, test

The test is a little more complicated here and involves the application of fabric-sdk-go. But here is an article for reference: Use fabric-sdk-go to manipulate chain codes . You can Adminreplace the places used in the source code (not in the configuration file) with User1and User2test. Here the author wrote a simple test file main.go, but the go mod initreader needs to get the configuration file by himself.

package main

import (
	"fmt"
	"log"

	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
	"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
)

const (
	org1CfgPath = "./config.yaml"
	ChannelID   = "mychannel"

	peer0Org1 = "peer0.org1.example.com"
	peer0Org2 = "peer0.org2.example.com"
)

func main() {
    
    
	sdk, err := fabsdk.New(config.FromFile(org1CfgPath))
	if err != nil {
    
    
		log.Panicf("failed to create fabric sdk: %s", err)
	}
	ccp := sdk.ChannelContext(ChannelID, fabsdk.WithUser("User2"))
	cc, err := channel.New(ccp)
	if err != nil {
    
    
		log.Panicf("failed to create channel client: %s", err)
	}
	fmt.Println("channel init over")
	query(cc)
	// execute(cc)
	// time.Sleep(5 * time.Second)
	// query(cc)
}

func query(cc *channel.Client) {
    
    
	// new channel request for query
	req := channel.Request{
    
    
		ChaincodeID: "mycc",
		Fcn:         "query",
		Args:        packArgs([]string{
    
    "a"}),
	}
	// send request and handle response
	reqPeers := channel.WithTargetEndpoints(peer0Org1)

	response, err := cc.Query(req, reqPeers)
	if err != nil {
    
    
		fmt.Printf("failed to query chaincode: %s\n", err)
	}

	if len(response.Payload) > 0 {
    
    
		fmt.Printf("chaincode query success,the value is %s\n", string(response.Payload))
	}
}

func execute(cc *channel.Client) {
    
    
	args := packArgs([]string{
    
    "a", "b", "10"})
	req := channel.Request{
    
    
		ChaincodeID: "mycc",
		Fcn:         "invoke",
		Args:        args,
	}
	peers := []string{
    
    peer0Org1, peer0Org2}
	reqPeers := channel.WithTargetEndpoints(peers...)
	response, err := cc.Execute(req, reqPeers)
	if err != nil {
    
    
		fmt.Printf("failed to Execute chaincode: %s\n", err)
	}
	fmt.Printf("Execute chaincode success,txId:%s\n", response.TransactionID)
}

func packArgs(paras []string) [][]byte {
    
    
	var args [][]byte
	for _, k := range paras {
    
    
		args = append(args, []byte(k))
	}
	return args
}

We can replace ccp := sdk.ChannelContext(ChannelID, fabsdk.WithUser("User2"))the "User2" in the middle with "User1" or "Admin", and it will work.
run:

go run main.go

Will get results similar to the following

channel init over
chaincode query success,the value is 90

The commented out code is used to execute the chain code, and interested readers can uncomment it and test it.

Well, the test is complete, and the newly generated users using CA can be used directly without changing the network.

Welcome everyone to point out the problems in the article or leave a message for discussion.

Guess you like

Origin blog.csdn.net/weixin_39430411/article/details/108165720