Hyperledger Fabrica 2.0 MSP & BCCSP

Keywords: github Blockchain network

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

Published 4 original articles, won praise 0, visited 248
Private letter follow

Posted by smbkgeo1983 on Mon, 09 Mar 2020 21:38:48 -0700