From 3ee033397cc81e90630cb7d7d84389c49641a172 Mon Sep 17 00:00:00 2001 From: Volodymyr Paprotski Date: Sun, 12 Feb 2017 00:26:57 -0500 Subject: [PATCH] [FAB-1647] Yaml used to configure BCCSP This time use Yaml files in peer and orderer to configure BCCSP factory The main three changes are for the two executables: - peer - orderer - chaincode shim They each have their own config yaml file, added a BCCSP section. The BCCSP is paired with the MSP configuration directory. The SW BCCSP Filestore takes over the keystore directory. Where it gets complicated are all the tests. The tests working against MSP were easy to fix (circa patch set 8) Patch set https://gerrit.hyperledger.org/r/#/c/6235/4 introduced more uses of BCCSP. Configuring those mostly to SW/nil, except need to find an appropriate location for InitFactories(nil). Either: - many/most test cases have function called SetupTestConfig() - TestMain() otherwise Since the TestMain() updates were getting unmanageable and unscalable (everyone writting unit tests would now need to know about InitFactories()), added a concept of bootBCCSP to bccsp/factory. bootBCCSP is meant to be used by test cases that only need keyless crypto operations (i.e. SHA) or where keeping keys does not matter. Change-Id: I084d7927550e7fad7a25cf2062dc20220cf81ccd Signed-off-by: Volodymyr Paprotski --- Makefile | 2 +- bccsp/factory/factory.go | 16 +++++- bccsp/factory/opts.go | 3 -- common/configtx/test/helper.go | 4 +- common/configtx/tool/configtx.yaml | 12 +++++ common/configtx/tool/localconfig/config.go | 3 ++ .../configtx/tool/provisional/provisional.go | 4 +- common/configvalues/msp/config_test.go | 2 +- common/localmsp/signer_test.go | 2 +- core/chaincode/config.go | 8 +++ core/chaincode/shim/chaincode.go | 6 +++ core/config/config.go | 16 ++++++ core/container/config.go | 16 ++++++ core/endorser/config.go | 17 +++++++ core/endorser/endorser_test.yaml | 10 ++++ events/config.go | 17 +++++++ msp/configbuilder.go | 47 ++++++++++++----- msp/mgmt/mgmt.go | 5 +- msp/mgmt/peermsp_test.go | 2 +- msp/mgmt/testtools/config.go | 2 +- msp/msp_test.go | 4 +- msp/mspimpl.go | 51 +++++++++++-------- ...71400827b80d413001616250f6519137460808_sk} | 0 orderer/localconfig/config.go | 4 ++ orderer/main.go | 2 +- orderer/orderer.yaml | 12 +++++ orderer/sbft_test.go | 2 +- peer/common/common.go | 10 +++- peer/core.yaml | 12 +++++ 29 files changed, 236 insertions(+), 55 deletions(-) rename msp/sampleconfig/keystore/{key.pem => be550e94606441378b27a5e4dc71400827b80d413001616250f6519137460808_sk} (100%) diff --git a/Makefile b/Makefile index 123be0d5114..bf4e58d6cb3 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ K := $(foreach exec,$(EXECUTABLES),\ GOSHIM_DEPS = $(shell ./scripts/goListFiles.sh $(PKGNAME)/core/chaincode/shim) JAVASHIM_DEPS = $(shell git ls-files core/chaincode/shim/java) PROTOS = $(shell git ls-files *.proto | grep -v vendor) -MSP_SAMPLECONFIG = $(shell git ls-files msp/sampleconfig/*.pem) +MSP_SAMPLECONFIG = $(shell git ls-files msp/sampleconfig/*) PROJECT_FILES = $(shell git ls-files) IMAGES = peer orderer ccenv javaenv buildenv testenv zookeeper kafka couchdb diff --git a/bccsp/factory/factory.go b/bccsp/factory/factory.go index c099faba61e..ccf2631a74c 100644 --- a/bccsp/factory/factory.go +++ b/bccsp/factory/factory.go @@ -27,11 +27,16 @@ var ( // Default BCCSP defaultBCCSP bccsp.BCCSP + // when InitFactories has not been called yet (should only happen + // in test cases), use this BCCSP temporarily + bootBCCSP bccsp.BCCSP + // BCCSP Factories bccspMap map[string]bccsp.BCCSP // factories' Sync on Initialization factoriesInitOnce sync.Once + bootBCCSPInitOnce sync.Once // Factories' Initialization Error factoriesInitError error @@ -53,7 +58,16 @@ type BCCSPFactory interface { // GetDefault returns a non-ephemeral (long-term) BCCSP func GetDefault() bccsp.BCCSP { if defaultBCCSP == nil { - panic("BCCSP Factory: Must call InitFactories before using BCCSP!") + logger.Warning("Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP.") + bootBCCSPInitOnce.Do(func() { + var err error + f := &SWFactory{} + bootBCCSP, err = f.Get(&DefaultOpts) + if err != nil { + panic("BCCSP Internal error, failed initialization with DefaultOpts!") + } + }) + return bootBCCSP } return defaultBCCSP } diff --git a/bccsp/factory/opts.go b/bccsp/factory/opts.go index 0122d64c765..e03e3b3de65 100644 --- a/bccsp/factory/opts.go +++ b/bccsp/factory/opts.go @@ -32,9 +32,6 @@ var DefaultOpts = FactoryOpts{ }, } -// FIXME! FIXME! This needs to be moved to where viper reads in configs! -var myHack = InitFactories(nil) - // FactoryName returns the name of the provider func (o *FactoryOpts) FactoryName() string { return o.ProviderName diff --git a/common/configtx/test/helper.go b/common/configtx/test/helper.go index fd9ccc13bdc..9a1282b4a86 100644 --- a/common/configtx/test/helper.go +++ b/common/configtx/test/helper.go @@ -91,7 +91,7 @@ const sampleOrgID = "DEFAULT" // ApplicationOrgTemplate returns the SAMPLE org with MSP template func ApplicationOrgTemplate() configtx.Template { - mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, sampleOrgID) + mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, nil, sampleOrgID) if err != nil { logger.Panicf("Could not load sample MSP config: %s", err) } @@ -100,7 +100,7 @@ func ApplicationOrgTemplate() configtx.Template { // OrdererOrgTemplate returns the SAMPLE org with MSP template func OrdererOrgTemplate() configtx.Template { - mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, sampleOrgID) + mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, nil, sampleOrgID) if err != nil { logger.Panicf("Could not load sample MSP config: %s", err) } diff --git a/common/configtx/tool/configtx.yaml b/common/configtx/tool/configtx.yaml index c69105cfb57..828af5522e4 100644 --- a/common/configtx/tool/configtx.yaml +++ b/common/configtx/tool/configtx.yaml @@ -52,6 +52,18 @@ Organizations: # MSPDir is the filesystem path which contains the MSP configuration MSPDir: msp/sampleconfig + # BCCSP (Blockchain crypto provider): Select which crypto implementation or + # library to use + BCCSP: + Default: SW + SW: + Hash: SHA3 + Security: 256 + # Location of Key Store. If this is unset, a location will + # be chosen using 'MSPDir'/keystore + FileKeyStore: + KeyStore: + AnchorPeers: # AnchorPeers defines the location of peers which can be used # for cross org gossip communication. Note, this value is only diff --git a/common/configtx/tool/localconfig/config.go b/common/configtx/tool/localconfig/config.go index 5bbd76fc022..115018015e6 100644 --- a/common/configtx/tool/localconfig/config.go +++ b/common/configtx/tool/localconfig/config.go @@ -27,6 +27,8 @@ import ( "github.com/op/go-logging" "github.com/spf13/viper" + + bccsp "github.com/hyperledger/fabric/bccsp/factory" ) const ( @@ -65,6 +67,7 @@ type Organization struct { Name string ID string MSPDir string + BCCSP *bccsp.FactoryOpts // Note, the viper deserialization does not seem to care for // embedding of types, so we use one organization structure for diff --git a/common/configtx/tool/provisional/provisional.go b/common/configtx/tool/provisional/provisional.go index 466cf2dc6cd..744fd13f090 100644 --- a/common/configtx/tool/provisional/provisional.go +++ b/common/configtx/tool/provisional/provisional.go @@ -113,7 +113,7 @@ func New(conf *genesisconfig.Profile) Generator { } for _, org := range conf.Orderer.Organizations { - mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.ID) + mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.BCCSP, org.ID) if err != nil { logger.Panicf("Error loading MSP configuration for org %s: %s", org.Name, err) } @@ -143,7 +143,7 @@ func New(conf *genesisconfig.Profile) Generator { policies.TemplateImplicitMetaMajorityPolicy([]string{configtxapplication.GroupKey}, configvaluesmsp.AdminsPolicyKey), } for _, org := range conf.Application.Organizations { - mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.ID) + mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.BCCSP, org.ID) if err != nil { logger.Panicf("Error loading MSP configuration for org %s: %s", org.Name, err) } diff --git a/common/configvalues/msp/config_test.go b/common/configvalues/msp/config_test.go index 31bd30cd25a..058e2dc05f3 100644 --- a/common/configvalues/msp/config_test.go +++ b/common/configvalues/msp/config_test.go @@ -25,7 +25,7 @@ import ( ) func TestMSPConfigManager(t *testing.T) { - conf, err := msp.GetLocalMspConfig("../../../msp/sampleconfig/", "DEFAULT") + conf, err := msp.GetLocalMspConfig("../../../msp/sampleconfig/", nil, "DEFAULT") assert.NoError(t, err) // test success: diff --git a/common/localmsp/signer_test.go b/common/localmsp/signer_test.go index 4ac890e68fc..e018a07d52b 100644 --- a/common/localmsp/signer_test.go +++ b/common/localmsp/signer_test.go @@ -37,7 +37,7 @@ func TestMain(m *testing.M) { mspMgrConfigDir = os.Getenv("GOPATH") + "/src/github.com/hyperledger/fabric/msp/sampleconfig/" } - if err := mspmgmt.LoadLocalMsp(mspMgrConfigDir, "DEFAULT"); err != nil { + if err := mspmgmt.LoadLocalMsp(mspMgrConfigDir, nil, "DEFAULT"); err != nil { os.Exit(-1) } diff --git a/core/chaincode/config.go b/core/chaincode/config.go index 91266ad8f72..295842b9f71 100644 --- a/core/chaincode/config.go +++ b/core/chaincode/config.go @@ -24,6 +24,8 @@ import ( "github.com/op/go-logging" "github.com/spf13/viper" + + "github.com/hyperledger/fabric/bccsp/factory" ) // Config the config wrapper structure @@ -71,4 +73,10 @@ func SetupTestConfig() { // Set the number of maxprocs var numProcsDesired = viper.GetInt("peer.gomaxprocs") chaincodeLogger.Debugf("setting Number of procs to %d, was %d\n", numProcsDesired, runtime.GOMAXPROCS(2)) + + // Init the BCCSP + err = factory.InitFactories(nil) + if err != nil { + panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)) + } } diff --git a/core/chaincode/shim/chaincode.go b/core/chaincode/shim/chaincode.go index 7a8fa0b180a..9267ef7d449 100644 --- a/core/chaincode/shim/chaincode.go +++ b/core/chaincode/shim/chaincode.go @@ -29,6 +29,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes/timestamp" + "github.com/hyperledger/fabric/bccsp/factory" "github.com/hyperledger/fabric/core/comm" pb "github.com/hyperledger/fabric/protos/peer" "github.com/hyperledger/fabric/protos/utils" @@ -76,6 +77,11 @@ func Start(cc Chaincode) error { SetChaincodeLoggingLevel() + err := factory.InitFactories(&factory.DefaultOpts) + if err != nil { + return fmt.Errorf("Internal error, BCCSP could not be initialized with default options: %s", err) + } + flag.StringVar(&peerAddress, "peer.address", "", "peer address") flag.Parse() diff --git a/core/config/config.go b/core/config/config.go index 36dc677c04b..d0792a5c378 100644 --- a/core/config/config.go +++ b/core/config/config.go @@ -24,6 +24,9 @@ import ( "github.com/op/go-logging" "github.com/spf13/viper" + + "github.com/hyperledger/fabric/bccsp/factory" + "github.com/hyperledger/fabric/msp" ) // Config the config wrapper structure @@ -74,4 +77,17 @@ func SetupTestConfig(pathToOpenchainYaml string) { var numProcsDesired = viper.GetInt("peer.gomaxprocs") configLogger.Debugf("setting Number of procs to %d, was %d\n", numProcsDesired, runtime.GOMAXPROCS(2)) + // Init the BCCSP + var bccspConfig *factory.FactoryOpts + err = viper.UnmarshalKey("peer.BCCSP", &bccspConfig) + if err != nil { + bccspConfig = nil + } + + msp.SetupBCCSPKeystoreConfig(bccspConfig, viper.GetString("peer.mspConfigPath")+"/keystore") + + err = factory.InitFactories(bccspConfig) + if err != nil { + panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)) + } } diff --git a/core/container/config.go b/core/container/config.go index ac53bddeae0..dab45c94dd4 100644 --- a/core/container/config.go +++ b/core/container/config.go @@ -24,6 +24,9 @@ import ( "github.com/op/go-logging" "github.com/spf13/viper" + + "github.com/hyperledger/fabric/bccsp/factory" + "github.com/hyperledger/fabric/msp" ) // Config the config wrapper structure @@ -73,4 +76,17 @@ func SetupTestConfig() { var numProcsDesired = viper.GetInt("peer.gomaxprocs") vmLogger.Debugf("setting Number of procs to %d, was %d\n", numProcsDesired, runtime.GOMAXPROCS(2)) + // Init the BCCSP + var bccspConfig *factory.FactoryOpts + err = viper.UnmarshalKey("peer.BCCSP", &bccspConfig) + if err != nil { + bccspConfig = nil + } + + msp.SetupBCCSPKeystoreConfig(bccspConfig, viper.GetString("peer.mspConfigPath")+"/keystore") + + err = factory.InitFactories(bccspConfig) + if err != nil { + panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)) + } } diff --git a/core/endorser/config.go b/core/endorser/config.go index f296502d815..48eadf388bb 100644 --- a/core/endorser/config.go +++ b/core/endorser/config.go @@ -23,6 +23,9 @@ import ( "github.com/op/go-logging" "github.com/spf13/viper" + + "github.com/hyperledger/fabric/bccsp/factory" + "github.com/hyperledger/fabric/msp" ) // Config the config wrapper structure @@ -68,4 +71,18 @@ func SetupTestConfig() { // Set the number of maxprocs viper.GetInt("peer.gomaxprocs") + + // Init the BCCSP + var bccspConfig *factory.FactoryOpts + err = viper.UnmarshalKey("peer.BCCSP", &bccspConfig) + if err != nil { + bccspConfig = nil + } + + msp.SetupBCCSPKeystoreConfig(bccspConfig, viper.GetString("peer.mspConfigPath")+"/keystore") + + err = factory.InitFactories(bccspConfig) + if err != nil { + panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)) + } } diff --git a/core/endorser/endorser_test.yaml b/core/endorser/endorser_test.yaml index 8f93e6e7ce5..053abe278bd 100644 --- a/core/endorser/endorser_test.yaml +++ b/core/endorser/endorser_test.yaml @@ -322,6 +322,16 @@ peer: enabled: false listenAddress: 0.0.0.0:6060 + # BCCSP (Blockchain crypto provider): Select which crypto implementation or + # library to use + BCCSP: + Default: SW + SW: + Hash: SHA3 + Security: 256 + FileKeyStore: + KeyStore: + ############################################################################### # # VM section diff --git a/events/config.go b/events/config.go index b2083463777..6ac6418521f 100644 --- a/events/config.go +++ b/events/config.go @@ -24,6 +24,9 @@ import ( "github.com/op/go-logging" "github.com/spf13/viper" + + "github.com/hyperledger/fabric/bccsp/factory" + "github.com/hyperledger/fabric/msp" ) // Config the config wrapper structure @@ -64,4 +67,18 @@ func SetupTestConfig() { } SetupTestLogging() + + // Init the BCCSP + var bccspConfig *factory.FactoryOpts + err = viper.UnmarshalKey("peer.BCCSP", &bccspConfig) + if err != nil { + bccspConfig = nil + } + + msp.SetupBCCSPKeystoreConfig(bccspConfig, viper.GetString("peer.mspConfigPath")+"/keystore") + + err = factory.InitFactories(bccspConfig) + if err != nil { + panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)) + } } diff --git a/msp/configbuilder.go b/msp/configbuilder.go index 77b3d83ae14..e813fb936f4 100644 --- a/msp/configbuilder.go +++ b/msp/configbuilder.go @@ -25,6 +25,7 @@ import ( "encoding/pem" "path/filepath" + "github.com/hyperledger/fabric/bccsp/factory" "github.com/hyperledger/fabric/protos/msp" ) @@ -87,13 +88,39 @@ const ( intermediatecerts = "intermediatecerts" ) -func GetLocalMspConfig(dir string, ID string) (*msp.MSPConfig, error) { +func SetupBCCSPKeystoreConfig(bccspConfig *factory.FactoryOpts, keystoreDir string) { + if bccspConfig == nil { + bccspConfig = &factory.DefaultOpts + } + + if bccspConfig.ProviderName == "SW" { + if bccspConfig.SwOpts == nil { + bccspConfig.SwOpts = factory.DefaultOpts.SwOpts + } + + // Only override the KeyStorePath if it was left empty + if bccspConfig.SwOpts.FileKeystore == nil || + bccspConfig.SwOpts.FileKeystore.KeyStorePath == "" { + bccspConfig.SwOpts.Ephemeral = false + bccspConfig.SwOpts.FileKeystore = &factory.FileKeystoreOpts{KeyStorePath: keystoreDir} + } + } +} + +func GetLocalMspConfig(dir string, bccspConfig *factory.FactoryOpts, ID string) (*msp.MSPConfig, error) { cacertDir := filepath.Join(dir, cacerts) signcertDir := filepath.Join(dir, signcerts) admincertDir := filepath.Join(dir, admincerts) keystoreDir := filepath.Join(dir, keystore) intermediatecertsDir := filepath.Join(dir, intermediatecerts) + SetupBCCSPKeystoreConfig(bccspConfig, keystoreDir) + + err := factory.InitFactories(bccspConfig) + if err != nil { + return nil, fmt.Errorf("Could not initialize BCCSP Factories [%s]", err) + } + cacerts, err := getPemMaterialFromDir(cacertDir) if err != nil || len(cacerts) == 0 { return nil, fmt.Errorf("Could not load a valid ca certificate from directory %s, err %s", cacertDir, err) @@ -109,22 +136,16 @@ func GetLocalMspConfig(dir string, ID string) (*msp.MSPConfig, error) { return nil, fmt.Errorf("Could not load a valid admin certificate from directory %s, err %s", admincertDir, err) } - keys, err := getPemMaterialFromDir(keystoreDir) - if err != nil || len(keys) == 0 { - return nil, fmt.Errorf("Could not load a valid signing key from directory %s, err %s", keystoreDir, err) - } - intermediatecert, _ := getPemMaterialFromDir(intermediatecertsDir) // intermediate certs are not mandatory - // FIXME: for now we're making the following assumptions - // 1) there is exactly one signing cert - // 2) there is exactly one signing key - // 3) the cert and the key match - - keyinfo := &msp.KeyInfo{KeyIdentifier: "PEER", KeyMaterial: keys[0]} + /* FIXME: for now we're making the following assumptions + 1) there is exactly one signing cert + 2) BCCSP's KeyStore has the the private key that matches SKI of + signing cert + */ - sigid := &msp.SigningIdentityInfo{PublicSigner: signcert[0], PrivateSigner: keyinfo} + sigid := &msp.SigningIdentityInfo{PublicSigner: signcert[0], PrivateSigner: nil} fmspconf := &msp.FabricMSPConfig{ Admins: admincert, diff --git a/msp/mgmt/mgmt.go b/msp/mgmt/mgmt.go index ce94062f301..72d75fb1677 100644 --- a/msp/mgmt/mgmt.go +++ b/msp/mgmt/mgmt.go @@ -21,17 +21,18 @@ import ( "errors" + "github.com/hyperledger/fabric/bccsp/factory" "github.com/hyperledger/fabric/msp" "github.com/op/go-logging" ) // LoadLocalMsp loads the local MSP from the specified directory -func LoadLocalMsp(dir string, mspID string) error { +func LoadLocalMsp(dir string, bccspConfig *factory.FactoryOpts, mspID string) error { if mspID == "" { return errors.New("The local MSP must have an ID") } - conf, err := msp.GetLocalMspConfig(dir, mspID) + conf, err := msp.GetLocalMspConfig(dir, bccspConfig, mspID) if err != nil { return err } diff --git a/msp/mgmt/peermsp_test.go b/msp/mgmt/peermsp_test.go index cca9d087c96..7ac86184a1b 100644 --- a/msp/mgmt/peermsp_test.go +++ b/msp/mgmt/peermsp_test.go @@ -33,7 +33,7 @@ func getTestMSPConfigPath() string { func TestLocalMSP(t *testing.T) { testMSPConfigPath := getTestMSPConfigPath() - err := LoadLocalMsp(testMSPConfigPath, "DEFAULT") + err := LoadLocalMsp(testMSPConfigPath, nil, "DEFAULT") if err != nil { t.Fatalf("LoadLocalMsp failed, err %s", err) diff --git a/msp/mgmt/testtools/config.go b/msp/mgmt/testtools/config.go index 8f38573824c..36cbe81bb18 100644 --- a/msp/mgmt/testtools/config.go +++ b/msp/mgmt/testtools/config.go @@ -48,7 +48,7 @@ func LoadMSPSetupForTesting(dir string) error { if dir, err = getConfigPath(dir); err != nil { return err } - conf, err := msp.GetLocalMspConfig(dir, "DEFAULT") + conf, err := msp.GetLocalMspConfig(dir, nil, "DEFAULT") if err != nil { return err } diff --git a/msp/msp_test.go b/msp/msp_test.go index 776c078d079..1506174c12b 100644 --- a/msp/msp_test.go +++ b/msp/msp_test.go @@ -71,7 +71,7 @@ func TestNoopMSP(t *testing.T) { } func TestMSPSetupBad(t *testing.T) { - _, err := GetLocalMspConfig("barf", "DEFAULT") + _, err := GetLocalMspConfig("barf", nil, "DEFAULT") if err == nil { t.Fatalf("Setup should have failed on an invalid config file") return @@ -283,7 +283,7 @@ var mspMgr MSPManager func TestMain(m *testing.M) { var err error - conf, err = GetLocalMspConfig("./sampleconfig/", "DEFAULT") + conf, err = GetLocalMspConfig("./sampleconfig/", nil, "DEFAULT") if err != nil { fmt.Printf("Setup should have succeeded, got err %s instead", err) os.Exit(-1) diff --git a/msp/mspimpl.go b/msp/mspimpl.go index af2e155782a..bc8d90cf37a 100644 --- a/msp/mspimpl.go +++ b/msp/mspimpl.go @@ -17,16 +17,14 @@ limitations under the License. package msp import ( - "crypto/x509" - "fmt" - - "encoding/pem" - "bytes" - + "crypto/x509" "crypto/x509/pkix" "encoding/asn1" + "encoding/hex" + "encoding/pem" "errors" + "fmt" "math/big" "reflect" @@ -80,34 +78,34 @@ func NewBccspMsp() (MSP, error) { return theMsp, nil } -func (msp *bccspmsp) getIdentityFromConf(idBytes []byte) (Identity, error) { +func (msp *bccspmsp) getIdentityFromConf(idBytes []byte) (Identity, bccsp.Key, error) { if idBytes == nil { - return nil, fmt.Errorf("getIdentityFromBytes error: nil idBytes") + return nil, nil, fmt.Errorf("getIdentityFromBytes error: nil idBytes") } // Decode the pem bytes pemCert, _ := pem.Decode(idBytes) if pemCert == nil { - return nil, fmt.Errorf("getIdentityFromBytes error: could not decode pem bytes") + return nil, nil, fmt.Errorf("getIdentityFromBytes error: could not decode pem bytes") } // get a cert var cert *x509.Certificate cert, err := x509.ParseCertificate(pemCert.Bytes) if err != nil { - return nil, fmt.Errorf("getIdentityFromBytes error: failed to parse x509 cert, err %s", err) + return nil, nil, fmt.Errorf("getIdentityFromBytes error: failed to parse x509 cert, err %s", err) } // get the public key in the right format certPubK, err := msp.bccsp.KeyImport(cert, &bccsp.X509PublicKeyImportOpts{Temporary: true}) if err != nil { - return nil, fmt.Errorf("getIdentityFromBytes error: failed to import certitifacate's public key [%s]", err) + return nil, nil, fmt.Errorf("getIdentityFromBytes error: failed to import certitifacate's public key [%s]", err) } return newIdentity(&IdentityIdentifier{ Mspid: msp.name, Id: "IDENTITY"}, /* FIXME: not clear where we would get the identifier for this identity */ - cert, certPubK, msp), nil + cert, certPubK, msp), certPubK, nil } func (msp *bccspmsp) getSigningIdentityFromConf(sidInfo *m.SigningIdentityInfo) (SigningIdentity, error) { @@ -115,22 +113,31 @@ func (msp *bccspmsp) getSigningIdentityFromConf(sidInfo *m.SigningIdentityInfo) return nil, fmt.Errorf("getIdentityFromBytes error: nil sidInfo") } - // extract the public part of the identity - idPub, err := msp.getIdentityFromConf(sidInfo.PublicSigner) + // Extract the public part of the identity + idPub, pubKey, err := msp.getIdentityFromConf(sidInfo.PublicSigner) if err != nil { return nil, err } - // Get secret key - pemKey, _ := pem.Decode(sidInfo.PrivateSigner.KeyMaterial) - key, err := msp.bccsp.KeyImport(pemKey.Bytes, &bccsp.ECDSAPrivateKeyImportOpts{Temporary: true}) + // Find the matching private key in the BCCSP keystore + privKey, err := msp.bccsp.GetKey(pubKey.SKI()) + // Less Secure: Attempt to import Private Key from KeyInfo, if BCCSP was not able to find the key if err != nil { - return nil, fmt.Errorf("getIdentityFromBytes error: Failed to import EC private key, err %s", err) + mspLogger.Debugf("Could not find SKI [%s], trying KeyMaterial field: %s\n", hex.EncodeToString(pubKey.SKI()), err) + if sidInfo.PrivateSigner == nil || sidInfo.PrivateSigner.KeyMaterial == nil { + return nil, fmt.Errorf("KeyMaterial not found in SigningIdentityInfo") + } + + pemKey, _ := pem.Decode(sidInfo.PrivateSigner.KeyMaterial) + privKey, err = msp.bccsp.KeyImport(pemKey.Bytes, &bccsp.ECDSAPrivateKeyImportOpts{Temporary: true}) + if err != nil { + return nil, fmt.Errorf("getIdentityFromBytes error: Failed to import EC private key, err %s", err) + } } // get the peer signer peerSigner := &signer.CryptoSigner{} - err = peerSigner.Init(msp.bccsp, key) + err = peerSigner.Init(msp.bccsp, privKey) if err != nil { return nil, fmt.Errorf("getIdentityFromBytes error: Failed initializing CryptoSigner, err %s", err) } @@ -243,7 +250,7 @@ func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error { // make and fill the set of admin certs (if present) msp.admins = make([]Identity, len(conf.Admins)) for i, admCert := range conf.Admins { - id, err := msp.getIdentityFromConf(admCert) + id, _, err := msp.getIdentityFromConf(admCert) if err != nil { return err } @@ -257,7 +264,7 @@ func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error { } msp.rootCerts = make([]Identity, len(conf.RootCerts)) for i, trustedCert := range conf.RootCerts { - id, err := msp.getIdentityFromConf(trustedCert) + id, _, err := msp.getIdentityFromConf(trustedCert) if err != nil { return err } @@ -268,7 +275,7 @@ func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error { // make and fill the set of intermediate certs (if present) msp.intermediateCerts = make([]Identity, len(conf.IntermediateCerts)) for i, trustedCert := range conf.IntermediateCerts { - id, err := msp.getIdentityFromConf(trustedCert) + id, _, err := msp.getIdentityFromConf(trustedCert) if err != nil { return err } diff --git a/msp/sampleconfig/keystore/key.pem b/msp/sampleconfig/keystore/be550e94606441378b27a5e4dc71400827b80d413001616250f6519137460808_sk similarity index 100% rename from msp/sampleconfig/keystore/key.pem rename to msp/sampleconfig/keystore/be550e94606441378b27a5e4dc71400827b80d413001616250f6519137460808_sk diff --git a/orderer/localconfig/config.go b/orderer/localconfig/config.go index 81dd87a31f5..e700cb4f3b6 100644 --- a/orderer/localconfig/config.go +++ b/orderer/localconfig/config.go @@ -28,6 +28,8 @@ import ( "github.com/Shopify/sarama" "github.com/op/go-logging" "github.com/spf13/viper" + + bccsp "github.com/hyperledger/fabric/bccsp/factory" ) var logger = logging.MustGetLogger("orderer/config") @@ -52,6 +54,7 @@ type General struct { LogLevel string LocalMSPDir string LocalMSPID string + BCCSP *bccsp.FactoryOpts } //TLS contains config used to configure TLS @@ -155,6 +158,7 @@ var defaults = TopLevel{ LogLevel: "INFO", LocalMSPDir: "../msp/sampleconfig/", LocalMSPID: "DEFAULT", + BCCSP: &bccsp.DefaultOpts, }, RAMLedger: RAMLedger{ HistorySize: 10000, diff --git a/orderer/main.go b/orderer/main.go index 6003250a02f..7595157b82c 100644 --- a/orderer/main.go +++ b/orderer/main.go @@ -85,7 +85,7 @@ func main() { } // Load local MSP - err = mspmgmt.LoadLocalMsp(conf.General.LocalMSPDir, conf.General.LocalMSPID) + err = mspmgmt.LoadLocalMsp(conf.General.LocalMSPDir, conf.General.BCCSP, conf.General.LocalMSPID) if err != nil { // Handle errors reading the config file panic(fmt.Errorf("Failed initializing crypto [%s]", err)) } diff --git a/orderer/orderer.yaml b/orderer/orderer.yaml index bd0dd40262e..709762d23ab 100644 --- a/orderer/orderer.yaml +++ b/orderer/orderer.yaml @@ -65,6 +65,18 @@ General: Profile: Enabled: false Address: 0.0.0.0:6060 + + # BCCSP (Blockchain crypto provider): Select which crypto implementation or + # library to use + BCCSP: + Default: SW + SW: + Hash: SHA3 + Security: 256 + # Location of Key Store. If this is unset, a temporary location will + # be chosen using 'LocalMSPDir'/keystore + FileKeyStore: + KeyStore: ################################################################################ # diff --git a/orderer/sbft_test.go b/orderer/sbft_test.go index 9503780e249..de3fa008047 100644 --- a/orderer/sbft_test.go +++ b/orderer/sbft_test.go @@ -120,7 +120,7 @@ func TestSbftPeer(t *testing.T) { consenters := make(map[string]multichain.Consenter) consenters[sbftName] = sbftConsenter - err = mspmgmt.LoadLocalMsp(conf.General.LocalMSPDir, conf.General.LocalMSPID) + err = mspmgmt.LoadLocalMsp(conf.General.LocalMSPDir, conf.General.BCCSP, conf.General.LocalMSPID) if err != nil { // Handle errors reading the config file panic(fmt.Errorf("Failed initializing crypto [%s]", err)) } diff --git a/peer/common/common.go b/peer/common/common.go index 2319cc003eb..8d779590da6 100644 --- a/peer/common/common.go +++ b/peer/common/common.go @@ -21,6 +21,7 @@ import ( "os" "path/filepath" + "github.com/hyperledger/fabric/bccsp/factory" "github.com/hyperledger/fabric/common/flogging" "github.com/hyperledger/fabric/core/errors" "github.com/hyperledger/fabric/core/peer" @@ -61,7 +62,14 @@ func InitConfig(cmdRoot string) error { //InitCrypto initializes crypto for this peer func InitCrypto(mspMgrConfigDir string, localMSPID string) error { - err := mspmgmt.LoadLocalMsp(mspMgrConfigDir, localMSPID) + // Init the BCCSP + var bccspConfig *factory.FactoryOpts + err := viper.UnmarshalKey("peer.BCCSP", &bccspConfig) + if err != nil { + return fmt.Errorf("Could not parse YAML config [%s]", err) + } + + err = mspmgmt.LoadLocalMsp(mspMgrConfigDir, bccspConfig, localMSPID) if err != nil { return fmt.Errorf("Fatal error when setting up MSP from directory %s: err %s\n", mspMgrConfigDir, err) } diff --git a/peer/core.yaml b/peer/core.yaml index 8716b5dfdc0..a711074fe1a 100644 --- a/peer/core.yaml +++ b/peer/core.yaml @@ -195,6 +195,18 @@ peer: # Path on the file system where peer will store data (eg ledger) fileSystemPath: /var/hyperledger/production + # BCCSP (Blockchain crypto provider): Select which crypto implementation or + # library to use + BCCSP: + Default: SW + SW: + Hash: SHA3 + Security: 256 + # Location of Key Store, can be subdirectory of SbftLocal.DataDir + FileKeyStore: + # If "", defaults to 'mspConfigPath'/keystore + KeyStore: + # Path on the file system where peer will find MSP local configurations mspConfigPath: msp/sampleconfig