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