github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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  		if err != nil {
   234  			continue
   235  		}
   236  
   237  		key, err := utils.PEMtoPrivateKey(raw, ks.pwd)
   238  		if err != nil {
   239  			continue
   240  		}
   241  
   242  		switch key.(type) {
   243  		case *ecdsa.PrivateKey:
   244  			k = &ecdsaPrivateKey{key.(*ecdsa.PrivateKey)}
   245  		case *rsa.PrivateKey:
   246  			k = &rsaPrivateKey{key.(*rsa.PrivateKey)}
   247  		default:
   248  			continue
   249  		}
   250  
   251  		if !bytes.Equal(k.SKI(), ski) {
   252  			continue
   253  		}
   254  
   255  		return k, nil
   256  	}
   257  	return nil, errors.New("Key type not recognized")
   258  }
   259  
   260  func (ks *fileBasedKeyStore) getSuffix(alias string) string {
   261  	files, _ := ioutil.ReadDir(ks.path)
   262  	for _, f := range files {
   263  		if strings.HasPrefix(f.Name(), alias) {
   264  			if strings.HasSuffix(f.Name(), "sk") {
   265  				return "sk"
   266  			}
   267  			if strings.HasSuffix(f.Name(), "pk") {
   268  				return "pk"
   269  			}
   270  			if strings.HasSuffix(f.Name(), "key") {
   271  				return "key"
   272  			}
   273  			break
   274  		}
   275  	}
   276  	return ""
   277  }
   278  
   279  func (ks *fileBasedKeyStore) storePrivateKey(alias string, privateKey interface{}) error {
   280  	rawKey, err := utils.PrivateKeyToPEM(privateKey, ks.pwd)
   281  	if err != nil {
   282  		logger.Errorf("Failed converting private key to PEM [%s]: [%s]", alias, err)
   283  		return err
   284  	}
   285  
   286  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "sk"), rawKey, 0700)
   287  	if err != nil {
   288  		logger.Errorf("Failed storing private key [%s]: [%s]", alias, err)
   289  		return err
   290  	}
   291  
   292  	return nil
   293  }
   294  
   295  func (ks *fileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) error {
   296  	rawKey, err := utils.PublicKeyToPEM(publicKey, ks.pwd)
   297  	if err != nil {
   298  		logger.Errorf("Failed converting public key to PEM [%s]: [%s]", alias, err)
   299  		return err
   300  	}
   301  
   302  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "pk"), rawKey, 0700)
   303  	if err != nil {
   304  		logger.Errorf("Failed storing private key [%s]: [%s]", alias, err)
   305  		return err
   306  	}
   307  
   308  	return nil
   309  }
   310  
   311  func (ks *fileBasedKeyStore) storeKey(alias string, key []byte) error {
   312  	pem, err := utils.AEStoEncryptedPEM(key, ks.pwd)
   313  	if err != nil {
   314  		logger.Errorf("Failed converting key to PEM [%s]: [%s]", alias, err)
   315  		return err
   316  	}
   317  
   318  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "key"), pem, 0700)
   319  	if err != nil {
   320  		logger.Errorf("Failed storing key [%s]: [%s]", alias, err)
   321  		return err
   322  	}
   323  
   324  	return nil
   325  }
   326  
   327  func (ks *fileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) {
   328  	path := ks.getPathForAlias(alias, "sk")
   329  	logger.Debugf("Loading private key [%s] at [%s]...", alias, path)
   330  
   331  	raw, err := ioutil.ReadFile(path)
   332  	if err != nil {
   333  		logger.Errorf("Failed loading private key [%s]: [%s].", alias, err.Error())
   334  
   335  		return nil, err
   336  	}
   337  
   338  	privateKey, err := utils.PEMtoPrivateKey(raw, ks.pwd)
   339  	if err != nil {
   340  		logger.Errorf("Failed parsing private key [%s]: [%s].", alias, err.Error())
   341  
   342  		return nil, err
   343  	}
   344  
   345  	return privateKey, nil
   346  }
   347  
   348  func (ks *fileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) {
   349  	path := ks.getPathForAlias(alias, "pk")
   350  	logger.Debugf("Loading public key [%s] at [%s]...", alias, path)
   351  
   352  	raw, err := ioutil.ReadFile(path)
   353  	if err != nil {
   354  		logger.Errorf("Failed loading public key [%s]: [%s].", alias, err.Error())
   355  
   356  		return nil, err
   357  	}
   358  
   359  	privateKey, err := utils.PEMtoPublicKey(raw, ks.pwd)
   360  	if err != nil {
   361  		logger.Errorf("Failed parsing private key [%s]: [%s].", alias, err.Error())
   362  
   363  		return nil, err
   364  	}
   365  
   366  	return privateKey, nil
   367  }
   368  
   369  func (ks *fileBasedKeyStore) loadKey(alias string) ([]byte, error) {
   370  	path := ks.getPathForAlias(alias, "key")
   371  	logger.Debugf("Loading key [%s] at [%s]...", alias, path)
   372  
   373  	pem, err := ioutil.ReadFile(path)
   374  	if err != nil {
   375  		logger.Errorf("Failed loading key [%s]: [%s].", alias, err.Error())
   376  
   377  		return nil, err
   378  	}
   379  
   380  	key, err := utils.PEMtoAES(pem, ks.pwd)
   381  	if err != nil {
   382  		logger.Errorf("Failed parsing key [%s]: [%s]", alias, err)
   383  
   384  		return nil, err
   385  	}
   386  
   387  	return key, nil
   388  }
   389  
   390  func (ks *fileBasedKeyStore) close() error {
   391  	ks.isOpen = false
   392  	logger.Debug("Closing keystore...done!")
   393  	return nil
   394  }
   395  
   396  func (ks *fileBasedKeyStore) createKeyStoreIfNotExists() error {
   397  	// Check keystore directory
   398  	ksPath := ks.path
   399  	missing, err := utils.DirMissingOrEmpty(ksPath)
   400  
   401  	if missing {
   402  		logger.Debugf("KeyStore path [%s] missing [%t]: [%s]", ksPath, missing, utils.ErrToString(err))
   403  
   404  		err := ks.createKeyStore()
   405  		if err != nil {
   406  			logger.Errorf("Failed creating KeyStore At [%s]: [%s]", ksPath, err.Error())
   407  			return nil
   408  		}
   409  	}
   410  
   411  	return nil
   412  }
   413  
   414  func (ks *fileBasedKeyStore) createKeyStore() error {
   415  	// Create keystore directory root if it doesn't exist yet
   416  	ksPath := ks.path
   417  	logger.Debugf("Creating KeyStore at [%s]...", ksPath)
   418  
   419  	os.MkdirAll(ksPath, 0755)
   420  
   421  	logger.Debugf("KeyStore created at [%s].", ksPath)
   422  	return nil
   423  }
   424  
   425  func (ks *fileBasedKeyStore) deleteKeyStore() error {
   426  	logger.Debugf("Removing KeyStore at [%s].", ks.path)
   427  
   428  	return os.RemoveAll(ks.path)
   429  }
   430  
   431  func (ks *fileBasedKeyStore) openKeyStore() error {
   432  	if ks.isOpen {
   433  		return nil
   434  	}
   435  
   436  	logger.Debugf("KeyStore opened at [%s]...done", ks.path)
   437  
   438  	return nil
   439  }
   440  
   441  func (ks *fileBasedKeyStore) getPathForAlias(alias, suffix string) string {
   442  	return filepath.Join(ks.path, alias+"_"+suffix)
   443  }