bccsp即blockchain cryptographic service provider
1、bccsp接口
如下,即bccsp实例将提供密钥生成、加解密、签名生成和验证、哈希生成等功能。
// 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.
// 密钥派生算法,是指由一个密钥根据某种规则生成另一个密钥,fabric中的TCert即基于密钥派生算法实现,可以实现对原密钥的追溯。
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)
}
fabric中所有的key类型需要实现以下接口:
当key为私钥时,SKI()返回的是私钥的曲线和公钥XY值的序列化值,Bytes()返回的是nil, errors.New(“Not supported.”);当key是公钥时,SKI()返回的是公钥的曲线和公钥XY值的序列化值,Bytes()返回的是公钥的x509编码证书,因此一对公私钥具有相同的SKI。
// Key represents a cryptographic key
type Key interface {
// Bytes converts this key to its byte representation,
// if this operation is allowed.
Bytes() ([]byte, error)
// SKI returns the subject key identifier of this key.
SKI() []byte
// Symmetric returns true if this key is a symmetric key,
// false is this key is asymmetric
Symmetric() bool
// Private returns true if this key is a private key,
// false otherwise.
Private() bool
// PublicKey returns the corresponding public key part of an asymmetric public/private key pair.
// This method returns an error in symmetric key schemes.
PublicKey() (Key, error)
}
2、bccsp接口基于software的实现类CSP
此包中包括了bccsp接口的两种实现类型:纯软件实现sw和软硬件结合的pkcs11。
下面主要介绍基于sw的实现类中的CSP(fabric\bccsp\sw\impl.go):
该实现类使用map保存了每种功能使用不同算法时对应的处理对象,外界调用接口中的每个方法时,首先根据要使用的算法类型从map获取对应的请求处理对象,然后使用该对象对请求进行处理。初始化时会通过wrapper方法初始化这些map类型变量。
// CSP provides a generic implementation of the BCCSP interface based
// on wrappers. It can be customized by providing implementations for the
// following algorithm-based wrappers: KeyGenerator, KeyDeriver, KeyImporter,
// Encryptor, Decryptor, Signer, Verifier, Hasher. Each wrapper is bound to a
// goland type representing either an option or a key.
type CSP struct {
//KeyStore是密钥存储器变量,有三个实现类,DummyKeystore是假的存储器,不存储任何信息;InmemKeystore是一个包含一个map变量的对象,可以在内存中短暂存储密钥,通过map变量存储密钥id(ski)和对应的密钥对象;FileKeystore是持久化保存到文件中,初始化时需配置路径,文件名是密钥的ski加上密钥类型后缀,aes是key,ecdsa公钥是pk,ecdsa私钥是sk,获取时需要根据后缀将文件中的数据解析成对应的密钥类型,特别是ecdsa公私钥的ski是一样的,使用后缀加以区分和存储。ps:InmemKeystore中直接使用ski作为字典的键,那么怎么解决ecdsa公私钥的ski一样的问题,还是因为私钥一定不会存到内存里?
ks bccsp.KeyStore
KeyGenerators map[reflect.Type]KeyGenerator
KeyDerivers map[reflect.Type]KeyDeriver
KeyImporters map[reflect.Type]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
}
CSP初始化方法:
func NewWithParams(securityLevel int, hashFamily string, keyStore bccsp.KeyStore) (bccsp.BCCSP, error)
参数 hashFamily string 配置了哈希算法,可选sha2/sha3
参数securityLevel int 配置了安全级别即密钥长度,包括哈希算法的密钥长度和系统中使用的椭圆曲线算法的密钥长度都是由这个变量定义,目前可选为256/384
由以上两个参数初始化一个配置类型config变量,config中还包括了一个aes算法的密钥长度配置,当前默认为32.
初始化方法的功能:
1、新建一个空的CSP类型变量
2、将CSP类中的ks 设为keyStore;
3、Encryptors字典中增加aes密钥类型和对应处理对象,该对象实现了bccsp接口的Encrypt方法
4、Decryptors字典中增加aes密钥类型和对应处理对象,该对象实现了bccsp接口的Decrypt方法
5、Signers字典中增加ecdsa私钥类型和对应处理对象,该对象实现了bccsp接口的Sign方法
5、Verifiers字典中增加ecdsa公钥类型和对应处理对象以及ecdsa私钥类型和对应处理对象,这两个对象都实现了bccsp接口的Verify方法
6-10:其他字典处理同理,具体如下面代码。
除了注册每个具体算法的每个安全级别对应的处理对象之外,根据配置文件注册当哈希或者密钥生成指定了算法但是没有指定安全级别时,使用的处理对象,即每中类型算法的默认处理对象。
// NewWithParams returns a new instance of the software-based BCCSP
// set at the passed security level, hash family and KeyStore.
func NewWithParams(securityLevel int, hashFamily string, keyStore bccsp.KeyStore) (bccsp.BCCSP, error) {
// Init config
conf := &config{}
err := conf.setSecurityLevel(securityLevel, hashFamily)
if err != nil {
return nil, errors.Wrapf(err, "Failed initializing configuration at [%v,%v]", securityLevel, hashFamily)
}
swbccsp, err := New(keyStore)
if err != nil {
return nil, err
}
// Notice that errors are ignored here because some test will fail if one
// of the following call fails.
// Set the Encryptors
swbccsp.AddWrapper(reflect.TypeOf(&aesPrivateKey{}), &aescbcpkcs7Encryptor{})
// Set the Decryptors
swbccsp.AddWrapper(reflect.TypeOf(&aesPrivateKey{}), &aescbcpkcs7Decryptor{})
// Set the Signers
swbccsp.AddWrapper(reflect.TypeOf(&ecdsaPrivateKey{}), &ecdsaSigner{})
// Set the Verifiers
swbccsp.AddWrapper(reflect.TypeOf(&ecdsaPrivateKey{}), &ecdsaPrivateKeyVerifier{})
swbccsp.AddWrapper(reflect.TypeOf(&ecdsaPublicKey{}), &ecdsaPublicKeyKeyVerifier{})
// Set the Hashers
// 未指定具体sha的算法和安全级别时,默认使用conf中配置的具体sha算法和安全级别
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.SHAOpts{}), &hasher{hash: conf.hashFunction})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.SHA256Opts{}), &hasher{hash: sha256.New})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.SHA384Opts{}), &hasher{hash: sha512.New384})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.SHA3_256Opts{}), &hasher{hash: sha3.New256})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.SHA3_384Opts{}), &hasher{hash: sha3.New384})
// Set the key generators
// 未指定使用的具体的ecdsa曲线即密钥长度时,默认使用配置中的曲线对应的处理对象
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.ECDSAKeyGenOpts{}), &ecdsaKeyGenerator{curve: conf.ellipticCurve})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.ECDSAP256KeyGenOpts{}), &ecdsaKeyGenerator{curve: elliptic.P256()})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.ECDSAP384KeyGenOpts{}), &ecdsaKeyGenerator{curve: elliptic.P384()})
// // 未指定使用的具体的aes密钥长度时,默认使用配置中的aes密钥长度
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.AESKeyGenOpts{}), &aesKeyGenerator{length: conf.aesBitLength})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.AES256KeyGenOpts{}), &aesKeyGenerator{length: 32})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.AES192KeyGenOpts{}), &aesKeyGenerator{length: 24})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.AES128KeyGenOpts{}), &aesKeyGenerator{length: 16})
// Set the key deriver
// 密钥派生,基于椭圆曲线公私钥的叠加特性实现,即公钥dG+kG的私钥是d+k,原理是为拥有私钥d的用户生成公钥dG+kG,并用dG对k进行加密保存到证书拓展域中,只有拥有私钥d的用户和监管者能够解析出对应私钥(d+k)。(当前实现中k是直接保存在拓展域中,并未进行加密)
swbccsp.AddWrapper(reflect.TypeOf(&ecdsaPrivateKey{}), &ecdsaPrivateKeyKeyDeriver{})
swbccsp.AddWrapper(reflect.TypeOf(&ecdsaPublicKey{}), &ecdsaPublicKeyKeyDeriver{})
swbccsp.AddWrapper(reflect.TypeOf(&aesPrivateKey{}), &aesPrivateKeyKeyDeriver{conf: conf})
// Set the key importers
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.AES256ImportKeyOpts{}), &aes256ImportKeyOptsKeyImporter{})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.HMACImportKeyOpts{}), &hmacImportKeyOptsKeyImporter{})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.ECDSAPKIXPublicKeyImportOpts{}), &ecdsaPKIXPublicKeyImportOptsKeyImporter{})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.ECDSAPrivateKeyImportOpts{}), &ecdsaPrivateKeyImportOptsKeyImporter{})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.ECDSAGoPublicKeyImportOpts{}), &ecdsaGoPublicKeyImportOptsKeyImporter{})
swbccsp.AddWrapper(reflect.TypeOf(&bccsp.X509PublicKeyImportOpts{}), &x509PublicKeyImportOptsKeyImporter{bccsp: swbccsp})
return swbccsp, nil
}
3、idemix包
4、factory包
BCCSPFactory接口包括获取工厂名称Name()和获取BCCSP实例Get()两个方法,fabric包中提供了两个工厂接口的实现类SWFactory和PKCS11Factory。SWFactory的Name()返回“SW”, Get()返回一个bccsp接口基于software的实现类CSP的一个实例;PKCS11Factory的Name()返回"PKCS11", Get()返回一个bccsp接口基于pkcs11的实现类impl(位置:fabric\bccsp\pkcs11\impl.go)的一个实例。
在使用factory接口实例前,需要调用InitFactories方法初始化factory包。factory包中提供了两个平行的文件pkcs11.go 和 nopkcs11.go,两个文件中具有完全相同的接口和方法名(包括InitFactories方法),具体实现不同,通过使用+build 关键字来实现编译互斥。当编译执行pkcs11.go 中的InitFactories方法,会初始化一个SWFactory实例然后使用get()方法获取一个swbccsp实例,并将该实例保存到全局变量bccsp实例字典中,然后设置全部变量DefaultBCCSP为该bccsp实例;当编译执行nopkcs11.go 中的InitFactories方法时,会初始化一个PKCS11Factory实例然后使用get()方法获取一个pkcs11bccsp实例并将该实例保存到全局变量bccsp实例字典中,(如果配置了sw初始化参数,则可以同时初始化一个SWFactory实例然后使用get()方法获取一个swbccsp实例并将该实例保存到全局变量bccsp实例字典中),然后设置全局变量DefaultBCCSP为pkcs11bccsp实例。
// BCCSPFactory is used to get instances of the BCCSP interface.
// A Factory has name used to address it.
type BCCSPFactory interface {
// Name returns the name of this factory
Name() string
// Get returns an instance of BCCSP using opts.
Get(opts *FactoryOpts) (bccsp.BCCSP, error)
}
下面是初始化SWFactory,使用nopkcs11.go而屏蔽pkcs11.go:
// InitFactories must be called before using factory interfaces
// It is acceptable to call with config = nil, in which case
// some defaults will get used
// Error is returned only if defaultBCCSP cannot be found
func InitFactories(config *FactoryOpts) error {
factoriesInitOnce.Do(func() {
setFactories(config)
})
return factoriesInitError
}
type FactoryOpts struct {
// ProviderName设置DefaultBCCSP是初始化后中全局变量bccspMap的哪一个
ProviderName string `mapstructure:"default" json:"default" yaml:"Default"`
SwOpts *SwOpts `mapstructure:"SW,omitempty" json:"SW,omitempty" yaml:"SwOpts"`
}
// SwOpts contains options for the SWFactory
type SwOpts struct {
// Default algorithms when not specified (Deprecated?)
SecLevel int `mapstructure:"security" json:"security" yaml:"Security"`
HashFamily string `mapstructure:"hash" json:"hash" yaml:"Hash"`
// Keystore Options, 从三种密钥存储器类型中选一种默认或Ephemeral为1时为假存储器类型。
Ephemeral bool `mapstructure:"tempkeys,omitempty" json:"tempkeys,omitempty"`
FileKeystore *FileKeystoreOpts `mapstructure:"filekeystore,omitempty" json:"filekeystore,omitempty" yaml:"FileKeyStore"`
DummyKeystore *DummyKeystoreOpts `mapstructure:"dummykeystore,omitempty" json:"dummykeystore,omitempty"`
InmemKeystore *InmemKeystoreOpts `mapstructure:"inmemkeystore,omitempty" json:"inmemkeystore,omitempty"`
}
setFactories方法的作用是:
1、当setFactories的参数config为空或参数空缺时,为config添加默认配置值,默认配置如下:
func GetDefaultOpts() *FactoryOpts {
return &FactoryOpts{
ProviderName: "SW",
SwOpts: &SwOpts{
HashFamily: "SHA2",
SecLevel: 256,
Ephemeral: true,
},
}
}
2、初始化全局变量bccsp实例字典bccspMap
bccspMap = make(map[string]bccsp.BCCSP)
3、新建一个SWFactory实例,然后生成一个config配置的swbccsp实例,并将实例保存到bccsp实例字典中,键为工厂名称“SW”,值为生成的swbccsp实例,一个CSP对象。(所以bccspMap中保存的每种工厂类型对应一个BCCSP实例,pkcs11.go的初始化方法中可以同时初始化SW和pkcs11两种类型的bccsp实例,并保存到map)
4、根据配置中的ProviderName给全局变量DefaultBCCSP即默认BCCSP对象赋值。
DefaultBCCSP, ok = bccspMap[config.ProviderName]
**注意:**初始化后,调用者可以直接调用包中的方法GetDefault()获取默认bccsp对象,或者通过func GetBCCSPFromOpts(config *FactoryOpts) (bccsp.BCCSP, error)方法获取一个给定配置的bccsp对象(目前只支持SW类型)