BCCSP,全称Blockchain Cryptographic Service Provider,即区块链加密服务提供者,为Fabric提供加密标准和算法的实现,包括哈希、签名、校验、加解密等。
BCCSP通过MSP(即Membership Service Provider成员关系服务提供者)给核心功能和客户端SDK提供加密算法相关服务。
另外BCCSP支持可插拔,提供多种CSP,支持自定义CSP。目前支持sw和pkcs11两种实现。
代码在bccsp目录,bccsp主要目录结构如下:
BCCSP接口(区块链加密服务提供者)定义如下:
type BCCSP interface {
KeyGen(opts KeyGenOpts) (k Key, err error) //生成Key
KeyDeriv(k Key, opts KeyDerivOpts) (dk Key, err error) //派生Key
KeyImport(raw interface{}, opts KeyImportOpts) (k Key, err error) //导入Key
GetKey(ski []byte) (k Key, err error) //获取Key
Hash(msg []byte, opts HashOpts) (hash []byte, err error) //哈希msg
GetHash(opts HashOpts) (h hash.Hash, err error) //获取哈希实例
Sign(k Key, digest []byte, opts SignerOpts) (signature []byte, err error) //签名
Verify(k Key, signature, digest []byte, opts SignerOpts) (valid bool, err error) //校验签名
Encrypt(k Key, plaintext []byte, opts EncrypterOpts) (ciphertext []byte, err error) //加密
Decrypt(k Key, ciphertext []byte, opts DecrypterOpts) (plaintext []byte, err error) //解密
}
//代码在bccsp/bccsp.go
Key接口(密钥)定义如下:
type Key interface {
Bytes() ([]byte, error) //Key转换成字节形式
SKI() []byte //SKI,全称Subject Key Identifier,主题密钥标识符
Symmetric() bool //是否对称密钥,是为true,否则为false
Private() bool //是否为私钥,是为true,否则为false
PublicKey() (Key, error) //返回非对称密钥中的公钥,如果为对称密钥则返回错误
}
//代码在bccsp/bccsp.go
KeyStore接口(密钥存储)定义如下:
type KeyStore interface {
ReadOnly() bool //密钥库是否只读,只读时StoreKey将失败
GetKey(ski []byte) (k Key, err error) //如果SKI通过,返回Key
StoreKey(k Key) (err error) //将Key存储到密钥库中
}
//代码在bccsp/keystore.go
KeyGenOpts接口(密钥生成选项)定义如下:
//KeyGen(opts KeyGenOpts) (k Key, err error)
type KeyGenOpts interface {
Algorithm() string //获取密钥生成算法的标识符
Ephemeral() bool //要生成的密钥是否为暂时的,如果为长期密钥,需要通过SKI来完成存储和索引
}
//代码在bccsp/bccsp.go
KeyDerivOpts接口(密钥派生选项)定义如下:
//KeyDeriv(k Key, opts KeyDerivOpts) (dk Key, err error)
type KeyDerivOpts interface {
Algorithm() string //获取密钥派生算法标识符
Ephemeral() bool //要派生的密钥是否为暂时的
}
//代码在bccsp/bccsp.go
KeyImportOpts接口(导入选项)定义如下:
//KeyImport(raw interface{}, opts KeyImportOpts) (k Key, err error)
type KeyImportOpts interface {
Algorithm() string //获取密钥导入算法标识符
Ephemeral() bool //要生成的密钥是否为暂时的
}
//代码在bccsp/bccsp.go
HashOpts接口(哈希选项)定义如下:
//Hash(msg []byte, opts HashOpts) (hash []byte, err error)
type HashOpts interface {
Algorithm() string //获取哈希算法标识符
}
//代码在bccsp/bccsp.go
SignerOpts接口(签名选项)定义如下:
//Sign(k Key, digest []byte, opts SignerOpts) (signature []byte, err error)
//即go标准库crypto.SignerOpts接口
type SignerOpts interface {
crypto.SignerOpts
}
//代码在bccsp/bccsp.go
另外EncrypterOpts接口(加密选项)和DecrypterOpts接口(解密选项)均为空接口。
type EncrypterOpts interface{}
type DecrypterOpts interface{}
//代码在bccsp/bccsp.go
SW实现方式是默认实现方式,代码在bccsp/sw。主要目录结构如下:
即代码bccsp/sw/conf.go,config数据结构定义:
elliptic.Curve为椭圆曲线接口,使用了crypto/elliptic包。有关椭圆曲线,参考http://8btc.com/thread-1240-1-1.html。
SHA,全称Secure Hash Algorithm,即安全哈希算法,参考https://www.cnblogs.com/kabi/p/5871421.html。
type config struct {
ellipticCurve elliptic.Curve //指定椭圆曲线,elliptic.P256()和elliptic.P384()分别为P-256曲线和P-384曲线
hashFunction func() hash.Hash //指定哈希函数,如SHA-2(SHA-256、SHA-384、SHA-512等)和SHA-3
aesBitLength int //指定AES密钥长度
rsaBitLength int //指定RSA密钥长度
}
//代码在bccsp/sw/conf.go
func (conf *config) setSecurityLevel(securityLevel int, hashFamily string) (err error)为设置安全级别和哈希系列(包括SHA2和SHA3)。
如果hashFamily为"SHA2"或"SHA3",将分别调取conf.setSecurityLevelSHA2(securityLevel)或conf.setSecurityLevelSHA3(securityLevel)。
func (conf *config) setSecurityLevelSHA2(level int) (err error)代码如下:
switch level {
case 256:
conf.ellipticCurve = elliptic.P256() //P-256曲线
conf.hashFunction = sha256.New //SHA-256
conf.rsaBitLength = 2048 //指定AES密钥长度2048
conf.aesBitLength = 32 //指定RSA密钥长度32
case 384:
conf.ellipticCurve = elliptic.P384() //P-384曲线
conf.hashFunction = sha512.New384 //SHA-384
conf.rsaBitLength = 3072 //指定AES密钥长度3072
conf.aesBitLength = 32 //指定RSA密钥长度32
//...
}
//代码在bccsp/sw/conf.go
func (conf *config) setSecurityLevelSHA3(level int) (err error)代码如下:
switch level {
case 256:
conf.ellipticCurve = elliptic.P256() //P-256曲线
conf.hashFunction = sha3.New256 //SHA3-256
conf.rsaBitLength = 2048 //指定AES密钥长度2048
conf.aesBitLength = 32 //指定RSA密钥长度32
case 384:
conf.ellipticCurve = elliptic.P384() //P-384曲线
conf.hashFunction = sha3.New384 //SHA3-384
conf.rsaBitLength = 3072 //指定AES密钥长度3072
conf.aesBitLength = 32 //指定RSA密钥长度32
//...
}
//代码在bccsp/sw/conf.go
type impl struct {
conf *config //bccsp实例的配置
ks bccsp.KeyStore //KeyStore对象,用于存储和获取Key
keyGenerators map[reflect.Type]KeyGenerator //KeyGenerator映射
keyDerivers map[reflect.Type]KeyDeriver //KeyDeriver映射
keyImporters map[reflect.Type]KeyImporter //KeyImporter映射
encryptors map[reflect.Type]Encryptor //加密者映射
decryptors map[reflect.Type]Decryptor //解密者映射
signers map[reflect.Type]Signer //签名者映射
verifiers map[reflect.Type]Verifier //校验者映射
hashers map[reflect.Type]Hasher //Hasher映射
}
//代码在bccsp/sw/impl.go
涉及如下方法:
func New(securityLevel int, hashFamily string, keyStore bccsp.KeyStore) (bccsp.BCCSP, error) //生成sw实例
func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) //生成Key
func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error) //派生Key
func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) //导入Key
func (csp *impl) GetKey(ski []byte) (k bccsp.Key, err error) //获取Key
func (csp *impl) Hash(msg []byte, opts bccsp.HashOpts) (digest []byte, err error) //哈希msg
func (csp *impl) GetHash(opts bccsp.HashOpts) (h hash.Hash, err error) //获取哈希实例
func (csp *impl) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) //签名
func (csp *impl) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) //校验签名
func (csp *impl) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) (ciphertext []byte, err error) //加密
func (csp *impl) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) (plaintext []byte, err error) //解密
//代码在bccsp/sw/impl.go
func New(securityLevel int, hashFamily string, keyStore bccsp.KeyStore) (bccsp.BCCSP, error)作用为:
设置securityLevel和hashFamily,设置keyStore、encryptors、decryptors、signers、verifiers和hashers,之后设置keyGenerators、keyDerivers和keyImporters。
func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error)作用为:
按opts查找keyGenerator是否在csp.keyGenerators[]中,如果在则调取keyGenerator.KeyGen(opts)生成Key。如果opts.Ephemeral()不是暂时的,调取csp.ks.StoreKey存储Key。
func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error)作用为:
按k的类型查找keyDeriver是否在csp.keyDerivers[]中,如果在则调取keyDeriver.KeyDeriv(k, opts)派生Key。如果opts.Ephemeral()不是暂时的,调取csp.ks.StoreKey存储Key。
func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error)
func (csp *impl) Hash(msg []byte, opts bccsp.HashOpts) (digest []byte, err error)
func (csp *impl) GetHash(opts bccsp.HashOpts) (h hash.Hash, err error)
func (csp *impl) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error)
func (csp *impl) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error)
func (csp *impl) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) (ciphertext []byte, err error)
func (csp *impl) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) (plaintext []byte, err error)
//与上述方法实现方式相似。
func (csp *impl) GetKey(ski []byte) (k bccsp.Key, err error)作用为:按ski调取csp.ks.GetKey(ski)获取Key。
参考:https://studygolang.com/articles/7302。
AES,Advanced Encryption Standard,即高级加密标准,是一种对称加密算法。
AES属于块密码工作模式。块密码工作模式,允许使用同一个密码块对于多于一块的数据进行加密。
块密码只能加密长度等于密码块长度的单块数据,若要加密变长数据,则数据必须先划分为一些单独的数据块。
通常而言最后一块数据,也需要使用合适的填充方式将数据扩展到符合密码块大小的长度。
Fabric中使用的填充方式为:pkcs7Padding,即填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。 代码如下:
另外pkcs7UnPadding为其反操作。
func pkcs7Padding(src []byte) []byte {
padding := aes.BlockSize - len(src)%aes.BlockSize //计算填充长度
padtext := bytes.Repeat([]byte{byte(padding)}, padding) //bytes.Repeat构建长度为padding的字节序列,内容为padding
return append(src, padtext...)
}
//代码在bccsp/sw/aes.go
AES常见模式有ECB、CBC等。其中ECB,对于相同的数据块都会加密为相同的密文块,这种模式不能提供严格的数据保密性。
而CBC模式,每个数据块都会和前一个密文块异或后再加密,这种模式中每个密文块都会依赖前一个数据块。同时为了保证每条消息的唯一性,在第一块中需要使用初始化向量。
Fabric使用了CBC模式,代码如下:
//AES加密
func aesCBCEncrypt(key, s []byte) ([]byte, error) {
block, err := aes.NewCipher(key) //生成加密块
//随机一个块大小作为初始化向量
ciphertext := make([]byte, aes.BlockSize+len(s))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
mode := cipher.NewCBCEncrypter(block, iv) //创建CBC模式加密器
mode.CryptBlocks(ciphertext[aes.BlockSize:], s) //执行加密操作
return ciphertext, nil
}
//代码在bccsp/sw/aes.go
//AES解密
func aesCBCDecrypt(key, src []byte) ([]byte, error) {
block, err := aes.NewCipher(key) //生成加密块
iv := src[:aes.BlockSize] //初始化向量
src = src[aes.BlockSize:] //实际数据
mode := cipher.NewCBCDecrypter(block, iv) //创建CBC模式解密器
mode.CryptBlocks(src, src) //执行解密操作
return src, nil
}
//代码在bccsp/sw/aes.go
pkcs7Padding和aesCBCEncrypt整合后代码如下:
//AES加密
func AESCBCPKCS7Encrypt(key, src []byte) ([]byte, error) {
tmp := pkcs7Padding(src)
return aesCBCEncrypt(key, tmp)
}
//AES解密
func AESCBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
pt, err := aesCBCDecrypt(key, src)
return pkcs7UnPadding(pt)
}
//代码在bccsp/sw/aes.go
签名相关代码如下:
type rsaSigner struct{}
func (s *rsaSigner) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
//...
return k.(*rsaPrivateKey).privKey.Sign(rand.Reader, digest, opts) //签名
}
//代码在bccsp/sw/rsa.go
校验签名相关代码如下:
type rsaPrivateKeyVerifier struct{}
func (v *rsaPrivateKeyVerifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
/...
rsa.VerifyPSS(&(k.(*rsaPrivateKey).privKey.PublicKey), (opts.(*rsa.PSSOptions)).Hash, digest, signature, opts.(*rsa.PSSOptions)) //验签
/...
}
type rsaPublicKeyKeyVerifier struct{}
func (v *rsaPublicKeyKeyVerifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
/...
err := rsa.VerifyPSS(k.(*rsaPublicKey).pubKey, (opts.(*rsa.PSSOptions)).Hash, digest, signature, opts.(*rsa.PSSOptions)) //验签
/...
}
//代码在bccsp/sw/rsa.go
另附rsaPrivateKey和rsaPublicKey定义如下:
type rsaPrivateKey struct {
privKey *rsa.PrivateKey
}
type rsaPublicKey struct {
pubKey *rsa.PublicKey
}
//代码在bccsp/sw/rsakey.go
代码在bccsp/sw/ecdsa.go
椭圆曲线算法,相关内容参考:Fabric 1.0源代码笔记 之 附录-ECDSA(椭圆曲线数字签名算法)
虚拟类型KeyStore接口实现dummyKeyStore,无任何实际操作,忽略。
文件类型KeyStore接口实现fileBasedKeyStore,数据结构定义如下:
type fileBasedKeyStore struct {
path string //路径
readOnly bool //是否只读
isOpen bool //是否打开
pwd []byte //密码
m sync.Mutex //锁
}
//代码在bccsp/sw/fileks.go
fileBasedKeyStore是一个基于文件夹的密钥库,每个Key都存储在分散的文件中,文件名包含密钥的SKI。
密钥库可以用密码初始化,这个密码可以用于加密和解密存储密钥的文件。为了避免覆盖,密钥库可以设置为只读。
涉及方法如下:
func NewFileBasedKeyStore(pwd []byte, path string, readOnly bool) (bccsp.KeyStore, error) //创建fileBasedKeyStore,并调用Init完成初始化
func (ks *fileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error //初始化路径、密码、是否只读,以及创建并打开KeyStore
func (ks *fileBasedKeyStore) ReadOnly() bool //密钥库是否只读,只读时StoreKey将失败
func (ks *fileBasedKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) //如果SKI通过,返回Key。通过ski可以获取文件后缀,key、sk、pk分别为普通key、私钥、公钥
func (ks *fileBasedKeyStore) StoreKey(k bccsp.Key) (err error) //将Key存储到密钥库中
//代码在bccsp/sw/fileks.go
func (ks *fileBasedKeyStore) StoreKey(k bccsp.Key) (err error)代码如下:
switch k.(type) {
case *ecdsaPrivateKey:
kk := k.(*ecdsaPrivateKey)
err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey) //ECDSA私钥
case *ecdsaPublicKey:
kk := k.(*ecdsaPublicKey)
err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey) //ECDSA公钥
case *rsaPrivateKey:
kk := k.(*rsaPrivateKey)
err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey) //RSA私钥
case *rsaPublicKey:
kk := k.(*rsaPublicKey)
err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey) //RSA公钥
case *aesPrivateKey:
kk := k.(*aesPrivateKey)
err = ks.storeKey(hex.EncodeToString(k.SKI()), kk.privKey) //AES私钥
//...
//代码在bccsp/sw/fileks.go
pkcs11包,即HSM基础的bccsp(the hsm-based BCCSP implementation),HSM是Hardware Security Modules,即硬件安全模块。
pckcs11是硬件基础的加密服务实现,sw是软件基础的加密服务实现。这个硬件基础的实现以 https://github.com/miekg/pkcs11 这个库为基础。
PKCS#11称为Cyptoki,定义了一套独立于技术的程序设计接口,USBKey安全应用需要实现的接口。
在密码系统中,PKCS#11是公钥加密标准(PKCS, Public-Key Cryptography Standards)中的一份子,由RSA实验室(RSA Laboratories)发布,它为加密令牌定义了一组平台无关的API ,如硬件安全模块和智能卡。
pkcs11包主要内容是PKCS11标准的实现及椭圆曲线算法中以low-S算法为主导的go实现。同时也通过利用RSA的一些特性和算法,丰富了PKCS11加密体系。
type impl struct {
bccsp.BCCSP //结构体中内嵌接口,参考https://studygolang.com/articles/6934
conf *config //pkcs11实例的配置
ks bccsp.KeyStore //KeyStore对象,用于存储和获取Key
ctx *pkcs11.Ctx //pkcs11上下文
sessions chan pkcs11.SessionHandle //即type SessionHandle uint,会话标识符通道,默认数量10
slot uint //安全硬件外设连接插槽标识号
lib string //pkcs11库文件所在路径
noPrivImport bool //是否禁止导入私钥
softVerify bool //是否使用软件方式校验签名
}
//代码在bccsp/pkcs11/impl.go
涉及方法如下:
func New(opts PKCS11Opts, keyStore bccsp.KeyStore) (bccsp.BCCSP, error) //生成pkcs11实例
func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) //生成Key
func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error) //派生Key
func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) //导入Key
func (csp *impl) GetKey(ski []byte) (k bccsp.Key, err error) //获取Key
func (csp *impl) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) //签名
func (csp *impl) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) //校验签名
func (csp *impl) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) (ciphertext []byte, err error) //加密
func (csp *impl) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) (plaintext []byte, err error) //解密
func FindPKCS11Lib() (lib, pin, label string) //从环境变量PKCS11_LIB、PKCS11_PIN、PKCS11_LABEL中获取lib、pin、label,否则取默认使用libsofthsm2.so、98765432、ForFabric
//代码在bccsp/pkcs11/impl.go
func New(opts PKCS11Opts, keyStore bccsp.KeyStore) (bccsp.BCCSP, error)核心代码如下:
conf := &config{}
err := conf.setSecurityLevel(opts.SecLevel, opts.HashFamily) //初始化conf
swCSP, err := sw.New(opts.SecLevel, opts.HashFamily, keyStore) //创建sw实例
lib := opts.Library
pin := opts.Pin
label := opts.Label
ctx, slot, session, err := loadLib(lib, pin, label) //加载动态库,寻找slot,打开会话并登陆会话
sessions := make(chan pkcs11.SessionHandle, sessionCacheSize)
csp := &impl{swCSP, conf, keyStore, ctx, sessions, slot, lib, opts.Sensitive, opts.SoftVerify}
csp.returnSession(*session)
return csp, nil
//代码在bccsp/pkcs11/impl.go
loadLib(lib, pin, label)代码如下:
var slot uint = 0
ctx := pkcs11.New(lib) //根据lib路径加载动态库(如openCryptoki的动态库),并建立pkcs11实例ctx
ctx.Initialize() //初始化 PKCS #11 库
slots, err := ctx.GetSlotList(true) //可用插槽的列表
found := false
for _, s := range slots {
info, err := ctx.GetTokenInfo(s) //获取有关特定令牌的信息
if label == info.Label {
found = true
slot = s
break
}
}
var session pkcs11.SessionHandle
for i := 0; i < 10; i++ { //尝试10次调用ctx.OpenSession打开一个会话session
session, err = ctx.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
if err != nil {
//...
} else {
break
}
}
err = ctx.Login(session, pkcs11.CKU_USER, pin) //登陆会话ctx.Login
return ctx, slot, &session, nil //返回ctx,slot,会话对象session
//代码在bccsp/pkcs11/pkcs11.go
补充type PKCS11Opts struct定义如下:
type PKCS11Opts struct {
//...
//Keystore选项
Ephemeral bool //是否暂存的
FileKeystore *FileKeystoreOpts //FileKeystore
DummyKeystore *DummyKeystoreOpts //DummyKeystore
// PKCS11 options
Library string //库文件路径
Label string //插槽标识
Pin string //登录密码
Sensitive bool
SoftVerify bool
}
//代码在bccsp/pkcs11/conf.go
如下方法优先判断Opts或Key类型,如果为pkcs11支持的ecdsa类型,将调取pkcs11包的实现,否则调取sw包作为默认实现。
func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) //生成Key
func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error) //派生Key
func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) //导入Key
func (csp *impl) GetKey(ski []byte) (k bccsp.Key, err error) //获取Key
func (csp *impl) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) //签名
func (csp *impl) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) //校验签名
//代码在bccsp/pkcs11/impl.go
如下加解密方法,将直接调取sw包的默认实现。
func (csp *impl) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) (ciphertext []byte, err error) //加密
func (csp *impl) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) (plaintext []byte, err error) //解密
//代码在bccsp/pkcs11/impl.go
func (csp *impl) getSession() (session pkcs11.SessionHandle) //在cache为空或者完全为使用状态的时候,通过OpenSession来获取session
func (csp *impl) returnSession(session pkcs11.SessionHandle) //关闭Session
func (csp *impl) getECKey(ski []byte) (pubKey *ecdsa.PublicKey, isPriv bool, err error) //通过SKI, 查找EC(椭圆曲线) key
func (csp *impl) generateECKey(curve asn1.ObjectIdentifier, ephemeral bool) (ski []byte, pubKey *ecdsa.PublicKey, err error) //生成EC key
func (csp *impl) signP11ECDSA(ski []byte, msg []byte) (R, S *big.Int, err error) //签名
func (csp *impl) verifyP11ECDSA(ski []byte, msg []byte, R, S *big.Int, byteSize int) (valid bool, err error) //校验签名
func (csp *impl) importECKey(curve asn1.ObjectIdentifier, privKey, ecPt []byte, ephemeral bool, keyType bool) (ski []byte, err error) //导入EC key
//loadLib 加载lib文件,初始化数据,通过GetSlotList来解析slot数据,通过GetTokenInfo获取token信息,通过pkcs11.SessionHandle方法来获取session
func loadLib(lib, pin, label string) (*pkcs11.Ctx, uint, *pkcs11.SessionHandle, error)
//findKeyPairFromSKI 通过Ctx、session及ski来获取对应的公私钥
func findKeyPairFromSKI(mod *pkcs11.Ctx, session pkcs11.SessionHandle, ski []byte, keyType bool) (*pkcs11.ObjectHandle, error)
//代码在bccsp/pkcs11/pkcs11.go
通过factory可以获得两类BCCSP实例:sw和pkcs11。
BCCSP实例是通过工厂来提供的,sw包对应的工厂在swFactory.go中实现,pkcs11包对应的工厂在pkcs11Factory.go中实现,它们都共同实现了BCCSPFactory接口。
type BCCSPFactory interface {
Name() string //获取工厂名称
Get(opts *FactoryOpts) (bccsp.BCCSP, error) //使用FactoryOpts获取BCCSP实例
}
//代码在bccsp/factory/factory.go
nopkcs11的FactoryOpts:
type FactoryOpts struct {
ProviderName string
SwOpts *SwOpts
}
//代码在bccsp/factory/nopkcs11.go
pkcs11的FactoryOpts:
type FactoryOpts struct {
ProviderName string
SwOpts *SwOpts
Pkcs11Opts *pkcs11.PKCS11Opts
}
//代码在bccsp/factory/pkcs11.go
type SWFactory struct{}
涉及方法:
func (f *SWFactory) Name() string //此处返回SoftwareBasedFactoryName,即"SW"
func (f *SWFactory) Get(config *FactoryOpts) (bccsp.BCCSP, error) //使用FactoryOpts获取BCCSP实例
//代码在bccsp/factory/swfactory.go
func (f *SWFactory) Get(config *FactoryOpts) (bccsp.BCCSP, error)代码如下:
swOpts := config.SwOpts
var ks bccsp.KeyStore
if swOpts.Ephemeral == true { //密钥是暂时的
ks = sw.NewDummyKeyStore()
} else if swOpts.FileKeystore != nil { //密钥是永久的并且定义了FileKeystore
fks, err := sw.NewFileBasedKeyStore(nil, swOpts.FileKeystore.KeyStorePath, false)
ks = fks
} else {
ks = sw.NewDummyKeyStore() //默认是暂时的
}
return sw.New(swOpts.SecLevel, swOpts.HashFamily, ks) //创建sw实例
//代码在bccsp/factory/swfactory.go
type PKCS11Factory struct{}
涉及方法:
func (f *PKCS11Factory) Name() string //此处返回PKCS11BasedFactoryName,即"PKCS11"
func (f *PKCS11Factory) Get(config *FactoryOpts) (bccsp.BCCSP, error) //使用FactoryOpts获取BCCSP实例
//代码在bccsp/factory/pkcs11factory.go
func (f *PKCS11Factory) Get(config *FactoryOpts) (bccsp.BCCSP, error)代码如下:
代码结构基本与swfactory相同,但此处有一个TODO提示。即:
PKCS11是不需要密钥库(keystore)的,但目前还没有从PKCS11 BCCSP中拆分出去,所以这里留着待后续进行改进,因此代码实现中依然保留了一部分keystore的实现。
p11Opts := config.Pkcs11Opts
//TODO: PKCS11 does not need a keystore, but we have not migrated all of PKCS11 BCCSP to PKCS11 yet
var ks bccsp.KeyStore
if p11Opts.Ephemeral == true {
ks = sw.NewDummyKeyStore()
} else if p11Opts.FileKeystore != nil {
fks, err := sw.NewFileBasedKeyStore(nil, p11Opts.FileKeystore.KeyStorePath, false)
ks = fks
} else {
ks = sw.NewDummyKeyStore()
}
return pkcs11.New(*p11Opts, ks)
//代码在bccsp/factory/pkcs11factory.go
nopkcs11版本Factories初始化:
factoriesInitOnce.Do(func() { //仅执行一次
bccspMap = make(map[string]bccsp.BCCSP) //初始化全局bccsp.BCCSP map:bccspMap
// Software-Based BCCSP
if config.SwOpts != nil {
f := &SWFactory{} //创建SWFactory
err := initBCCSP(f, config) //创建BCCSP实例,即调用f.Get,并加入bccspMap中
}
var ok bool
defaultBCCSP, ok = bccspMap[config.ProviderName] //将其作为默认defaultBCCSP
})
//代码在bccsp/factory/nopkcs11.go
pkcs11版本Factories初始化:
func InitFactories(config *FactoryOpts) error {
factoriesInitOnce.Do(func() {
setFactories(config)
})
}
func setFactories(config *FactoryOpts) error {
bccspMap = make(map[string]bccsp.BCCSP)
// Software-Based BCCSP,如果是SW
if config.SwOpts != nil {
f := &SWFactory{}
err := initBCCSP(f, config)
}
// PKCS11-Based BCCSP,如果是PKCS11
if config.Pkcs11Opts != nil {
f := &PKCS11Factory{}
err := initBCCSP(f, config)
}
var ok bool
defaultBCCSP, ok = bccspMap[config.ProviderName]
}
//代码在bccsp/factory/pkcs11.go
func initBCCSP(f BCCSPFactory, config *FactoryOpts) error代码如下:
csp, err := f.Get(config) //调取f.Get生成BCCSP实例
bccspMap[f.Name()] = csp //新生成的实例,加入bccspMap中
//代码在bccsp/factory/factory.go
作者:尹成
来源:CSDN
原文:https://blog.csdn.net/itcastcpp/article/details/80380473
版权声明:本文为博主原创文章,转载请附上博文链接!