github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/bccsp/sw/fileks.go (about)

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