hyper ledger国密改造(1)

密码是解决网络与信息安全最有效、最可靠、最经济的方式,是维护网络与信息安全的核心技术和基础支撑。而密码算法在区块链系统中起着举足轻重的作用,说是没有密码没有BlockChain也不足为过。区块链中涉及到的密码学基础主要包括加解密算法,哈希算法与数字摘要,Merkle树,数字签名和PKI体系等。密码算法大体分为非对称,对称和哈希散列(摘要算法) 三个大的种类,不同种类的密码算法区块链系统的不同的地方都起到重要作用。
1.非对称算法的应用场景
可以看到整个生命周期中,客户端,背书节点,排序节点,提交节点都参与了签名或者验签工作。除此之外:
验证证书链本身的时候,用到了非对称算法相关内容
在建立TLS加密通道时,用到了非对称算法相关内容(值得注意的是,这部分和交易部分是相对独立的)。

使用场景:Propose transactions / Endorse transactions / Create block / TLS / Certificate validate
提议交易/背书交易/创建区块/TLS/证书验证

支持算法:ECDSA / RSA
1.2哈希散列的应用场景
哈希(Hash)算法主要作用是将一段任意长度的数据,经过计算转换成一段定长的数据。

几乎不能通过Hash的结果推导出原文。并且几乎没有可能找到两个不同的信息,对两个信息进行Hash计算之后得到相同的哈希值。
作验证的时候是快速的,但逆向推出明文是基本不可能的。例如:有两条信息,可以很快速的计算出来它们各自的哈希值,并通过哈希值的比对,就可以判定出两条信息是否内容相同,但是几乎不可能从过哈希值计算出信息的原文。
哈希函数的另外一个特性,难题友好性在区块链的工作量证明POW中起到很大作用。
使用场景及支持算法
使用场景: Hash before Signature / Blocks chain each other via hash code / Generate unique id
签名前对消息进行散列/区块通过哈希相互连接/产生独特ID
支持算法 :SHA-256 / SHA-384 / SHA3-256

1.3 对称算法的应用场景

使用场景及支持算法
使用场景: 未在fabric核心中使用

个别例子: chaincode加密示例
这个例子在建议交易的时候,会在瞬态映射里面附上对称加密秘钥和IV,这样chaincode就可以对数据进行加解密处理。保证存储在账本的数据变成只有你和特定peer之间的“小秘密”
支持算法 :AES

国密算法

国密算法是国家通用密码算法的简称,是国家密码管理局制定的自主可控的国产算法,包括SM1、SM2、SM3 、SM4、SM7、SM9、祖冲之密码算法(ZUC)等。
在金融领域目前主要使用公开的SM2、SM3、SM4三种商用密码算法,恰好对应上一章的算法种类,分别为非对称加密算法、哈希算法和对称加密算法:

SM2为基于椭圆曲线密码的公钥密码算法标准,包含数字签名、密钥交换和公钥加密,用于替换RSA / Diffie-Hellman / ECDSA / ECDH 等国际算法。
SM3为密码哈希算法,用于替代MD5 / SHA-1 / SHA-256等国际算法。
SM4为分组密码,用于替代DES / AES等国际算法。
2,3,4的go代码实现https://github.com/tjfoc/gmsm

国密改造
BCCSP-Blockchain Cryptographic Service Provider 区块链密码服务提供者,实现密钥生成,哈希运算,签名验证,加密解密
hyper ledger国密改造(1)_第1张图片
BCCSP接口提供的具体功能:代码路径 :fabric/bccsp/bccsp.go

type KeyGenOpts interface {

	// Algorithm returns the key generation algorithm identifier (to be used).
	Algorithm() string

	// Ephemeral returns true if the key to generate has to be ephemeral,
	// false otherwise.
	Ephemeral() bool
}

// KeyDerivOpts contains options for key-derivation with a CSP.
type KeyDerivOpts interface {

	// Algorithm returns the key derivation algorithm identifier (to be used).
	Algorithm() string

	// Ephemeral returns true if the key to derived has to be ephemeral,
	// false otherwise.
	Ephemeral() bool
}

// KeyImportOpts contains options for importing the raw material of a key with a CSP.
type KeyImportOpts interface {

	// Algorithm returns the key importation algorithm identifier (to be used).
	Algorithm() string

	// Ephemeral returns true if the key generated has to be ephemeral,
	// false otherwise.
	Ephemeral() bool
}

// HashOpts contains options for hashing with a CSP.
type HashOpts interface {

	// Algorithm returns the hash algorithm identifier (to be used).
	Algorithm() string
}

// SignerOpts contains options for signing with a CSP.
type SignerOpts interface {
	crypto.SignerOpts
}

// EncrypterOpts contains options for encrypting with a CSP.
type EncrypterOpts interface{}

// DecrypterOpts contains options for decrypting with a CSP.
type DecrypterOpts interface{}

// BCCSP is the blockchain cryptographic service provider that offers
// the implementation of cryptographic standards and algorithms.
type BCCSP interface {

	// KeyGen generates a key using opts.
	KeyGen(opts KeyGenOpts) (k Key, err error)

	// KeyDeriv derives a key from k using opts.
	// The opts argument should be appropriate for the primitive used.
	KeyDeriv(k Key, opts KeyDerivOpts) (dk Key, err error)

	// KeyImport imports a key from its raw representation using opts.
	// The opts argument should be appropriate for the primitive used.
	KeyImport(raw interface{}, opts KeyImportOpts) (k Key, err error)

	// GetKey returns the key this CSP associates to
	// the Subject Key Identifier ski.
	GetKey(ski []byte) (k Key, err error)

	// Hash hashes messages msg using options opts.
	// If opts is nil, the default hash function will be used.
	Hash(msg []byte, opts HashOpts) (hash []byte, err error)

	// GetHash returns and instance of hash.Hash using options opts.
	// If opts is nil, the default hash function will be returned.
	GetHash(opts HashOpts) (h hash.Hash, err error)

	// Sign signs digest using key k.
	// The opts argument should be appropriate for the algorithm used.
	//
	// Note that when a signature of a hash of a larger message is needed,
	// the caller is responsible for hashing the larger message and passing
	// the hash (as digest).
	Sign(k Key, digest []byte, opts SignerOpts) (signature []byte, err error)

	// Verify verifies signature against key k and digest
	// The opts argument should be appropriate for the algorithm used.
	Verify(k Key, signature, digest []byte, opts SignerOpts) (valid bool, err error)

	// Encrypt encrypts plaintext using key k.
	// The opts argument should be appropriate for the algorithm used.
	Encrypt(k Key, plaintext []byte, opts EncrypterOpts) (ciphertext []byte, err error)

	// Decrypt decrypts ciphertext using key k.
	// The opts argument should be appropriate for the algorithm used.
	Decrypt(k Key, ciphertext []byte, opts DecrypterOpts) (plaintext []byte, err error)
}

可以看出,接口功能大体分成4类,即:

1、秘钥生命周期管理
KeyGen秘钥产生
KeyDeriv秘钥派生
KeyImport秘钥导入
GetKey秘钥导出
2、哈希散列管理
散列哈希运算
GetHash获取哈希功能
3、签名验证管理
签名功能
验证验签功能
4、加解密功能
加密加密功能
Decrypt解密功能
Fabric的密码算法支持都是依赖上一页中的四类接口完成的,开发者可以设计不同的CSP来提供不同形式的密码算法支持。现在Fabric提供了两种CSP可供选择:

SW模式 : 软件实现方案,通过golang的加密库,提供不同类型的算法软件实现
pcks11模式 : 硬件对接方案,RSA提供的一套标准密码接口API,为实现了对应api接口的设备提供支持
对于国密的支持,可以自己重新设计CSP,也可以根据上面两个现有模块进行定制支持。
如何实现国密支持?
最后一部分,介绍布国密支持的具体实现思路。

**

国密支持关注点

**
首先了解一下进行国密支持需要关注哪几个方面内容。分为4个层次:

BCCSP
算法实现
X509证书支持
秘钥相关内容。
第一点BCCSP前面已经介绍了,可以通过改造sw和pkcs11部分工作,提供软件和硬件层面的支持。sw提供一套密码算法集,可以考虑在中间加入国密算法接口支持。

第二点是国密算法具体的实现,上一章最后已经说过了,直接用别人的就可以了。

第三点是X509证书支持,Fabric中证书创建和解析相关是加入Golang中的X509证书模块完成的,但是现在x509模块只支持RSA和ECDSA两种算法模式,所以如果直接引入原版的X509证书解析的话,在证书国密支持方面会比较棘手,这个问题可以通过重写x509文件或者在Fabric重新定义x509证书生成解析方法来解决。

X509里面会根据OID来指定所使用的签名算法,签名参数等信息,这部分可以参考“GMT 0015-2012”规范附件部分定义。

第四点是秘钥相关部分,其中包括通过证书封装的公匙部分,还有本地存储的私钥部分。特别注意到SW中算法是可以通过秘钥的类型来动态选择的,并且能够更灵活应用,带格式的秘密存储是有必要的。比如现在通过pkcs1来存储RSA密钥,通过pkcs8来存储ECDSA密钥,SM2和ECDSA结构类似,也可以参考使用PKCS8来进行格式存储。
国密支持解决思路
前面介绍了国密支持所需要关注的问题。除了BCCSP层面外,算法实现和X509证书支持Fabric是是直接引用的golang下面的标准库来支持的。

而标准库并没有对国密算法进行支持,所以这里引出了两种思路。

定制化golang环境: 将算法实现和X509国密支持部分放在golang的标准库上,这样Fabric层面的适配就会少很多。这种缺点的是golang部分需要做定制,特别是牵扯到用户环境还要同时考虑到本地和docker环境两种方式下,golang层面应该如何完成适配。

一切交给Fabric: 把算法实现和X509的证书支持都放在Fabric层面来做。这种方式的好处是不用动golang的标准库,所有工作都收敛到Fabric上。但是缺点是X509的证书部分需要在上层做定制,所有引入证书的地方,都需要做调整。代码也会有较多冗余部分。

下面讲下两种方法的实现思路。
这种方法好处在于,能够在不影响整个Fabric架构的前提下,更好的完成国密支持,并且可以进行动态配置需要使用的算法,不失灵活性。hyper ledger国密改造(1)_第2张图片上图中所示为整个国密支持中,Fabric和golang lib层面所需要定制的部分。黄色代表需要修改部分,红色代表新增部分。在这里插入图片描述
上层为Fabric需要处理的模块,主要集中在BCCSP部分。下层为golang层面需要处理的模块,主要集中在crypto中。

如果想在golang层面做支持的话,那么整个系统的构建环境就需要做一定的定制:

对于本地的构建环境来说,需要将golang替换成国密版本支持的
对于docker相关的,需要更改docker image中golang层的支持.Fabric中,对golang的支持,是放在fabric-baseimage中的.baseimage中,将特定版本的环境打包到镜像中,提供底层的支持。

baseimage相关内容可以从官方仓库https://github.com/hyperledger/fabric-baseimage了解。

.2、一切交给Fabric
目前我采用的是这种方案。

先说不好的地方:

代码升级不方便,因为需要Fabric的代码进行改造,后续官方版本增加新功能需要同步进行代码改造。据目前Fabric版本更新差异来看,版本之间,存在大量重构,做迁移比较麻烦。
相比之下,如果采用定制化golang环境,由于升级go版本需求频率低于升级Fabric版本,且改动golang标准库代码相对轻松,结构清晰,在升级迁移的时候可以花费少量经历,更为灵活。。
好处是:

比定制化golang环境少打包.baseimage的docker镜像
相对改变golang标准库来说,在多个golang项目存在的情况下更加安全
完全在Fabric层实现改造,需要从以下三个方面着手:

其一,把国密的库进行移植,封装gm-crypto;
其二,扩展Fabric现有的bccsp模块;
其三,修改x509证书相关的地方。
综合考虑下两种实现方法,后期考虑做定制化golang方案

外围支持
除此之外,作为整个系统来看,Fabric做国密支持,也少不了外围的支持,包括Fabric-CA和Fabric-SDK。
1 Fabric-CA国密改造
hyper ledger国密改造(1)_第3张图片
Fabric-CA主要是为了实现对加入联盟链的成员的身份控制以及数据生成保管。
CA可以考虑使用现有的国密CA系统,也可以考虑通过Fabric-CA来做搭建,目前采用后一种方案。

改造CA主要改动如下几个包:

Lib:主要是接口的实现,主要在解析申请证书请求以及签发证书流程要替换为国密算法;
Util:该包数据工具类,主要在证书的编解码等操作中扩展国密算法;
Vendor:因为CA沿用Fabric中的BCCSP套件,所以需要替换对Fabric的包的引用,提供对国密算法的支持。
2.Fabric-SDK国密改造
Fabric-SDK主要是一个区块链的大框架,每一个应用发布上去,可以调用我们提供的SDK的功能。而Client-SDK现在有很多种版本,所以有一些工作量在里面。好在每个版本的密码服务套件都是插件化的,可以从以下几个方面着手:

API:主要是接口的定义
PKG:主要是接口的实现
Vendor:替换对Fabric包的引用,提供对国密算法的支持,这一点同CA类似

你可能感兴趣的:(hyper ledger国密改造(1))