From f4e359ffab771f9f99c81c92e190eca818b925fa Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Sun, 19 Feb 2017 14:45:31 +0100 Subject: [PATCH] BCCSP KeyStore cleanup This change-set introduces New* methods to instantiate file-based key stores and dummy key stores. The purpose is to streamline the instantiation of keystore and allow reusability in the pkcs11 package. Change-Id: I1cf6b3e6a9c3244bdc46f6aa164a49acb1e4b1f0 Signed-off-by: Angelo De Caro --- bccsp/factory/pkcs11factory.go | 7 +++-- bccsp/factory/swfactory.go | 7 +++-- bccsp/pkcs11/dummyks.go | 2 +- bccsp/pkcs11/fileks.go | 2 +- bccsp/pkcs11/impl_test.go | 2 +- bccsp/sw/dummyks.go | 16 ++++++++---- bccsp/sw/fileks.go | 47 ++++++++++++++++++++-------------- bccsp/sw/fileks_test.go | 6 ++--- bccsp/sw/impl.go | 2 +- bccsp/sw/impl_test.go | 4 +-- 10 files changed, 54 insertions(+), 41 deletions(-) diff --git a/bccsp/factory/pkcs11factory.go b/bccsp/factory/pkcs11factory.go index d009fb4238c..099723c54b0 100644 --- a/bccsp/factory/pkcs11factory.go +++ b/bccsp/factory/pkcs11factory.go @@ -49,17 +49,16 @@ func (f *PKCS11Factory) Get(config *FactoryOpts) (bccsp.BCCSP, error) { //TODO: PKCS11 does not need a keystore, but we have not migrated all of PKCS11 BCCSP to PKCS11 yet var ks bccsp.KeyStore if p11Opts.Ephemeral == true { - ks = &sw.DummyKeyStore{} + ks = sw.NewDummyKeyStore() } else if p11Opts.FileKeystore != nil { - fks := &sw.FileBasedKeyStore{} - err := fks.Init(nil, p11Opts.FileKeystore.KeyStorePath, false) + fks, err := sw.NewFileBasedKeyStore(nil, p11Opts.FileKeystore.KeyStorePath, false) if err != nil { return nil, fmt.Errorf("Failed to initialize software key store: %s", err) } ks = fks } else { // Default to DummyKeystore - ks = &sw.DummyKeyStore{} + ks = sw.NewDummyKeyStore() } err := pkcs11.InitPKCS11(p11Opts.Library, p11Opts.Pin, p11Opts.Label) if err != nil { diff --git a/bccsp/factory/swfactory.go b/bccsp/factory/swfactory.go index b30f3554d4b..c95f0be0f2c 100644 --- a/bccsp/factory/swfactory.go +++ b/bccsp/factory/swfactory.go @@ -47,17 +47,16 @@ func (f *SWFactory) Get(config *FactoryOpts) (bccsp.BCCSP, error) { var ks bccsp.KeyStore if swOpts.Ephemeral == true { - ks = &sw.DummyKeyStore{} + ks = sw.NewDummyKeyStore() } else if swOpts.FileKeystore != nil { - fks := &sw.FileBasedKeyStore{} - err := fks.Init(nil, swOpts.FileKeystore.KeyStorePath, false) + fks, err := sw.NewFileBasedKeyStore(nil, swOpts.FileKeystore.KeyStorePath, false) if err != nil { return nil, fmt.Errorf("Failed to initialize software key store: %s", err) } ks = fks } else { // Default to DummyKeystore - ks = &sw.DummyKeyStore{} + ks = sw.NewDummyKeyStore() } return sw.New(swOpts.SecLevel, swOpts.HashFamily, ks) diff --git a/bccsp/pkcs11/dummyks.go b/bccsp/pkcs11/dummyks.go index c28544032e3..37e4827c802 100644 --- a/bccsp/pkcs11/dummyks.go +++ b/bccsp/pkcs11/dummyks.go @@ -22,7 +22,7 @@ import ( "github.com/hyperledger/fabric/bccsp" ) -// DummyKeyStore is a read-only KeyStore that neither loads nor stores keys. +// dummyKeyStore is a read-only KeyStore that neither loads nor stores keys. type DummyKeyStore struct { } diff --git a/bccsp/pkcs11/fileks.go b/bccsp/pkcs11/fileks.go index ff7f98b4d55..8a1af88d51f 100644 --- a/bccsp/pkcs11/fileks.go +++ b/bccsp/pkcs11/fileks.go @@ -30,7 +30,7 @@ import ( "github.com/hyperledger/fabric/bccsp/utils" ) -// FileBasedKeyStore is a folder-based KeyStore. +// fileBasedKeyStore is a folder-based KeyStore. // Each key is stored in a separated file whose name contains the key's SKI // and flags to identity the key's type. All the keys are stored in // a folder whose path is provided at initialization time. diff --git a/bccsp/pkcs11/impl_test.go b/bccsp/pkcs11/impl_test.go index 8d0bd7e2e32..b08283da5f1 100644 --- a/bccsp/pkcs11/impl_test.go +++ b/bccsp/pkcs11/impl_test.go @@ -89,7 +89,7 @@ func TestMain(m *testing.M) { os.Exit(-1) } - currentSWBCCSP, err = sw.New(config.securityLevel, config.hashFamily, &sw.DummyKeyStore{}) + currentSWBCCSP, err = sw.New(config.securityLevel, config.hashFamily, sw.NewDummyKeyStore()) if err != nil { fmt.Printf("Failed initiliazing BCCSP at [%d, %s]: [%s]", config.securityLevel, config.hashFamily, err) os.Exit(-1) diff --git a/bccsp/sw/dummyks.go b/bccsp/sw/dummyks.go index c94e7e0a3c4..c800649b602 100644 --- a/bccsp/sw/dummyks.go +++ b/bccsp/sw/dummyks.go @@ -21,23 +21,29 @@ import ( "github.com/hyperledger/fabric/bccsp" ) -// DummyKeyStore is a read-only KeyStore that neither loads nor stores keys. -type DummyKeyStore struct { +// NewDummyKeyStore instantiate a dummy key store +// that neither loads nor stores keys +func NewDummyKeyStore() bccsp.KeyStore { + return &dummyKeyStore{} +} + +// 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 { +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) { +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) { +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/bccsp/sw/fileks.go b/bccsp/sw/fileks.go index 661c3949106..f1bd2ca3573 100644 --- a/bccsp/sw/fileks.go +++ b/bccsp/sw/fileks.go @@ -33,14 +33,23 @@ import ( "github.com/hyperledger/fabric/bccsp/utils" ) -// FileBasedKeyStore is a folder-based KeyStore. +// NewFileBasedKeyStore instantiated a file-based key store at a given position. +// The key store can be encrypted if a non-empty password is specifiec. +// It can be also be set as read only. In this case, any store operation +// will be forbidden +func NewFileBasedKeyStore(pwd []byte, path string, readOnly bool) (bccsp.KeyStore, error) { + ks := &fileBasedKeyStore{} + return ks, ks.Init(pwd, path, readOnly) +} + +// fileBasedKeyStore is a folder-based KeyStore. // Each key is stored in a separated file whose name contains the key's SKI // and flags to identity the key's type. All the keys are stored in // a folder whose path is provided at initialization time. // The KeyStore can be initialized with a password, this password // is used to encrypt and decrypt the files storing the keys. // A KeyStore can be read only to avoid the overwriting of keys. -type FileBasedKeyStore struct { +type fileBasedKeyStore struct { path string readOnly bool @@ -62,7 +71,7 @@ type FileBasedKeyStore struct { // key-store is initialized without a password, then retrieving keys from the // KeyStore will fail. // A KeyStore can be read only to avoid the overwriting of keys. -func (ks *FileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error { +func (ks *fileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error { // Validate inputs // pwd can be nil @@ -97,12 +106,12 @@ func (ks *FileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error // ReadOnly returns true if this KeyStore is read only, false otherwise. // If ReadOnly is true then StoreKey will fail. -func (ks *FileBasedKeyStore) ReadOnly() bool { +func (ks *fileBasedKeyStore) ReadOnly() bool { return ks.readOnly } // GetKey returns a key object whose SKI is the one passed. -func (ks *FileBasedKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) { +func (ks *fileBasedKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) { // Validate arguments if len(ski) == 0 { return nil, errors.New("Invalid SKI. Cannot be of zero length.") @@ -156,7 +165,7 @@ func (ks *FileBasedKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) { // StoreKey stores the key k in this KeyStore. // If this KeyStore is read only then the method will fail. -func (ks *FileBasedKeyStore) StoreKey(k bccsp.Key) (err error) { +func (ks *fileBasedKeyStore) StoreKey(k bccsp.Key) (err error) { if ks.readOnly { return errors.New("Read only KeyStore.") } @@ -212,7 +221,7 @@ func (ks *FileBasedKeyStore) StoreKey(k bccsp.Key) (err error) { return } -func (ks *FileBasedKeyStore) getSuffix(alias string) string { +func (ks *fileBasedKeyStore) getSuffix(alias string) string { files, _ := ioutil.ReadDir(ks.path) for _, f := range files { if strings.HasPrefix(f.Name(), alias) { @@ -231,7 +240,7 @@ func (ks *FileBasedKeyStore) getSuffix(alias string) string { return "" } -func (ks *FileBasedKeyStore) storePrivateKey(alias string, privateKey interface{}) error { +func (ks *fileBasedKeyStore) storePrivateKey(alias string, privateKey interface{}) error { rawKey, err := utils.PrivateKeyToPEM(privateKey, ks.pwd) if err != nil { logger.Errorf("Failed converting private key to PEM [%s]: [%s]", alias, err) @@ -247,7 +256,7 @@ func (ks *FileBasedKeyStore) storePrivateKey(alias string, privateKey interface{ return nil } -func (ks *FileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) error { +func (ks *fileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) error { rawKey, err := utils.PublicKeyToPEM(publicKey, ks.pwd) if err != nil { logger.Errorf("Failed converting public key to PEM [%s]: [%s]", alias, err) @@ -263,7 +272,7 @@ func (ks *FileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) return nil } -func (ks *FileBasedKeyStore) storeKey(alias string, key []byte) error { +func (ks *fileBasedKeyStore) storeKey(alias string, key []byte) error { pem, err := utils.AEStoEncryptedPEM(key, ks.pwd) if err != nil { logger.Errorf("Failed converting key to PEM [%s]: [%s]", alias, err) @@ -279,7 +288,7 @@ func (ks *FileBasedKeyStore) storeKey(alias string, key []byte) error { return nil } -func (ks *FileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) { +func (ks *fileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) { path := ks.getPathForAlias(alias, "sk") logger.Debugf("Loading private key [%s] at [%s]...", alias, path) @@ -300,7 +309,7 @@ func (ks *FileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) { return privateKey, nil } -func (ks *FileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) { +func (ks *fileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) { path := ks.getPathForAlias(alias, "pk") logger.Debugf("Loading public key [%s] at [%s]...", alias, path) @@ -321,7 +330,7 @@ func (ks *FileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) { return privateKey, nil } -func (ks *FileBasedKeyStore) loadKey(alias string) ([]byte, error) { +func (ks *fileBasedKeyStore) loadKey(alias string) ([]byte, error) { path := ks.getPathForAlias(alias, "key") logger.Debugf("Loading key [%s] at [%s]...", alias, path) @@ -342,13 +351,13 @@ func (ks *FileBasedKeyStore) loadKey(alias string) ([]byte, error) { return key, nil } -func (ks *FileBasedKeyStore) close() error { +func (ks *fileBasedKeyStore) close() error { ks.isOpen = false logger.Debug("Closing keystore...done!") return nil } -func (ks *FileBasedKeyStore) createKeyStoreIfNotExists() error { +func (ks *fileBasedKeyStore) createKeyStoreIfNotExists() error { // Check keystore directory ksPath := ks.path missing, err := utils.DirMissingOrEmpty(ksPath) @@ -365,7 +374,7 @@ func (ks *FileBasedKeyStore) createKeyStoreIfNotExists() error { return nil } -func (ks *FileBasedKeyStore) createKeyStore() error { +func (ks *fileBasedKeyStore) createKeyStore() error { // Create keystore directory root if it doesn't exist yet ksPath := ks.path logger.Debugf("Creating KeyStore at [%s]...", ksPath) @@ -376,13 +385,13 @@ func (ks *FileBasedKeyStore) createKeyStore() error { return nil } -func (ks *FileBasedKeyStore) deleteKeyStore() error { +func (ks *fileBasedKeyStore) deleteKeyStore() error { logger.Debugf("Removing KeyStore at [%s].", ks.path) return os.RemoveAll(ks.path) } -func (ks *FileBasedKeyStore) openKeyStore() error { +func (ks *fileBasedKeyStore) openKeyStore() error { if ks.isOpen { return nil } @@ -392,6 +401,6 @@ func (ks *FileBasedKeyStore) openKeyStore() error { return nil } -func (ks *FileBasedKeyStore) getPathForAlias(alias, suffix string) string { +func (ks *fileBasedKeyStore) getPathForAlias(alias, suffix string) string { return filepath.Join(ks.path, alias+"_"+suffix) } diff --git a/bccsp/sw/fileks_test.go b/bccsp/sw/fileks_test.go index 8fdd8b201f3..b91c6695291 100644 --- a/bccsp/sw/fileks_test.go +++ b/bccsp/sw/fileks_test.go @@ -23,13 +23,13 @@ import ( ) func TestInvalidStoreKey(t *testing.T) { - ks := &FileBasedKeyStore{} - if err := ks.Init(nil, filepath.Join(os.TempDir(), "bccspks"), false); err != nil { + ks, err := NewFileBasedKeyStore(nil, filepath.Join(os.TempDir(), "bccspks"), false) + if err != nil { fmt.Printf("Failed initiliazing KeyStore [%s]", err) os.Exit(-1) } - err := ks.StoreKey(nil) + err = ks.StoreKey(nil) if err == nil { t.Fatal("Error should be different from nil in this case") } diff --git a/bccsp/sw/impl.go b/bccsp/sw/impl.go index ea8751a95db..8871c81ffb8 100644 --- a/bccsp/sw/impl.go +++ b/bccsp/sw/impl.go @@ -47,7 +47,7 @@ var ( // NewDefaultSecurityLevel returns a new instance of the software-based BCCSP // at security level 256, hash family SHA2 and using FolderBasedKeyStore as KeyStore. func NewDefaultSecurityLevel(keyStorePath string) (bccsp.BCCSP, error) { - ks := &FileBasedKeyStore{} + ks := &fileBasedKeyStore{} if err := ks.Init(nil, keyStorePath, false); err != nil { return nil, fmt.Errorf("Failed initializing key store [%s]", err) } diff --git a/bccsp/sw/impl_test.go b/bccsp/sw/impl_test.go index 2f9a1c7bff1..588867096e0 100644 --- a/bccsp/sw/impl_test.go +++ b/bccsp/sw/impl_test.go @@ -58,8 +58,8 @@ type testConfig struct { } func TestMain(m *testing.M) { - ks := &FileBasedKeyStore{} - if err := ks.Init(nil, os.TempDir(), false); err != nil { + ks, err := NewFileBasedKeyStore(nil, os.TempDir(), false); + if err != nil { fmt.Printf("Failed initiliazing KeyStore [%s]", err) os.Exit(-1) }