BCCSP(blockchain crypto service provider):为fabric项目提供各种加密技术,签名技术,MSP服务模块中就使用到了BCCSP。
基本架构
BCCSP的基本架构如下所示:

从大致的层次上划分,可分为三层。
BCCSP层
- 从包结构的角度来看,这一层指的是
package bccsp。 - 从文件的角度来看,主要包括bccsp/目录下的
*.go文件。
这一层主要将BCCSP的一些特征抽象为interface,只定义方法而不定义实现,实现部分交给其struct具体实现。在这一层中,含interface的文件为bccsp.go和keystore.go;含struct的文件为aesopts.go,ecdsaopts.go,hashopts.go,opts.go,rsaopts.go,sm2opts。
bccsp.go
该文件中的interface,可分为两类。一类是bccsp的interface,另一类是第一类中传入参数的interface。

第一类的interface如上图所示。显然,红框的opts表示要传入的参数,并未实现。
下面,对之前的接口传入的参数的定义,同样进行接口操作:
以上属于Go中结构的嵌套。


上述文件十分重要,所以梳理出这个文件的整体结构:

keystore.go
另一个有interface的文件是keystore.go文件。
KeyStore表示加密密钥的存储系统。- 允许存储和检索
bccsp.Key对象。 KeyStore可以是只读的,在这种情况下,StoreKey将返回一个错误。
具体如下所示:

以上的interface部分,只是定义了接口并未对其进行实现,实现部分由将struct实现。
aesopts.go
该文件定义了分组密码算法。要注意的是struct的书写要符合之前interface的定义:
AES128KeyGenOpts包含生成密钥长度为128位的密钥生成选项:

同理,该文件包含生成密钥长度为192位和256位的密钥生成选项:


ecdsaopts.go、rsaopts.go、sm2opts.go与之同理。
hashopts.go
要说明的是hashopts.go。这个与之前不同之处在于,只需要返回算法标识符:


还有一个函数GetHashOpts,根据传入的hashFunction进行识别:

opts.go
opts.go文件中定义了以上所有算法的常量及所有的struct。下面展示部分常量:



还有新的一些struct,添加了对密钥格式的选项,定义了整体的密钥系统,以sm2为例:





除了以上对于算法完整性的实现,也包含了对其他算法的实现。
HMACDeriveKeyOpts包含用于HMAC密钥派生的选项:

HMACImportKeyOpts包含用于导入HMAC密钥的选项。

SHAOpts包含用于计算SHA的选项。

X509PublicKeyImportOpts包含从x509证书导入公钥的选项:

小结
-
以上为第一层BCCSP的具体介绍
-
包括接口interface和结构体struct
-
这一层主要将BCCSP的一些特征抽象为interface,只定义方法而不定义实现,实现部分交给其struct具体实现。
factory层
-
从包结构的角度来看,指
package factory。 -
从文件的角度来看,主要包括bccsp/ factory目录下的
*.go文件。
介绍的顺序是从底层调用说起,大致可分为是否包含pkcs11的实现。
opts.go
此文件是整个factory层中最底层调用,包含以下两个函数:
-
GetDefaultOpts为Opts提供默认实现,每次都会返回一个新实例。 -
FactoryName返回提供者的名称。

factory.go
定义了BCCSPfactory的接口使其获取实例,对BCCSP的初始化和获取:




nopkcs11.go
此文件介绍了不使用pkcs11而只使用sw的方式。其中:
-
在使用工厂接口之前,必须调用
InitFactories。 -
可以接受使用
config = nil进行调用,这种情况下会使用一些默认值。 -
只有在找不到
defaultBCCSP时才返回错误。


GetBCCSPFromOpts返回根据输入中传递的选项创建的BCCSP。

swfactory.go
SoftwareBasedFactoryName是基于软件的BCCSP实现的工厂名称:

SWFactory是基于软实现的BCCSP的工厂。此处定义了空结构体,可作为函数接收者来使用。

SwOpts包含SWFactory的选项。

FileKeystoreOpts定义了密钥存储选项的文件格式,可为pem。

pkcs11.go
pkcs11是在nopkcs11的基础上,加入了pkcs11的实现,其工厂选择如下,增加了pkcs11的选项:

- 与
nopkcs11相比,初始化略有不同,增加了pkcs11:

GetBCCSPFromOpts返回根据输入中传递的选项创建的BCCSP。略有不同的地方是增加了pkcs11:

pkcs11factory.go
PKCS11BasedFactoryName是基于hsm的BCCSP实现的工厂名称

类似之前swfactory,定义了空的结构体以及Name和Get函数


综上,整个factory结构可如下表示:

这一层主要定义了存储BCCSP实体的全局变量,和初始化这些变量的初始函数。BCCSP采用了工厂模式的设计思想,分为软件加密和硬件加密两种模式,在这一层决定使用哪种加密模式。
impl层
impl层简单的说就是对之前定义的BCCSP真正意义上的实现。
其结构体如下:

该结构体定义了8种行为的执行者集合,用Map存储不同的执行者。
此处8个定义的相似度极高,以keyGenerators说明。

从Map中根据Key的类型获取对应的KeyGenerator(具体是哪个struct),然后调用不同KeyGenerator中的KeyGen()函数(此时函数的具体实现根据map中的KeyGenerator是哪一个struct决定)。
Map中的映射关系,在impl中有定义。先对Map进行实例化。在向其中添加对应的key和value,以下为impl文件中的New()方法部分截取

根据curve的不同,调用不同的KeyGenerator,其中SM2KeyGenOpts在bccsp\opts.go下:

sm2KeyGenerator在sw\keygen下:

KeyGenerator接口如下:

根据接口,进行struct实例化,并选择调用。

小结
总的来说,impl实现了BCCSP接口,通过impl中各种动作(比如keygen)的执行者(对应keyGenerator ),传入不同的key(可以是不同的Key struct)值,得到对应的struct,从而执行相应的操作。上述代码在这