This article is based on fabric v2.0.1 The initialization process of localmsp and bccsp is described with the example of peer node startup.
I. BCCSP
BCCSP is the abbreviation of Blockchain Cryptographic Service Provider, which is an abstract representation of commonly used block chain cryptography algorithms. Including Hash, encryption and decryption, signature, signature verification, etc.
There are two implementation methods in Fabric, one is SW (Software), that is, pure Golang implementation (standard library or third-party library), the other is PKCS11 based on the existing pkcs11 c library. This paper focuses on the implementation of SW.
1.1 interface
Defined in bccsp/bccsp.go
// 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) }
1.2 implementation
SW implementation at sw/impl.go
// 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 { 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 }
The specific cryptography algorithm is realized through AddWrapper Method injection, Fabric built-in support registration is as follows:
Code is located sw/new.go
// 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 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 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()}) 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 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 }
Two, MSP
MSP is the Membership Service Provider. Fabric uses PKI system to organize and manage the identity, organization, authority, etc. in the whole network. More see MSP detailed explanation (I) - MSP basis.
In the same way, FABRIC also provides two implementations for MSP: FABRIC, IDEMIX, and Fabric 2.0 can only use standard to implement FABRIC. For details, see node/start.go . This paper only focuses on the FABRIC implementation, which is based on bccsp.
2.1 interface definition
Interface defined in msp/msp.go
// MSP is the minimal Membership Service Provider Interface to be implemented // to accommodate peer functionality type MSP interface { // IdentityDeserializer interface needs to be implemented by MSP IdentityDeserializer // Setup the MSP instance according to configuration information Setup(config *msp.MSPConfig) error // GetVersion returns the version of this MSP GetVersion() MSPVersion // GetType returns the provider type GetType() ProviderType // GetIdentifier returns the provider identifier GetIdentifier() (string, error) // GetSigningIdentity returns a signing identity corresponding to the provided identifier GetSigningIdentity(identifier *IdentityIdentifier) (SigningIdentity, error) // GetDefaultSigningIdentity returns the default signing identity GetDefaultSigningIdentity() (SigningIdentity, error) // GetTLSRootCerts returns the TLS root certificates for this MSP GetTLSRootCerts() [][]byte // GetTLSIntermediateCerts returns the TLS intermediate root certificates for this MSP GetTLSIntermediateCerts() [][]byte // Validate checks whether the supplied identity is valid Validate(id Identity) error // SatisfiesPrincipal checks whether the identity matches // the description supplied in MSPPrincipal. The check may // involve a byte-by-byte comparison (if the principal is // a serialized identity) or may require MSP validation SatisfiesPrincipal(id Identity, principal *msp.MSPPrincipal) error }
2.2 implementation
The latest version based on bccsp is mspv1 ﹣ 4 ﹣ 3. For the definition, see msp/mspimpl.go
// newBccspMsp returns an MSP instance backed up by a BCCSP // crypto provider. It handles x.509 certificates and can // generate identities and signing identities backed by // certificates and keypairs func newBccspMsp(version MSPVersion, defaultBCCSP bccsp.BCCSP) (MSP, error) { mspLogger.Debugf("Creating BCCSP-based MSP instance") theMsp := &bccspmsp{} theMsp.version = version theMsp.bccsp = defaultBCCSP switch version { case MSPv1_0: ... case MSPv1_1: ... case MSPv1_3: ... case MSPv1_4_3: theMsp.internalSetupFunc = theMsp.setupV142 theMsp.internalValidateIdentityOusFunc = theMsp.validateIdentityOUsV142 theMsp.internalSatisfiesPrincipalInternalFunc = theMsp.satisfiesPrincipalInternalV142 theMsp.internalSetupAdmin = theMsp.setupAdminsV142 default: return nil, errors.Errorf("Invalid MSP version [%v]", version) } return theMsp, nil }
adopt Setup Method to initialize:
// Setup sets up the internal data structures // for this MSP, given an MSPConfig ref; it // returns nil in case of success or an error otherwise func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error { if conf1 == nil { return errors.New("Setup error: nil conf reference") } // given that it's an msp of type fabric, extract the MSPConfig instance conf := &m.FabricMSPConfig{} err := proto.Unmarshal(conf1.Config, conf) if err != nil { return errors.Wrap(err, "failed unmarshalling fabric msp config") } // set the name for this msp msp.name = conf.Name mspLogger.Debugf("Setting up MSP instance %s", msp.name) // setup return msp.internalSetupFunc(conf) }
There is no further expansion here. The setup process mainly deals with the certificates.
3, Initialization process
Take peer node start as an example to understand the initialization process of bccsp and localmsp
3.1 configuration
Note: MSP standard implementation FABRIC configuration type is identified as peer.localMspType: bccsp
peer: # BCCSP (Blockchain crypto provider): Select which crypto implementation or # library to use BCCSP: Default: SW # Settings for the SW crypto provider (i.e. when DEFAULT: SW) SW: # TODO: The default Hash and Security level needs refactoring to be # fully configurable. Changing these defaults requires coordination # SHA2 is hardcoded in several places, not only BCCSP Hash: SHA2 Security: 256 # Location of Key Store FileKeyStore: # If "", defaults to 'mspConfigPath'/keystore KeyStore: # Path on the file system where peer will find MSP local configurations mspConfigPath: msp # Identifier of the local MSP # ----!!!!IMPORTANT!!!-!!!IMPORTANT!!!-!!!IMPORTANT!!!!---- # Deployers need to change the value of the localMspId string. # In particular, the name of the local MSP ID of a peer needs # to match the name of one of the MSPs in each of the channel # that this peer is a member of. Otherwise this peer's messages # will not be identified as valid by other nodes. localMspId: SampleOrg # Type for the local MSP - by default it's of type bccsp localMspType: bccsp
3.2 initialization process
Call entry at cobra PersistentPreRun hook definition of Command node/node.go
Initialization entry InitCmd
func InitCmd(cmd *cobra.Command, args []string) { ... // Init the MSP var mspMgrConfigDir = config.GetPath("peer.mspConfigPath") var mspID = viper.GetString("peer.localMspId") var mspType = viper.GetString("peer.localMspType") if mspType == "" { mspType = msp.ProviderTypeToString(msp.FABRIC) } err = InitCrypto(mspMgrConfigDir, mspID, mspType) if err != nil { // Handle errors reading the config file mainLogger.Errorf("Cannot run peer because %s", err.Error()) os.Exit(1) } }
The detailed call stack is as follows:
InitCmd in github.com/hyperledger/fabric/internal/peer/common/common.go InitCrypto in github.com/hyperledger/fabric/internal/peer/common/common.go LoadLocalMspWithType in github.com/hyperledger/fabric/msp/mgmt/mgmt.go GetLocalMspConfigWithType in github.com/hyperledger/fabric/msp/configbuilder.go GetLocalMspConfig in github.com/hyperledger/fabric/msp/configbuilder.go // Initialize bccsp InitFactories in github.com/hyperledger/fabric/bccsp/factory/nopkcs11.go initBCCSP in github.com/hyperledger/fabric/bccsp/factory/factory.go *SWFactory.Get in github.com/hyperledger/fabric/bccsp/factory/swfactory.go NewWithParams in github.com/hyperledger/fabric/bccsp/sw/new.go New in github.com/hyperledger/fabric/bccsp/sw/impl.go AddWrapper (26 usages) in github.com/hyperledger/fabric/bccsp/sw/impl.go getPemMaterialFromDir in github.com/hyperledger/fabric/msp/configbuilder.go getMspConfig in github.com/hyperledger/fabric/msp/configbuilder.go GetDefault in github.com/hyperledger/fabric/bccsp/factory/factory.go GetLocalMSP in github.com/hyperledger/fabric/msp/mgmt/mgmt.go loadLocaMSP in github.com/hyperledger/fabric/msp/mgmt/mgmt.go New in github.com/hyperledger/fabric/msp/factory.go newBccspMsp in github.com/hyperledger/fabric/msp/mspimpl.go New in github.com/hyperledger/fabric/msp/cache/cache.go *bccspmsp.Setup in github.com/hyperledger/fabric/msp/mspimpl.go *bccspmsp.setupV142 in github.com/hyperledger/fabric/msp/mspimpl.go *bccspmsp.preSetupV142 in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.setupCrypto in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.setupCAs in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.setupCRLs in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.finalizeSetupCAs in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.setupSigningIdentity in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.setupTLSCAs in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.setupOUs in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.setupNodeOUsV142 in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.setupAdmins in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.postSetupV142 in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.postSetupV1 in github.com/hyperledger/fabric/msp/mspimplsetup.go *bccspmsp.hasOURole (2 usages) in github.com/hyperledger/fabric/msp/mspimpl.go