From 4464f6c7c9eb13bb2ae06ed4111ba68efd935701 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Tue, 13 Dec 2016 10:36:06 +0100 Subject: [PATCH] MSP crytpo and HASH cleanup This change-sets removes all dependencies to the crytpo/primitives package from the msp package. The MSP uses now only the BCCSP for its cryptographic operations. This change-sets also removes all dependencies to the primitives.Hash function. The BCCSP is used to replace thos calls. Change-Id: Ia1432fac29745bb4f42b9acb8334caf69f115b3d Signed-off-by: Angelo De Caro --- core/crypto/bccsp/factory/factory.go | 9 ++++++ core/crypto/bccsp/sw/dummyks.go | 28 ++++++++++++++++++ core/crypto/bccsp/sw/impl.go | 12 ++++++-- msp/identities.go | 43 +++++++++++++++++----------- msp/msp_test.go | 4 --- msp/mspimpl.go | 11 ++++--- peer/chaincode/upgrade_test.go | 4 --- protos/utils/txutils.go | 24 ++++++++++------ 8 files changed, 92 insertions(+), 43 deletions(-) create mode 100644 core/crypto/bccsp/sw/dummyks.go diff --git a/core/crypto/bccsp/factory/factory.go b/core/crypto/bccsp/factory/factory.go index 0245917008c..cfcce4ec90a 100644 --- a/core/crypto/bccsp/factory/factory.go +++ b/core/crypto/bccsp/factory/factory.go @@ -70,6 +70,15 @@ func GetDefault() (bccsp.BCCSP, error) { return defaultBCCSP, nil } +// GetDefaultOrPanic returns a non-ephemeral (long-term) BCCSP or panic if an error occurs. +func GetDefaultOrPanic() bccsp.BCCSP { + if err := initFactories(); err != nil { + panic(err) + } + + return defaultBCCSP +} + // GetBCCSP returns a BCCSP created according to the options passed in input. func GetBCCSP(opts Opts) (bccsp.BCCSP, error) { if err := initFactories(); err != nil { diff --git a/core/crypto/bccsp/sw/dummyks.go b/core/crypto/bccsp/sw/dummyks.go new file mode 100644 index 00000000000..c2e0c2cf864 --- /dev/null +++ b/core/crypto/bccsp/sw/dummyks.go @@ -0,0 +1,28 @@ +package sw + +import ( + "errors" + + "github.com/hyperledger/fabric/core/crypto/bccsp" +) + +// DummyKeyStore is a read-only KeyStore that neither loads nor stores keys. +type DummyKeyStore struct { +} + +// ReadOnly returns true if this KeyStore is read only, false otherwise. +// If ReadOnly is true then StoreKey will fail. +func (ks *DummyKeyStore) ReadOnly() bool { + return true +} + +// GetKey returns a key object whose SKI is the one passed. +func (ks *DummyKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) { + return nil, errors.New("Key not found. This is a dummy KeyStore") +} + +// StoreKey stores the key k in this KeyStore. +// If this KeyStore is read only then the method will fail. +func (ks *DummyKeyStore) StoreKey(k bccsp.Key) (err error) { + return errors.New("Cannot store key. This is a dummy read-only KeyStore") +} diff --git a/core/crypto/bccsp/sw/impl.go b/core/crypto/bccsp/sw/impl.go index 2e19357fd5f..899ed679458 100644 --- a/core/crypto/bccsp/sw/impl.go +++ b/core/crypto/bccsp/sw/impl.go @@ -46,7 +46,7 @@ var ( ) // NewDefaultSecurityLevel returns a new instance of the software-based BCCSP -// at security level 256, hash family SHA2 and using FolderBasedKeyStore as keystore. +// at security level 256, hash family SHA2 and using FolderBasedKeyStore as KeyStore. func NewDefaultSecurityLevel(keyStorePath string) (bccsp.BCCSP, error) { ks := &FileBasedKeyStore{} if err := ks.Init(nil, keyStorePath, false); err != nil { @@ -56,8 +56,14 @@ func NewDefaultSecurityLevel(keyStorePath string) (bccsp.BCCSP, error) { return New(256, "SHA2", ks) } +// NewDefaultSecurityLevel returns a new instance of the software-based BCCSP +// at security level 256, hash family SHA2 and using the passed KeyStore. +func NewDefaultSecurityLevelWithKeystore(keyStore bccsp.KeyStore) (bccsp.BCCSP, error) { + return New(256, "SHA2", keyStore) +} + // New returns a new instance of the software-based BCCSP -// set at the passed security level, hash family and keystore. +// set at the passed security level, hash family and KeyStore. func New(securityLevel int, hashFamily string, keyStore bccsp.KeyStore) (bccsp.BCCSP, error) { // Init config conf := &config{} @@ -66,7 +72,7 @@ func New(securityLevel int, hashFamily string, keyStore bccsp.KeyStore) (bccsp.B return nil, fmt.Errorf("Failed initializing configuration [%s]", err) } - // Check keystore + // Check KeyStore if keyStore == nil { return nil, errors.New("Invalid bccsp.KeyStore instance. It must be different from nil.") } diff --git a/msp/identities.go b/msp/identities.go index a9ade688af6..45d4e5568ab 100644 --- a/msp/identities.go +++ b/msp/identities.go @@ -25,10 +25,10 @@ import ( "encoding/asn1" + "errors" + "github.com/hyperledger/fabric/core/crypto/bccsp" - "github.com/hyperledger/fabric/core/crypto/bccsp/factory" "github.com/hyperledger/fabric/core/crypto/bccsp/signer" - "github.com/hyperledger/fabric/core/crypto/primitives" ) type identity struct { @@ -42,12 +42,12 @@ type identity struct { pk bccsp.Key // reference to the MSP that "owns" this identity - myMsp MSP + msp *bccspmsp } -func newIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, myMsp MSP) Identity { +func newIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, msp *bccspmsp) Identity { mspLogger.Infof("Creating identity instance for ID %s", id) - return &identity{id: id, cert: cert, pk: pk, myMsp: myMsp} + return &identity{id: id, cert: cert, pk: pk, msp: msp} } // GetIdentifier returns the identifier (MSPID/IDID) for this instance @@ -62,7 +62,7 @@ func (id *identity) GetMSPIdentifier() string { // IsValid returns nil if this instance is a valid identity or an error otherwise func (id *identity) IsValid() error { - return id.myMsp.Validate(id) + return id.msp.Validate(id) } // GetOrganizationUnits returns the OU for this instance @@ -76,21 +76,22 @@ func (id *identity) GetOrganizationUnits() string { // signature; it returns nil if so or an error otherwise func (id *identity) Verify(msg []byte, sig []byte) error { mspLogger.Infof("Verifying signature") - bccsp, err := factory.GetDefault() + + // Compute Hash + digest, err := id.msp.bccsp.Hash(msg, &bccsp.SHAOpts{}) if err != nil { - return fmt.Errorf("Failed getting default BCCSP [%s]", err) - } else if bccsp == nil { - return fmt.Errorf("Failed getting default BCCSP. Nil instance.") + return fmt.Errorf("Failed computing digest [%s]", err) } - valid, err := bccsp.Verify(id.pk, sig, primitives.Hash(msg), nil) + // Verify signature + valid, err := id.msp.bccsp.Verify(id.pk, sig, digest, nil) if err != nil { return fmt.Errorf("Could not determine the validity of the signature, err %s", err) } else if !valid { - return fmt.Errorf("The signature is invalid") - } else { - return nil + return errors.New("The signature is invalid") } + + return nil } func (id *identity) VerifyOpts(msg []byte, sig []byte, opts SignatureOpts) error { @@ -131,15 +132,23 @@ type signingidentity struct { signer *signer.CryptoSigner } -func newSigningIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, signer *signer.CryptoSigner, myMsp MSP) SigningIdentity { +func newSigningIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, signer *signer.CryptoSigner, msp *bccspmsp) SigningIdentity { mspLogger.Infof("Creating signing identity instance for ID %s", id) - return &signingidentity{identity{id: id, cert: cert, pk: pk, myMsp: myMsp}, signer} + return &signingidentity{identity{id: id, cert: cert, pk: pk, msp: msp}, signer} } // Sign produces a signature over msg, signed by this instance func (id *signingidentity) Sign(msg []byte) ([]byte, error) { mspLogger.Infof("Signing message") - return id.signer.Sign(rand.Reader, primitives.Hash(msg), nil) + + // Compute Hash + digest, err := id.msp.bccsp.Hash(msg, &bccsp.SHAOpts{}) + if err != nil { + return nil, fmt.Errorf("Failed computing digest [%s]", err) + } + + // Sign + return id.signer.Sign(rand.Reader, digest, nil) } func (id *signingidentity) SignOpts(msg []byte, opts SignatureOpts) ([]byte, error) { diff --git a/msp/msp_test.go b/msp/msp_test.go index 81bb7fa0b1e..5f4c289afc6 100644 --- a/msp/msp_test.go +++ b/msp/msp_test.go @@ -4,8 +4,6 @@ import ( "os" "reflect" "testing" - - "github.com/hyperledger/fabric/core/crypto/primitives" ) var localMsp MSP @@ -158,8 +156,6 @@ func TestSignAndVerify(t *testing.T) { } func TestMain(m *testing.M) { - primitives.SetSecurityLevel("SHA2", 256) - retVal := m.Run() os.Exit(retVal) } diff --git a/msp/mspimpl.go b/msp/mspimpl.go index c58e5d16380..060d078b1d5 100644 --- a/msp/mspimpl.go +++ b/msp/mspimpl.go @@ -28,8 +28,8 @@ import ( "encoding/asn1" "github.com/hyperledger/fabric/core/crypto/bccsp" - "github.com/hyperledger/fabric/core/crypto/bccsp/factory" "github.com/hyperledger/fabric/core/crypto/bccsp/signer" + "github.com/hyperledger/fabric/core/crypto/bccsp/sw" ) // This is an instantiation of an MSP that @@ -58,12 +58,11 @@ type bccspmsp struct { func NewBccspMsp() (MSP, error) { mspLogger.Infof("Creating BCCSP-based MSP instance") - /* TODO: is the default BCCSP okay here?*/ - bccsp, err := factory.GetDefault() + // TODO: security level, hash family and keystore should + // be probably set in the appropriate way. + bccsp, err := sw.NewDefaultSecurityLevelWithKeystore(&sw.DummyKeyStore{}) if err != nil { - return nil, fmt.Errorf("Failed getting default BCCSP [%s]", err) - } else if bccsp == nil { - return nil, fmt.Errorf("Failed getting default BCCSP. Nil instance.") + return nil, fmt.Errorf("Failed initiliazing BCCSP [%s]", err) } theMsp := &bccspmsp{} diff --git a/peer/chaincode/upgrade_test.go b/peer/chaincode/upgrade_test.go index 4cf7866530d..1eda9d67332 100644 --- a/peer/chaincode/upgrade_test.go +++ b/peer/chaincode/upgrade_test.go @@ -25,7 +25,6 @@ import ( "github.com/hyperledger/fabric/peer/common" pb "github.com/hyperledger/fabric/protos/peer" // "github.com/hyperledger/fabric/protos/utils" - "github.com/hyperledger/fabric/core/crypto/primitives" "github.com/hyperledger/fabric/core/peer/msp" ) @@ -55,7 +54,6 @@ func initMSP() { } func TestUpgradeCmd(t *testing.T) { - primitives.SetSecurityLevel("SHA2", 256) InitMSP() signer, err := common.GetDefaultSigner() @@ -90,7 +88,6 @@ func TestUpgradeCmd(t *testing.T) { } func TestUpgradeCmdEndorseFail(t *testing.T) { - primitives.SetSecurityLevel("SHA2", 256) InitMSP() signer, err := common.GetDefaultSigner() @@ -129,7 +126,6 @@ func TestUpgradeCmdEndorseFail(t *testing.T) { } func TestUpgradeCmdSendTXFail(t *testing.T) { - primitives.SetSecurityLevel("SHA2", 256) InitMSP() signer, err := common.GetDefaultSigner() diff --git a/protos/utils/txutils.go b/protos/utils/txutils.go index 3e7de6de9d9..cbf37213a67 100644 --- a/protos/utils/txutils.go +++ b/protos/utils/txutils.go @@ -23,7 +23,8 @@ import ( "bytes" "github.com/golang/protobuf/proto" - "github.com/hyperledger/fabric/core/crypto/primitives" + "github.com/hyperledger/fabric/core/crypto/bccsp" + "github.com/hyperledger/fabric/core/crypto/bccsp/factory" "github.com/hyperledger/fabric/msp" "github.com/hyperledger/fabric/protos/common" "github.com/hyperledger/fabric/protos/peer" @@ -255,11 +256,11 @@ func GetBytesProposalPayloadForTx(payload *peer.ChaincodeProposalPayload, visibi // here, as an example, I'll code the visibility policy that allows the // full header but only the hash of the payload - // TODO: use bccsp interfaces and providers as soon as they are ready! - hash := primitives.GetDefaultHash()() - hash.Write(cppBytes) // hash the serialized ChaincodeProposalPayload object (stripped of the transient bytes) - - return hash.Sum(nil), nil + digest, err := factory.GetDefaultOrPanic().Hash(cppBytes, &bccsp.SHAOpts{}) + if err != nil { + return nil, fmt.Errorf("Failed computing digest [%s]", err) + } + return digest, nil } // GetProposalHash2 gets the proposal hash - this version @@ -272,8 +273,10 @@ func GetProposalHash2(header []byte, ccPropPayl []byte) ([]byte, error) { return nil, fmt.Errorf("Nil arguments") } - // TODO: use bccsp interfaces and providers as soon as they are ready! - hash := primitives.GetDefaultHash()() + hash, err := factory.GetDefaultOrPanic().GetHash(&bccsp.SHAOpts{}) + if err != nil { + return nil, fmt.Errorf("Failed instantiating hash function [%s]", err) + } hash.Write(header) // hash the serialized Header object hash.Write(ccPropPayl) // hash the bytes of the chaincode proposal payload that we are given @@ -301,7 +304,10 @@ func GetProposalHash1(header []byte, ccPropPayl []byte, visibility []byte) ([]by } // TODO: use bccsp interfaces and providers as soon as they are ready! - hash2 := primitives.GetDefaultHash()() + hash2, err := factory.GetDefaultOrPanic().GetHash(&bccsp.SHAOpts{}) + if err != nil { + return nil, fmt.Errorf("Failed instantiating hash function [%s]", err) + } hash2.Write(header) // hash the serialized Header object hash2.Write(ppBytes) // hash of the part of the chaincode proposal payload that will go to the tx