fabric 国密改造
代码仓库(限制权限的私人仓库)
国密改造补丁:ssh://gitlabs.my118.com:9022/wanghongxing/fabric-sm-patch.git
国密版代码:ssh://git@gitlabs.my118.com:9022/wanghongxing/fabric.git
java sdk 国密版代码仓库 ssh://git@gitlabs.my118.com:9022/blockchain/fabric-sdk-java.git
fabric国密改造包括:源代码改造、sdk改造、ca改造。
Fabric源代码改造的大致清单 主要涉及一下目录及文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 bccsp/factory/gmfactory.go bccsp/factory/nopkcs11.go bccsp/factory/pkcs11.go bccsp/gm/fileks.go bccsp/gm/impl.go bccsp/gm/keys.go bccsp/gm/sm2.go bccsp/gm/sm2key.go bccsp/gm/sm3sig.go bccsp/sm2opts.go bccsp/utils/keys.go cmd/common/signer/signer.go common/tools/cryptogen/ca/generator.go common/tools/cryptogen/ca/generatorsm.go common/tools/cryptogen/csp/csp.go common/tools/cryptogen/csp/cspsm.go common/tools/cryptogen/main.go common/tools/cryptogen/mainsm.go common/tools/cryptogen/msp/generator.go common/tools/cryptogen/msp/generatorsm.go core/chaincode/shim/ext/attrmgr/attrmgr.go core/chaincode/shim/ext/cid/cid.go core/chaincode/shim/ext/cid/interfaces.go core/common/validation/msgvalidation.go msp/cert.go msp/identities.go msp/mspimpl.go msp/mspimplsetup.go msp/mspimplvalidate.go vendor/github.com/wanghongxing/crypto/sm/sm2/ vendor/github.com/wanghongxing/crypto/sm/sm3/ vendor/github.com/wanghongxing/crypto/sm/sm4/ vendor/github.com/wanghongxing/crypto/x509/
大致功能 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 bccsp/factory/ bccsp/gm/ bccsp/sm2opts.go bccsp/utils/keys.go core/common/validation/msgvalidation.go msp/cert.go msp/identities.go msp/ vendor/github.com/wanghongxing/crypto/sm/ vendor/github.com/wanghongxing/crypto/x509/ cmd/common/signer/signer.go common/tools/cryptogen/ core/chaincode/shim/ext/attrmgr/attrmgr.go core/chaincode/shim/ext/cid/cid.go core/chaincode/shim/ext/cid/interfaces.go
fabric国密补丁工程 fabric 官方源代码 fabric1.4.2 下能正常apply入原始项目中,到了fabric1.4.4以后,msp/mspimplvalidate.go 文件不能打入布丁,手动修改后正常.
为了保证以后版本能够正常打入官方发布版本,决定每个版本进行修订,修订包名称定为:
fabric-x.x.x-000xxxx.patch
同时依赖的crypto/sm crypto/x509决定克隆到自己的 git 目录下,确保版本稳定。
1.4.4 补丁 整理后三个patch包如下:
1 2 3 fabric-1.4.4-0001-china-crypto-standards-support-1.4.4.patch fabric-1.4.4-0002-gm-ecdsa-chaincode.patch fabric-1.4.4-0003-change-discover-support-gm.patch
分别完成了基本的国密支持、chaincode中证书支持国密、discover中证书支持国密。
使用方法 从fabric官方签出1.4.4的代码
然后把patch文件复制到fabric父目录下,然后执行
1 2 3 git am ../fabric-sm-patch/fabric-1.4.4-0001-china-crypto-standards-support-1.4.4.patch git am ../fabric-sm-patch/fabric-1.4.4-0002-gm-ecdsa-chaincode.patch git am ../fabric-sm-patch/fabric-1.4.4-0003-change-discover-support-gm.patch
1.4.6/1.4.7 版本 整理后有一个patch包
1 fabric-1.4.7-0001-china-crypto-standards-support-1.4.7.patch
使用方法 从官方签出1.4.7代码(注,1.4.7还没有打tag,所以暂时用release-1.4)
1 git chekcout release-1.4
或者(注,1.4.7还没有打tag,所以暂时用v1.4.6)
然后把patch文件复制到fabric父目录下,然后执行
1 git am ../fabric-sm-patch/fabric-1.4.7-0001-china-crypto-standards-support-1.4.7.patch
fabric国密版本编译 编译环境建立 fabirc的编译需要在ubuntu虚拟机里进行编译,所以先要安装virtualbox和vagrant,安装完以后理论上就可以进入devenv目录目录运行虚拟机。
但是,因为我们伟大的qiang,所以要想编译环境运行好,就先要装fan qiang软件。
我安装了:
小飞机Shadowsocks,这个是作为翻墙用的,但是它只监听127.0.0.1,为了让虚拟机的软件用,我们还要转另外一个东东“privoxy”,让这个东东监听ipv4的端口,我用它监听8118端口,
1 2 3 4 brew install privoxy listen-address 0.0.0.0:8118 forward-socks5 / localhost:1080 .
然后修改fabric 的 devenv/Vagrant文件,在这行Vagrant.configure('2') do |config|
后面添加着两行:
1 2 # config.proxy.http = "http://10.0.0.9:8118/" # config.proxy.https = "http://10.0.0.9:8118/"
注意,#去掉以后起作用,加上就不起作用了,为什么要说加上#不起作用呢?不加不久完了吗?
问题就在这里:
下载github google之类的东东,需要打开;
下载ubuntu系统之类的软件,需要关闭;
就是这么麻烦,如果你的fan qiang线路特别好,就一直打开。否则最简单的就是关闭的时候执行到一半不行了,就打开;打开的时候执行到一半不行了,就关闭。周而复始吧~(fuck)
建好了墙,按理说就可以直接开启虚拟机了,慢~先把Vagrant中
1 2 3 4 5 6 $script = <<SCRIPT set -x echo "127.0.0.1 couchdb" | tee -a /etc/hosts cd #{SRCMOUNT}/fabric/devenv ./setup.sh SCRIPT
其中./setup.sh这行注释掉,因为在虚拟机启动的时候它就调用,出错了后你都不知道干啥好,出不去进不来的,就像被卡在门缝中一样。
把它注释掉后,进入虚拟机后自己手动执行。
下面启动虚拟机
第一次的话需要下载镜像,启动完成后执行进入。
然后开始慢慢的执行devenv/setup.sh
执行出错后,慢慢手动开关代理,然后粘贴命令执行就行,最后这个东西执行完了之后,编译环境就算创建完了。
编译fabric执行程序 直接执行:
这个会把fabric 可执行程序编译好后放在.build/bin/目录下,包括常用的cryptogen configtxgen configtxlator
编译docker镜像 直接执行
这个一般网络不行都会出错,出错以后如果是下载github google之类的错误就打开代理,否则就关闭代理。
如果提示找不到.build/xxx/gotools/目录下的什么文件,这就是在代理切换的过程中,因为脚本文件把创建目录作为执行完的标记,所以没有执行成功下次也不会执行。解决办法就是删除它提示找不到文件的那个目录,大概率就是.build/docker/gotools目录。反正就是github google需要qiang,ubuntu系统文件不能用qiang,因为这些网站dns失败,我也没有细究,手动解决就OK。
打包镜像文件 为了方便大家使用,编译好之后需要把可执行程序和镜像保存起来供大家用,如下命令把所有可执行文件复制到fabric/devenv/bin,然后把镜像保存到:
fabric/devenv/fabric-gm-1.4.7-20200506.tar.gz
1 2 3 4 5 mkdir /vagrant/bin/cp .build/bin/* /vagrant/bin/docker save $(docker images | sed '1d' | awk '{print $1 ":" $2 }' ) | \ gzip -c > /vagrant/fabric-gm-1.4.7-20200506.tar.gz
java sdk国密改造 代码仓库 ssh://git@gitlabs.my118.com:9022/blockchain/fabric-sdk-java.git
改造思路 fabric java sdk使用 bouncycastle 作为加密库,因为bouncycastle 本身已经支持国密的算法,所以只用在fabric java sdk中添加对加密算法、hash算法、证书类型的判断即可。
但是: 因为bouncycastle必须手动加载早java security系统中,所以应用程序应该在启动的时候调用如下代码加载Security.addProvider(new BouncyCastleProvider());
。否则就会提示类似于不可识别的证书、不支持的算法等莫名其妙的错误提示。
Config改造 java sdk启动的时候在 config.properties 文件查找配置选项,比较有用的几个是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 org.hyperledger.fabric.sdk.crypto.security_level = 256 org.hyperledger.fabric.sdk.crypto.hash_algorithm = SHA2 org.hyperledger.fabric.sdk.crypto.default_signature_algorithm = SHA256withECDSA
上面的配置是缺省的椭圆曲线配置,为了满足国密支持,我们需要支持如下配置
1 2 3 org.hyperledger.fabric.sdk.crypto.default_signature_algorithm = SM3withSM2 org.hyperledger.fabric.sdk.hash_algorithm = SM3 org.hyperledger.fabric.sdk.security_level =255
security_level=255 是为了避免跟椭圆曲线冲突。
相应的我们需要在Config.java文件中修改加密曲线配置,增加255=sm2p256v1
1 2 3 defaultProperty(SECURITY_CURVE_MAPPING, "256=secp256r1:384=secp384r1:255=sm2p256v1" );
这样系统看到security_level=255
就知道使用 sm2p256v1 加密曲线。
加密套件修改 验证证书 在验证证书的时候CertPathValidator 不能使用缺省的,需要使用bouncycastle 提供的。
1 2 3 4 CertPathValidator.getDefaultType()); CertPathValidator certValidator = CertPathValidator.getInstance(\ CertPathValidator.getDefaultType(), "BC" );
配置哈希算法 需要添加sm3的判断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void setHashAlgorithm (String algorithm) throws InvalidArgumentException { if (isNullOrEmpty(algorithm) || !("SHA2" .equals(algorithm) || "SHA3" .equals(algorithm) || "SM3" .equals(algorithm) )) { throw new InvalidArgumentException ("Illegal Hash function family: " + algorithm + " - must be either SHA2 or SHA3 or SM3" ); } hashAlgorithm = algorithm; }
椭圆曲线证书转换的时候 标准算法转换的时候有这么一句,在国密里面要注释掉,否则验证签名会失败。
1 sigs = preventMalleability(sigs, curveN);
证书工厂配置 修改为之支持x509,由 bouncycastle 提供。
1 2 // cf = CertificateFactory.getInstance(CERTIFICATE_FORMAT); cf = CertificateFactory.getInstance("X509", "BC");
增加固定的sha256 因为在提交交易的时候,交易的哈希是固定的sha256,但做签名的时候根据证书使用,所以在这里添加一个sha256,在交易提交的时候调用
1 2 3 4 5 6 7 8 9 //whx 做一个固定的sha256哈希 @Override public byte[] hashSha256(byte[] input) { Digest digest = new SHA256Digest(); byte[] retValue = new byte[digest.getDigestSize()]; digest.update(input, 0, input.length); digest.doFinal(retValue, 0); return retValue; }
提交交易的时候:
1 2 3 public TransactionContext (Channel channel, User user, CryptoSuite cryptoPrimitives) { byte [] txh = cryptoPrimitives.hashSha256(comp.toByteArray());
配置文件 config.properties 作为java sdk的配置文件,缺省在jar执行文件的当前目录,如果没有,就是按照标准的椭圆曲线证书支持;否则,就必须单独做配置文件,如下是标准的国密算法配置内容:
上面的配置是缺省的椭圆曲线配置,为了满足国密支持,我们需要支持如下配置
1 2 3 org.hyperledger.fabric.sdk.crypto.default_signature_algorithm = SM3withSM2 org.hyperledger.fabric.sdk.hash_algorithm = SM3 org.hyperledger.fabric.sdk.security_level =255