github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/bccsp/sw/fileks.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  package sw
    17  
    18  import (
    19  	"bytes"
    20  	"io/ioutil"
    21  	"os"
    22  	"sync"
    23  
    24  	"errors"
    25  	"strings"
    26  
    27  	"crypto/ecdsa"
    28  	"crypto/rsa"
    29  	"encoding/hex"
    30  	"fmt"
    31  	"path/filepath"
    32  
    33  	"github.com/hyperledger/fabric/bccsp"
    34  	"github.com/hyperledger/fabric/bccsp/utils"
    35  )
    36  
    37  // NewFileBasedKeyStore instantiated a file-based key store at a given position.
    38  // The key store can be encrypted if a non-empty password is specifiec.
    39  // It can be also be set as read only. In this case, any store operation
    40  // will be forbidden
    41  func NewFileBasedKeyStore(pwd []byte, path string, readOnly bool) (bccsp.KeyStore, error) {
    42  	ks := &fileBasedKeyStore{}
    43  	return ks, ks.Init(pwd, path, readOnly)
    44  }
    45  
    46  // fileBasedKeyStore is a folder-based KeyStore.
    47  // Each key is stored in a separated file whose name contains the key's SKI
    48  // and flags to identity the key's type. All the keys are stored in
    49  // a folder whose path is provided at initialization time.
    50  // The KeyStore can be initialized with a password, this password
    51  // is used to encrypt and decrypt the files storing the keys.
    52  // A KeyStore can be read only to avoid the overwriting of keys.
    53  type fileBasedKeyStore struct {
    54  	path string
    55  
    56  	readOnly bool
    57  	isOpen   bool
    58  
    59  	pwd []byte
    60  
    61  	// Sync
    62  	m sync.Mutex
    63  }
    64  
    65  // Init initializes this KeyStore with a password, a path to a folder
    66  // where the keys are stored and a read only flag.
    67  // Each key is stored in a separated file whose name contains the key's SKI
    68  // and flags to identity the key's type.
    69  // If the KeyStore is initialized with a password, this password
    70  // is used to encrypt and decrypt the files storing the keys.
    71  // The pwd can be nil for non-encrypted KeyStores. If an encrypted
    72  // key-store is initialized without a password, then retrieving keys from the
    73  // KeyStore will fail.
    74  // A KeyStore can be read only to avoid the overwriting of keys.
    75  func (ks *fileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error {
    76  	// Validate inputs
    77  	// pwd can be nil
    78  
    79  	if len(path) == 0 {
    80  		return errors.New("An invalid KeyStore path provided. Path cannot be an empty string.")
    81  	}
    82  
    83  	ks.m.Lock()
    84  	defer ks.m.Unlock()
    85  
    86  	if ks.isOpen {
    87  		return errors.New("KeyStore already initilized.")
    88  	}
    89  
    90  	ks.path = path
    91  	ks.pwd = utils.Clone(pwd)
    92  
    93  	err := ks.createKeyStoreIfNotExists()
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	err = ks.openKeyStore()
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	ks.readOnly = readOnly
   104  
   105  	return nil
   106  }
   107  
   108  // ReadOnly returns true if this KeyStore is read only, false otherwise.
   109  // If ReadOnly is true then StoreKey will fail.
   110  func (ks *fileBasedKeyStore) ReadOnly() bool {
   111  	return ks.readOnly
   112  }
   113  
   114  // GetKey returns a key object whose SKI is the one passed.
   115  func (ks *fileBasedKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) {
   116  	// Validate arguments
   117  	if len(ski) == 0 {
   118  		return nil, errors.New("Invalid SKI. Cannot be of zero length.")
   119  	}
   120  
   121  	suffix := ks.getSuffix(hex.EncodeToString(ski))
   122  
   123  	switch suffix {
   124  	case "key":
   125  		// Load the key
   126  		key, err := ks.loadKey(hex.EncodeToString(ski))
   127  		if err != nil {
   128  			return nil, fmt.Errorf("Failed loading key [%x] [%s]", ski, err)
   129  		}
   130  
   131  		return &aesPrivateKey{key, false}, nil
   132  	case "sk":
   133  		// Load the private key
   134  		key, err := ks.loadPrivateKey(hex.EncodeToString(ski))
   135  		if err != nil {
   136  			return nil, fmt.Errorf("Failed loading secret key [%x] [%s]", ski, err)
   137  		}
   138  
   139  		switch key.(type) {
   140  		case *ecdsa.PrivateKey:
   141  			return &ecdsaPrivateKey{key.(*ecdsa.PrivateKey)}, nil
   142  		case *rsa.PrivateKey:
   143  			return &rsaPrivateKey{key.(*rsa.PrivateKey)}, nil
   144  		default:
   145  			return nil, errors.New("Secret key type not recognized")
   146  		}
   147  	case "pk":
   148  		// Load the public key
   149  		key, err := ks.loadPublicKey(hex.EncodeToString(ski))
   150  		if err != nil {
   151  			return nil, fmt.Errorf("Failed loading public key [%x] [%s]", ski, err)
   152  		}
   153  
   154  		switch key.(type) {
   155  		case *ecdsa.PublicKey:
   156  			return &ecdsaPublicKey{key.(*ecdsa.PublicKey)}, nil
   157  		case *rsa.PublicKey:
   158  			return &rsaPublicKey{key.(*rsa.PublicKey)}, nil
   159  		default:
   160  			return nil, errors.New("Public key type not recognized")
   161  		}
   162  	default:
   163  		return ks.searchKeystoreForSKI(ski)
   164  	}
   165  }
   166  
   167  // StoreKey stores the key k in this KeyStore.
   168  // If this KeyStore is read only then the method will fail.
   169  func (ks *fileBasedKeyStore) StoreKey(k bccsp.Key) (err error) {
   170  	if ks.readOnly {
   171  		return errors.New("Read only KeyStore.")
   172  	}
   173  
   174  	if k == nil {
   175  		return errors.New("Invalid key. It must be different from nil.")
   176  	}
   177  	switch k.(type) {
   178  	case *ecdsaPrivateKey:
   179  		kk := k.(*ecdsaPrivateKey)
   180  
   181  		err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey)
   182  		if err != nil {
   183  			return fmt.Errorf("Failed storing ECDSA private key [%s]", err)
   184  		}
   185  
   186  	case *ecdsaPublicKey:
   187  		kk := k.(*ecdsaPublicKey)
   188  
   189  		err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey)
   190  		if err != nil {
   191  			return fmt.Errorf("Failed storing ECDSA public key [%s]", err)
   192  		}
   193  
   194  	case *rsaPrivateKey:
   195  		kk := k.(*rsaPrivateKey)
   196  
   197  		err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey)
   198  		if err != nil {
   199  			return fmt.Errorf("Failed storing RSA private key [%s]", err)
   200  		}
   201  
   202  	case *rsaPublicKey:
   203  		kk := k.(*rsaPublicKey)
   204  
   205  		err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey)
   206  		if err != nil {
   207  			return fmt.Errorf("Failed storing RSA public key [%s]", err)
   208  		}
   209  
   210  	case *aesPrivateKey:
   211  		kk := k.(*aesPrivateKey)
   212  
   213  		err = ks.storeKey(hex.EncodeToString(k.SKI()), kk.privKey)
   214  		if err != nil {
   215  			return fmt.Errorf("Failed storing AES key [%s]", err)
   216  		}
   217  
   218  	default:
   219  		return fmt.Errorf("Key type not reconigned [%s]", k)
   220  	}
   221  
   222  	return
   223  }
   224  
   225  func (ks *fileBasedKeyStore) searchKeystoreForSKI(ski []byte) (k bccsp.Key, err error) {
   226  
   227  	files, _ := ioutil.ReadDir(ks.path)
   228  	for _, f := range files {
   229  		if f.IsDir() {
   230  			continue
   231  		}
   232  		raw, err := ioutil.ReadFile(filepath.Join(ks.path, f.Name()))
   233  
   234  		key, err := utils.PEMtoPrivateKey(raw, ks.pwd)
   235  		if err != nil {
   236  			continue
   237  		}
   238  
   239  		switch key.(type) {
   240  		case *ecdsa.PrivateKey:
   241  			k = &ecdsaPrivateKey{key.(*ecdsa.PrivateKey)}
   242  		case *rsa.PrivateKey:
   243  			k = &rsaPrivateKey{key.(*rsa.PrivateKey)}
   244  		default:
   245  			continue
   246  		}
   247  
   248  		if !bytes.Equal(k.SKI(), ski) {
   249  			continue
   250  		}
   251  
   252  		return k, nil
   253  	}
   254  	return nil, errors.New("Key type not recognized")
   255  }
   256  
   257  func (ks *fileBasedKeyStore) getSuffix(alias string) string {
   258  	files, _ := ioutil.ReadDir(ks.path)
   259  	for _, f := range files {
   260  		if strings.HasPrefix(f.Name(), alias) {
   261  			if strings.HasSuffix(f.Name(), "sk") {
   262  				return "sk"
   263  			}
   264  			if strings.HasSuffix(f.Name(), "pk") {
   265  				return "pk"
   266  			}
   267  			if strings.HasSuffix(f.Name(), "key") {
   268  				return "key"
   269  			}
   270  			break
   271  		}
   272  	}
   273  	return ""
   274  }
   275  
   276  func (ks *fileBasedKeyStore) storePrivateKey(alias string, privateKey interface{}) error {
   277  	rawKey, err := utils.PrivateKeyToPEM(privateKey, ks.pwd)
   278  	if err != nil {
   279  		logger.Errorf("Failed converting private key to PEM [%s]: [%s]", alias, err)
   280  		return err
   281  	}
   282  
   283  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "sk"), rawKey, 0700)
   284  	if err != nil {
   285  		logger.Errorf("Failed storing private key [%s]: [%s]", alias, err)
   286  		return err
   287  	}
   288  
   289  	return nil
   290  }
   291  
   292  func (ks *fileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) error {
   293  	rawKey, err := utils.PublicKeyToPEM(publicKey, ks.pwd)
   294  	if err != nil {
   295  		logger.Errorf("Failed converting public key to PEM [%s]: [%s]", alias, err)
   296  		return err
   297  	}
   298  
   299  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "pk"), rawKey, 0700)
   300  	if err != nil {
   301  		logger.Errorf("Failed storing private key [%s]: [%s]", alias, err)
   302  		return err
   303  	}
   304  
   305  	return nil
   306  }
   307  
   308  func (ks *fileBasedKeyStore) storeKey(alias string, key []byte) error {
   309  	pem, err := utils.AEStoEncryptedPEM(key, ks.pwd)
   310  	if err != nil {
   311  		logger.Errorf("Failed converting key to PEM [%s]: [%s]", alias, err)
   312  		return err
   313  	}
   314  
   315  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "key"), pem, 0700)
   316  	if err != nil {
   317  		logger.Errorf("Failed storing key [%s]: [%s]", alias, err)
   318  		return err
   319  	}
   320  
   321  	return nil
   322  }
   323  
   324  func (ks *fileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) {
   325  	path := ks.getPathForAlias(alias, "sk")
   326  	logger.Debugf("Loading private key [%s] at [%s]...", alias, path)
   327  
   328  	raw, err := ioutil.ReadFile(path)
   329  	if err != nil {
   330  		logger.Errorf("Failed loading private key [%s]: [%s].", alias, err.Error())
   331  
   332  		return nil, err
   333  	}
   334  
   335  	privateKey, err := utils.PEMtoPrivateKey(raw, ks.pwd)
   336  	if err != nil {
   337  		logger.Errorf("Failed parsing private key [%s]: [%s].", alias, err.Error())
   338  
   339  		return nil, err
   340  	}
   341  
   342  	return privateKey, nil
   343  }
   344  
   345  func (ks *fileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) {
   346  	path := ks.getPathForAlias(alias, "pk")
   347  	logger.Debugf("Loading public key [%s] at [%s]...", alias, path)
   348  
   349  	raw, err := ioutil.ReadFile(path)
   350  	if err != nil {
   351  		logger.Errorf("Failed loading public key [%s]: [%s].", alias, err.Error())
   352  
   353  		return nil, err
   354  	}
   355  
   356  	privateKey, err := utils.PEMtoPublicKey(raw, ks.pwd)
   357  	if err != nil {
   358  		logger.Errorf("Failed parsing private key [%s]: [%s].", alias, err.Error())
   359  
   360  		return nil, err
   361  	}
   362  
   363  	return privateKey, nil
   364  }
   365  
   366  func (ks *fileBasedKeyStore) loadKey(alias string) ([]byte, error) {
   367  	path := ks.getPathForAlias(alias, "key")
   368  	logger.Debugf("Loading key [%s] at [%s]...", alias, path)
   369  
   370  	pem, err := ioutil.ReadFile(path)
   371  	if err != nil {
   372  		logger.Errorf("Failed loading key [%s]: [%s].", alias, err.Error())
   373  
   374  		return nil, err
   375  	}
   376  
   377  	key, err := utils.PEMtoAES(pem, ks.pwd)
   378  	if err != nil {
   379  		logger.Errorf("Failed parsing key [%s]: [%s]", alias, err)
   380  
   381  		return nil, err
   382  	}
   383  
   384  	return key, nil
   385  }
   386  
   387  func (ks *fileBasedKeyStore) close() error {
   388  	ks.isOpen = false
   389  	logger.Debug("Closing keystore...done!")
   390  	return nil
   391  }
   392  
   393  func (ks *fileBasedKeyStore) createKeyStoreIfNotExists() error {
   394  	// Check keystore directory
   395  	ksPath := ks.path
   396  	missing, err := utils.DirMissingOrEmpty(ksPath)
   397  
   398  	if missing {
   399  		logger.Debugf("KeyStore path [%s] missing [%t]: [%s]", ksPath, missing, utils.ErrToString(err))
   400  
   401  		err := ks.createKeyStore()
   402  		if err != nil {
   403  			logger.Errorf("Failed creating KeyStore At [%s]: [%s]", ksPath, err.Error())
   404  			return nil
   405  		}
   406  	}
   407  
   408  	return nil
   409  }
   410  
   411  func (ks *fileBasedKeyStore) createKeyStore() error {
   412  	// Create keystore directory root if it doesn't exist yet
   413  	ksPath := ks.path
   414  	logger.Debugf("Creating KeyStore at [%s]...", ksPath)
   415  
   416  	os.MkdirAll(ksPath, 0755)
   417  
   418  	logger.Debugf("KeyStore created at [%s].", ksPath)
   419  	return nil
   420  }
   421  
   422  func (ks *fileBasedKeyStore) deleteKeyStore() error {
   423  	logger.Debugf("Removing KeyStore at [%s].", ks.path)
   424  
   425  	return os.RemoveAll(ks.path)
   426  }
   427  
   428  func (ks *fileBasedKeyStore) openKeyStore() error {
   429  	if ks.isOpen {
   430  		return nil
   431  	}
   432  
   433  	logger.Debugf("KeyStore opened at [%s]...done", ks.path)
   434  
   435  	return nil
   436  }
   437  
   438  func (ks *fileBasedKeyStore) getPathForAlias(alias, suffix string) string {
   439  	return filepath.Join(ks.path, alias+"_"+suffix)
   440  }