蜗牛讲-fabric原理之证书生成
蜗牛讲技术,满满的都是干货,你值得关注。
之前我们讲了通过
./byfn.sh generate
的作用是 用于生成fabric网络中的组件公私钥证书信息以及初始的交易信息。如果只是要生成相关证书信息,也可以直接使用fabric提供的cryptogen 工具完成这一步工作,命令如下:
cryptogen generate --config=./crypto-config.yaml
具体是怎么生成的,由crypto-config.yaml配置文件决定。我们将详细介绍是如何产生证书文件,已经生成了哪些证书文件。
读取crypto-config.yaml配置信息
cryptogen工具会读取 crypto-config.yaml中的所有配置,把内容解析到名为 OrdererOrgs和 PeerOrgs的数据结构中,其实这两个对应的就是crypto-config.yaml 中的两个根节点或是一级节点(这里是把yaml看成和xml一样的文件格式),这两个的类型为OrgSpec,类型的定义如下:
type OrgSpec struct {
Name string `yaml:"Name"`
Domain string `yaml:"Domain"`
EnableNodeOUs bool `yaml:"EnableNodeOUs"`
CA NodeSpec `yaml:"CA"`
Template NodeTemplate `yaml:"Template"`
Specs []NodeSpec `yaml:"Specs"`
Users UsersSpec `yaml:"Users"`
}
这里也可以看出OrdererOrgs和 PeerOrgs是由哪些子节点组成的(这里说的节点是 文件内容里的标签节点,而不是fabric里所的网络节点)
解析PeerOrgs
假如当前的一个PeerOrgs配置如下:
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
-
根据Template的count数量(这个count决定了这个org2.example.com的域名下有多少个节点),生成相应数量的hostname, 并把 这些hostname信息放在specs下,可以看成会生成如下格式,以yaml文件格式表示:
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
Specs:
-Hostname:peer0
-Hostname:peer1
-
处理yaml:Specs节点的配置
1. 首先会根据提供的模板
"{{.Hostname}}.{{.Domain}}"
生成两个CommonName :
peer0.org2.example.com
peer1.org2.example.com。
2. 之后处理SAN (Subject Alternative Names), SAN是一个可选配置,主要是用于指定要生成的X509中的一个或是多个SAN,可以为hostname, commonname 或是IP地址形式。处理规则是:如果有指定CommonName, 就用指定的CommonName为解析模板,否则就是用默认的CommonName解析模板,数据源为hostName和 Domain, 这个例子中就为 peer0 (peer1)和 org2.example.com。 默认的解析模板为:
"{{.Hostname}}.{{.Domain}}"
例子中由于没有指明CommonName,所以直接用默认模板,解析结果为:
peer0.org2.example.com
peer1.org2.example.com
3. 之后是拼接SANS,根据上面的解析结果,默认设置的SANS为hostname和 CommonName, 也就是peer0(peer1)和peer0.org2.example.com (peer1. org2.example.com)。如果配置文件上有指定其他的CommonName,就把这两个加入到指定的CommonName中,一起作为SANS,在生成正式的时候使用。
下面是一个完整的Specs的示例,配置的时候可以参考
Specs:
- Hostname: foo # implicitly "foo.org1.example.com"
CommonName: foo27.org5.example.com
SANS:
- "bar.{{.Domain}}"
- "altfoo.{{.Domain}}"
- "{{.Hostname}}.org6.net"
- 172.16.10.31
- Hostname: bar
- Hostname: baz
-
处理yaml:CA 的配置。如果没有指定ca配置,默认的ca的hostname为ca, 其它处理过程和yaml:Specs完全一致。
下面是CA配置的一个完整示例:
CA:
Hostname: ca # implicitly ca.org1.example.com
Country: US
Province: California
Locality: San Francisco
OrganizationalUnit: Hyperledger Fabric
StreetAddress: address for org # default nil
PostalCode: postalCode for org # default nil
生成证书和公私钥
-
生成节点的CA证书。创建 crypto-config/peerOrganizations/{domain}/ca 目录,例子中为org.example.com。根据yaml:CA的配置,使用fabric的加密服务提供程序(bccsp),生成P256的椭圆加密算法的私钥和公钥,然后使用ca中指定的 country, province,common name等信息生成包含公钥信息的ca.org2.example.com-cert.pem 文件
-
生成tls的证书。同上面的ca证书,只不过tls证书中的common name为 tlsca, 而上面的ca证书中的common name为ca
-
把ca下的证书和tls证书导入到crypto-config/peerOrganizations/org2.example.com/msp/cacerts和crypto-config/peerOrganizations/org2.example.com/msp/tlscacerts下
-
如果设置了EnableNodeOUs,就在msp下生成config.yaml文件
-
根据配置的节点信息,为每一个节点创建本地的msp, 包括两部分:
第一部分为创建peers/{commonName}/msp 。例子中的就为:peers/peer0.org2.example.com/msp
peers/peer1.org2.example.com/msp
这部分证书都是通过csp产生一个keystore私钥,然后使用这个私钥对应的公钥生成admincerts,cacerts,signcerts 的证书。而cacerts下的证书和peerOrganizations/{domain}/ca下ca.{domain}-cert.pem是完全一样的。tlscacerts 下的证书也和{domain}下其他的tlscacerts文件夹下的证书完全一致。
第二部分是生成peers/{commonName}/tls目录下的公私钥证书,例子中为:peers/peer0.org2.example.com/tls
peers/peer1.org2.example.com/tls
这部分证书是重新生成的。包含一个ca证书,一个公钥证书和一个私钥证书。如果节点类型为 client,就生成客户端的公钥证书和私钥证书,如果节点类型为orderer或是peer类型,就生成服务端相关的证书。私钥存在serer.key内。ca.crt是把证书内容通过x509.ParseCertificate转换得到,而server.crt是通过把写入了证书内容的pem文件直接重命名成crt文件得到。
-
根据配置的yaml:Users下的yaml:Count 的数目,来为每个用户生成用户信息,生成的内容和步骤和3.5完全一致。用户名的生成规则为:从1开始循环递增到Count, 每个用户名为:"User" + index + @ + Domain , 例子中就为:User1@org2.example.com。默认会有一个admin用户。
-
把用户下的signcerts 作为admincerts copy到org1.example.com/msp/admincerts和org1.example.com/peers/{CommonName}/admincerts下。
到此,节点相关的所有证书信息已经生成。接下来是生成orderer相关的证书信息,过程和节点完全类似,这里就不累赘描述了。
覆盖完整的区块链知识体系,从入门到源码,这里有真正想要的区块链技术,欢迎大家关注微信号:蜗牛讲技术。扫下面的二维码
作者: shaotine(蜗牛)
公众号:蜗牛讲技术
出处: http://www.cnblogs.com/StephenWu/
关注公众号:蜗牛讲技术。 满满的都是干货
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.