本文主要记录自己对Hyperledger fabric-ca的操作及认识,为原创内容,如有文中有书写或其他问题,请留言指导修正,互相交流,共同进步,本人QQ:417213902。
1、简单聊聊Fabric-ca模块
- Fabric-ca模块其实是个证书颁发模块,仅有证书颁发功能,也就是说在做交易或者在链中做其他操作时,是不涉及ca模块,这里我最初不是这么认为的,我觉得应该是它颁发证书后,后面在链中每一次操作,ca模块都进行相应的配合验证校验功能,这对目前的fabric-ca模块是个误区。
- 当然你也可以不用ca模块来管理证书,证书可以通过专门的证书部门生成根证书,然后在本地通过cryptogen工具自行生成证书(这个方式在上一篇文章中已经讲过)。
- fabric-ca分为fabric-ca-client和fabric-ca-server,fabric-ca-server就是ca服务;fabric-ca-server是可以通过fabric-ca-client 来操作生成证书、登记、注册、撤销证书等操作。
- 以下思路是通过作者自己不断的摸索得出的结论,不保证生产环境是否适用。
2、通过client端生成证书管理
2.1、前期准备
- 修改docker-compose.yaml文件
直接修改这个路径下的$GOPATH/src/github.com/hyperledger/fabric-sdk-java/src/test/fixture/sdkintegration/docker-compose.yaml文件
直接贴脚本了,修改过的地方标注中文说明,主要是修改了两个ca的挂载目录,可以方便操作sqlite3数据库
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
services:
ca0:
image: hyperledger/fabric-ca${IMAGE_TAG_FABRIC_CA}
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
ports:
- "7054:7054"
command: sh -c 'fabric-ca-server start -n ca0 ${V11_IDENTITIES_ALLOWREMOVE} ${V11_AFFILIATIONS_ALLOWREMOVE} --registry.maxenrollments -1 --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/e89b5807c72b15040d7ecdade99eb633995d2339e9b1faa672838a91278974ae_sk -b admin:adminpw ${ORG_HYPERLEDGER_FABRIC_SDKTEST_INTEGRATIONTESTS_CA_TLS} --tls.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --tls.keyfile /etc/hyperledger/fabric-ca-server-config/e89b5807c72b15040d7ecdade99eb633995d2339e9b1faa672838a91278974ae_sk -d'
volumes:
- ./e2e-2Orgs/${FAB_CONFIG_GEN_VERS}/crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config:ro
#为的是可以访问fabric-ca-server中生成的文件
- /etc/hyperledger/fabric-ca-peerOrg1-server:/etc/hyperledger/fabric-ca-server
container_name: ca_peerOrg1
ca1:
image: hyperledger/fabric-ca${IMAGE_TAG_FABRIC_CA}
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
ports:
- "8054:7054"
command: sh -c 'fabric-ca-server start --registry.maxenrollments -1 --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/7ba11256a588037957071ad894de23902bd42908b1b183bb03387ae09c133b44_sk -b admin:adminpw ${ORG_HYPERLEDGER_FABRIC_SDKTEST_INTEGRATIONTESTS_CA_TLS} --tls.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem --tls.keyfile /etc/hyperledger/fabric-ca-server-config/7ba11256a588037957071ad894de23902bd42908b1b183bb03387ae09c133b44_sk -d'
volumes:
- ./e2e-2Orgs/${FAB_CONFIG_GEN_VERS}/crypto-config/peerOrganizations/org2.example.com/ca/:/etc/hyperledger/fabric-ca-server-config:ro
#为的是可以访问fabric-ca-server中生成的文件
- /etc/hyperledger/fabric-ca-peerOrg2-server:/etc/hyperledger/fabric-ca-server
container_name: ca_peerOrg2
orderer.example.com:
container_name: orderer.example.com
image: hyperledger/fabric-orderer${IMAGE_TAG_FABRIC}
environment:
- ORDERER_GENERAL_LOGLEVEL=debug
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_GENESISMETHOD=file
- ORDERER_GENERAL_GENESISFILE=/etc/hyperledger/configtx/orderer.block
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp/orderer/msp
- ORDERER_GENERAL_TLS_ENABLED=${ORG_HYPERLEDGER_FABRIC_SDKTEST_INTEGRATIONTESTS_TLS}
- ORDERER_GENERAL_TLS_PRIVATEKEY=/etc/hyperledger/msp/orderer/tls/server.key
- ORDERER_GENERAL_TLS_CERTIFICATE=/etc/hyperledger/msp/orderer/tls/server.crt
- ORDERER_GENERAL_TLS_ROOTCAS=[/etc/hyperledger/msp/orderer/tls/ca.crt]
- GRPC_TRACE=all=true,
- GRPC_VERBOSITY=debug
- ORDERER_GENERAL_AUTHENTICATION_TIMEWINDOW=3600s #Not for production -- remove.
working_dir: /opt/gopath/src/github.com/hyperledger/fabric
command: orderer
volumes:
- ./e2e-2Orgs/${FAB_CONFIG_GEN_VERS}:/etc/hyperledger/configtx:ro
- ./e2e-2Orgs/${FAB_CONFIG_GEN_VERS}/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/:/etc/hyperledger/msp/orderer:ro
ports:
- 7050:7050
peer0.org1.example.com:
container_name: peer0.org1.example.com
extends:
file: peer-base/peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.org1.example.com
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
# - CORE_PEER_GOSSIP_ORGLEADER=true
- CORE_PEER_LOCALMSPID=Org1MSP
volumes:
- /var/run/:/host/var/run/
- ./e2e-2Orgs/${FAB_CONFIG_GEN_VERS}/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/:/etc/hyperledger/msp/peer:ro
ports:
- 7051:7051
- 7053:7053
depends_on:
- orderer.example.com
peer1.org1.example.com:
container_name: peer1.org1.example.com
extends:
file: peer-base/peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.org1.example.com
- CORE_PEER_ADDRESS=peer1.org1.example.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7051
# - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
volumes:
- /var/run/:/host/var/run/
- ./e2e-2Orgs/${FAB_CONFIG_GEN_VERS}/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/:/etc/hyperledger/msp/peer:ro
ports:
- 7056:7051
- 7058:7053
depends_on:
- orderer.example.com
- peer0.org1.example.com
peer0.org2.example.com:
container_name: peer0.org2.example.com
extends:
file: peer-base/peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.org2.example.com
- CORE_PEER_ADDRESS=peer0.org2.example.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:8051
# - CORE_PEER_GOSSIP_ORGLEADER=true
- CORE_PEER_LOCALMSPID=Org2MSP
volumes:
- /var/run/:/host/var/run/
- ./e2e-2Orgs/${FAB_CONFIG_GEN_VERS}/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/:/etc/hyperledger/msp/peer:ro
ports:
- 8051:7051
- 8053:7053
depends_on:
- orderer.example.com
peer1.org2.example.com:
container_name: peer1.org2.example.com
extends:
file: peer-base/peer-base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer1.org2.example.com
- CORE_PEER_ADDRESS=peer1.org2.example.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:8051
# - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:8051
- CORE_PEER_LOCALMSPID=Org2MSP
volumes:
- /var/run/:/host/var/run/
- ./e2e-2Orgs/${FAB_CONFIG_GEN_VERS}/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/:/etc/hyperledger/msp/peer:ro
ports:
- 8056:7051
- 8058:7053
depends_on:
- orderer.example.com
- peer0.org2.example.com
configtxlator:
image: hyperledger/fabric-tools${IMAGE_TAG_FABRIC}
ports:
- "7059:7059"
command: /usr/local/bin/configtxlator start
container_name: configtxlator
ccenv:
image: hyperledger/fabric-ccenv${IMAGE_TAG_FABRIC}
- 后面的所有操作是保证按照上一篇文章操作过来的。
2.2、采用非docker方式启动ca服务
此步骤会生成对应的文件
- fabric-ca-server-config.yaml
当前ca节点的相关配置 - fabric-ca-server.db
当前ca节点的sqlite的数据库 - msp
admin管理员的证书私钥
初始化ca服务,-n指定ca名称,-b指定启动的管理员用户名和密码,
# fabric-ca-server init -n ca0 -b admin:adminpw
启动,start会检查 上述文件是否已经生成,若没有会重新生成
# fabric-ca-server start -n ca0 -b admin:adminpw -d
通过fabric-ca-server init会生成以下目录结构
.
|-- ca-cert.pem CA证书文件,自签名 对这个文件做base64编码处理生成CAChain,如果再对生成后的CAChain做base64编码处理就会生成对应的CA证书内容,即ca-cert.pem文件
|-- fabric-ca-server-config.yaml 默认配置文件
|-- fabric-ca-server.db 存放数据的sqlite数据库
`-- msp
`-- keystore 存放个人身份的私钥文件(_sk文件),对应签名证书
`-- 3c163f464eef86178a729eb5b5c0d438c17de16f83f5db14b3cdf2ebe8260b6c_sk
后面的fabric-ca-client步骤统一放在docker方式里,因为操作是一样的
2.3、采用docker方式启动ca服务
按照上面的步骤替换或者修改docker-compose.yaml文件,完成后启动容器
# cd $GOPATH/src/github.com/hyperledger/fabric-sdk-java/src/test/fixture/sdkintegration
当然此处也可只启动ca容器
# sh fabric.sh up
可以看到两个文件夹fabric-ca-peerOrg1-server和fabric-ca-peerOrg2-server,他们分别是两个ca容器执行fabric-ca-server start后生成的文件,里面存放了admin用户的证书及当前ca的sqlite数据库
# cd /etc/hyperledger
设置环境变量,客户端证书存放路径
# export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
登记管理员,将本地配置信息、生成的私钥和证书请求结构等发送到服务器,生成证书,然后会存储到fabric-ca-server.db中,并返回到client端,在本地以文件形式保存下来
# fabric-ca-client enroll -u http://admin:adminpw@localhost:7054
# cd $FABRIC_CA_CLIENT_HOME
可以看到在客户端生成的证书,tree命令自行安装 yum install tree
# tree
接着我们看下sqlite3数据库中的数据
# cd /etc/hyperledger/fabric-ca-peerOrg1-server
查看数据库
# sqlite3 fabric-ca-server.db
展示所有的表
# .tables
这时可以看到有一条admin的数据
# select * from users;
这里可以查询到admin的证书
# select * from certificates;
执行fabric-ca-client enroll后生成的目录结构文件,首先利用本地配置信息(主要是csr字段下的信息)、生成的私钥和证书请求结构,构建EnrollmentRequestNet结构,之后通过Restful接口或enroll发送给服务端;服务器返回消息包括EnrollmentResponse结构信息,解析出相关的文件内容,并保存到本地。
.
|-- admin
| |-- cacerts 存放服务器的证书
| | `-- localhost-7054.pem
| |-- intermediatecerts
| | `-- localhost-7054.pem
| |-- keystore 客户端签名证书的私钥证书
| | `-- d5f8b9f98860a85d7970978526252ffcceaae23e2a7a1ce8c4c09a9496219a67_sk
| `-- signcerts 服务端签发的代表客户端身份的证书
| `-- cert.pem
`-- fabric-ca-client-config.yaml
sqlite3 表解读
- users:当用户fabric-ca-clientregister或者管理员fabric-ca-server init时才会生成对应的用户注册数据
- certificates:用户表对用的证书
- affiliations:组织结构
- properties:配置表
下面我们再生成一个其他用户,以test为例
注册新用户前,必须先执行登记(可以理解为登录)管理员,才能执行新用户注册,name可以修改,此时会返回一个密码,用于后面登录
# fabric-ca-client register --id.name name --id.type user --id.affiliation org1.department1 --id.attrs 'hf.Revoker=true,foo=bar'
去数据库中查询users表和certificates表,结果是在users表中新增了一条test数据,而certificates表并没有新增数据,说明 fabric-ca-client register只是新增注册用户。
# select * from users;
登记用户,并生成相应的证书,替换上面返回的密码
# fabric-ca-client enroll -u http://name:TVCRFuAKIZvo@localhost:7054 -M $FABRIC_CA_CLIENT_HOME/msp
# cd $FABRIC_CA_CLIENT_HOME/
可以看到新生成的证书
# tree
去数据库中查询certificates表,发现生成一条新的证书
# select * from certificates;
以上就是通过fabric-ca-client端生成证书的基本过程,注意在生产环境中因为可能会出现多个组织和多个用户,对个每个组织和用户都有其自己的证书,所以证书管理是个比较大的工作量,所以建议证书目录可以采用cryptogen generate 生成的crypto-config这个目录为准,还是比较清晰的。
这是一个用户的一套完整的证书
[email protected]
|-- msp
| |-- admincerts 当前节点用户证书
| | `-- [email protected]
| |-- cacerts 组织的根节点证书
| | `-- ca.org1.example.com-cert.pem
| |-- keystore 当前节点用户的私钥
| | `-- 6f6a67f77af274c92a615521923b8d833105f2a1906870b6ce2acfe4ed06e15b_sk
| |-- signcerts
| | `-- [email protected]
| `-- tlscacerts
| `-- tlsca.org1.example.com-cert.pem
`-- tls
|-- ca.crt
|-- client.crt
`-- client.key
3、通过Java-sdk端生成证书管理
首先,先保证上一篇文章搭建能正常跑通,接下来的内容主要是根据官方提供的demo(即上一篇java版的demo),进行源码解读。
找到End2endIT这个类中的setup方法,主要是两个方法
- enrollUsersSetup : 主要完成对ca的登记及证书的获取
- runFabricTest : 链码、通道、peer节点初始化等操作
这里我们主要讲 enrollUsersSetup ,以下这几步在HFCAClient中的enroll方法中
(1) 生成一对keypair(公钥和私钥秘钥对)
(2) 用秘钥对中的公钥对用户名进行加密,生成一串密文
(3) 将密文发送登记(enroll)到ca服务端,返回证书链
(4) 对证书链做base64处理获得证书,此时的证书与服务器里certificates表中的证书一致
SampleOrg实体中有admin和peerOrgAdmin,比较容易混淆
admin:admin是client端的管理员,可以理解为组织中的超级管理员;
peerOrgAdmin:是节点管理员