0%

fabric 国密改造

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中功过SW方式切换成国密
bccsp/factory/
#基本国密bccsp库
bccsp/gm/
#bccsp中增加sm2的常量
bccsp/sm2opts.go
bccsp/utils/keys.go
#消息验证增加国密
core/common/validation/msgvalidation.go
#msp证书对国密的支持
msp/cert.go
msp/identities.go
msp/
#国密算法,第三方拿过来修改了包名
vendor/github.com/wanghongxing/crypto/sm/
#国密x509证书 ,第三方拿过来修改了包名
vendor/github.com/wanghongxing/crypto/x509/
#discover国密支持
cmd/common/signer/signer.go
#生成证书工具改造
common/tools/cryptogen/
#chaincode中访问证书支持国密
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的代码

1
git checkout v1.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)

1
git checkout 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
#修改配置文件vim /usr/local/etc/privoxy/config
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这行注释掉,因为在虚拟机启动的时候它就调用,出错了后你都不知道干啥好,出不去进不来的,就像被卡在门缝中一样。

把它注释掉后,进入虚拟机后自己手动执行。

下面启动虚拟机

1
vagrant up

第一次的话需要下载镜像,启动完成后执行进入。

1
vagrant ssh

然后开始慢慢的执行devenv/setup.sh

执行出错后,慢慢手动开关代理,然后粘贴命令执行就行,最后这个东西执行完了之后,编译环境就算创建完了。

编译fabric执行程序

直接执行:

1
make native

这个会把fabric 可执行程序编译好后放在.build/bin/目录下,包括常用的cryptogen configtxgen configtxlator

编译docker镜像

直接执行

1
make 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

# security level determines the elliptic curve used to generate keys. Valid values are 256 ( curve is P-256 )
# and 384 ( curve is secp384r1 )
org.hyperledger.fabric.sdk.crypto.security_level = 256
# hash algorithm determines the message digest used when creating a signature. Valid values are
# SHA2 ( digest is SHA-256 ) and SHA3 ( digest is SHA-3 )
org.hyperledger.fabric.sdk.crypto.hash_algorithm = SHA2
# The format for the certificate PEM files used by the SDK, Fabric and Fabric-ca components.
# currently X.509 is the only valid format supported. This entry is here to allow for future support
# org.hyperledger.fabric.sdk.crypto.certificate_format = X.509
# The algorithm used to generate a signature. Valid values are listed in the JCA Standard Algorithm Name Documentation
# e.g. http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature
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");
defaultProperty(SECURITY_CURVE_MAPPING, "256=secp256r1:384=secp384r1:255=sm2p256v1");

这样系统看到security_level=255 就知道使用 sm2p256v1 加密曲线。

加密套件修改

验证证书

在验证证书的时候CertPathValidator 不能使用缺省的,需要使用bouncycastle 提供的。

1
2
3
4
//CertPathValidator certValidator = CertPathValidator.getInstance(
CertPathValidator.getDefaultType()); // PKIX
CertPathValidator certValidator = CertPathValidator.getInstance(\
CertPathValidator.getDefaultType(), "BC"); // PKIX

配置哈希算法

需要添加sm3的判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void setHashAlgorithm(String algorithm) throws InvalidArgumentException {

// whx: 添加SM3

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