github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/bccsp/pkcs11/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 pkcs11
    17  
    18  import (
    19  	"bytes"
    20  	"crypto/rsa"
    21  	"encoding/hex"
    22  	"errors"
    23  	"fmt"
    24  	"io/ioutil"
    25  	"os"
    26  	"path/filepath"
    27  	"strings"
    28  	"sync"
    29  
    30  	"github.com/hyperledger/fabric/bccsp"
    31  	"github.com/hyperledger/fabric/bccsp/utils"
    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) (k bccsp.Key, err 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 key.(type) {
   128  		case *rsa.PrivateKey:
   129  			return &rsaPrivateKey{key.(*rsa.PrivateKey)}, 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 key.(type) {
   141  		case *rsa.PublicKey:
   142  			return &rsaPublicKey{key.(*rsa.PublicKey)}, 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 k.(type) {
   162  	case *rsaPrivateKey:
   163  		kk := k.(*rsaPrivateKey)
   164  
   165  		err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey)
   166  		if err != nil {
   167  			return fmt.Errorf("Failed storing RSA private key [%s]", err)
   168  		}
   169  
   170  	case *rsaPublicKey:
   171  		kk := k.(*rsaPublicKey)
   172  
   173  		err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey)
   174  		if err != nil {
   175  			return fmt.Errorf("Failed storing RSA public key [%s]", err)
   176  		}
   177  
   178  	case *aesPrivateKey:
   179  		kk := k.(*aesPrivateKey)
   180  
   181  		err = ks.storeKey(hex.EncodeToString(k.SKI()), kk.privKey)
   182  		if err != nil {
   183  			return fmt.Errorf("Failed storing AES key [%s]", err)
   184  		}
   185  
   186  	default:
   187  		return fmt.Errorf("Key type not reconigned [%s]", k)
   188  	}
   189  
   190  	return
   191  }
   192  
   193  func (ks *FileBasedKeyStore) searchKeystoreForSKI(ski []byte) (k bccsp.Key, err error) {
   194  
   195  	files, _ := ioutil.ReadDir(ks.path)
   196  	for _, f := range files {
   197  		if f.IsDir() {
   198  			continue
   199  		}
   200  		raw, err := ioutil.ReadFile(filepath.Join(ks.path, f.Name()))
   201  
   202  		key, err := utils.PEMtoPrivateKey(raw, ks.pwd)
   203  		if err != nil {
   204  			continue
   205  		}
   206  
   207  		switch key.(type) {
   208  		case *rsa.PrivateKey:
   209  			k = &rsaPrivateKey{key.(*rsa.PrivateKey)}
   210  		default:
   211  			continue
   212  		}
   213  
   214  		if !bytes.Equal(k.SKI(), ski) {
   215  			continue
   216  		}
   217  
   218  		return k, nil
   219  	}
   220  	return nil, errors.New("Key type not recognized")
   221  }
   222  
   223  func (ks *FileBasedKeyStore) getSuffix(alias string) string {
   224  	files, _ := ioutil.ReadDir(ks.path)
   225  	for _, f := range files {
   226  		if strings.HasPrefix(f.Name(), alias) {
   227  			if strings.HasSuffix(f.Name(), "sk") {
   228  				return "sk"
   229  			}
   230  			if strings.HasSuffix(f.Name(), "pk") {
   231  				return "pk"
   232  			}
   233  			if strings.HasSuffix(f.Name(), "key") {
   234  				return "key"
   235  			}
   236  			break
   237  		}
   238  	}
   239  	return ""
   240  }
   241  
   242  func (ks *FileBasedKeyStore) storePrivateKey(alias string, privateKey interface{}) error {
   243  	rawKey, err := utils.PrivateKeyToPEM(privateKey, ks.pwd)
   244  	if err != nil {
   245  		logger.Errorf("Failed converting private key to PEM [%s]: [%s]", alias, err)
   246  		return err
   247  	}
   248  
   249  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "sk"), rawKey, 0700)
   250  	if err != nil {
   251  		logger.Errorf("Failed storing private key [%s]: [%s]", alias, err)
   252  		return err
   253  	}
   254  
   255  	return nil
   256  }
   257  
   258  func (ks *FileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) error {
   259  	rawKey, err := utils.PublicKeyToPEM(publicKey, ks.pwd)
   260  	if err != nil {
   261  		logger.Errorf("Failed converting public key to PEM [%s]: [%s]", alias, err)
   262  		return err
   263  	}
   264  
   265  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "pk"), rawKey, 0700)
   266  	if err != nil {
   267  		logger.Errorf("Failed storing private key [%s]: [%s]", alias, err)
   268  		return err
   269  	}
   270  
   271  	return nil
   272  }
   273  
   274  func (ks *FileBasedKeyStore) storeKey(alias string, key []byte) error {
   275  	pem, err := utils.AEStoEncryptedPEM(key, ks.pwd)
   276  	if err != nil {
   277  		logger.Errorf("Failed converting key to PEM [%s]: [%s]", alias, err)
   278  		return err
   279  	}
   280  
   281  	err = ioutil.WriteFile(ks.getPathForAlias(alias, "key"), pem, 0700)
   282  	if err != nil {
   283  		logger.Errorf("Failed storing key [%s]: [%s]", alias, err)
   284  		return err
   285  	}
   286  
   287  	return nil
   288  }
   289  
   290  func (ks *FileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) {
   291  	path := ks.getPathForAlias(alias, "sk")
   292  	logger.Debugf("Loading private key [%s] at [%s]...", alias, path)
   293  
   294  	raw, err := ioutil.ReadFile(path)
   295  	if err != nil {
   296  		logger.Errorf("Failed loading private key [%s]: [%s].", alias, err.Error())
   297  
   298  		return nil, err
   299  	}
   300  
   301  	privateKey, err := utils.PEMtoPrivateKey(raw, ks.pwd)
   302  	if err != nil {
   303  		logger.Errorf("Failed parsing private key [%s]: [%s].", alias, err.Error())
   304  
   305  		return nil, err
   306  	}
   307  
   308  	return privateKey, nil
   309  }
   310  
   311  func (ks *FileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) {
   312  	path := ks.getPathForAlias(alias, "pk")
   313  	logger.Debugf("Loading public key [%s] at [%s]...", alias, path)
   314  
   315  	raw, err := ioutil.ReadFile(path)
   316  	if err != nil {
   317  		logger.Errorf("Failed loading public key [%s]: [%s].", alias, err.Error())
   318  
   319  		return nil, err
   320  	}
   321  
   322  	privateKey, err := utils.PEMtoPublicKey(raw, ks.pwd)
   323  	if err != nil {
   324  		logger.Errorf("Failed parsing private key [%s]: [%s].", alias, err.Error())
   325  
   326  		return nil, err
   327  	}
   328  
   329  	return privateKey, nil
   330  }
   331  
   332  func (ks *FileBasedKeyStore) loadKey(alias string) ([]byte, error) {
   333  	path := ks.getPathForAlias(alias, "key")
   334  	logger.Debugf("Loading key [%s] at [%s]...", alias, path)
   335  
   336  	pem, err := ioutil.ReadFile(path)
   337  	if err != nil {
   338  		logger.Errorf("Failed loading key [%s]: [%s].", alias, err.Error())
   339  
   340  		return nil, err
   341  	}
   342  
   343  	key, err := utils.PEMtoAES(pem, ks.pwd)
   344  	if err != nil {
   345  		logger.Errorf("Failed parsing key [%s]: [%s]", alias, err)
   346  
   347  		return nil, err
   348  	}
   349  
   350  	return key, nil
   351  }
   352  
   353  func (ks *FileBasedKeyStore) close() error {
   354  	ks.isOpen = false
   355  	logger.Debug("Closing keystore...done!")
   356  	return nil
   357  }
   358  
   359  func (ks *FileBasedKeyStore) createKeyStoreIfNotExists() error {
   360  	// Check keystore directory
   361  	ksPath := ks.path
   362  	missing, err := utils.DirMissingOrEmpty(ksPath)
   363  
   364  	if missing {
   365  		logger.Debugf("KeyStore path [%s] missing [%t]: [%s]", ksPath, missing, utils.ErrToString(err))
   366  
   367  		err := ks.createKeyStore()
   368  		if err != nil {
   369  			logger.Errorf("Failed creating KeyStore At [%s]: [%s]", ksPath, err.Error())
   370  			return nil
   371  		}
   372  	}
   373  
   374  	return nil
   375  }
   376  
   377  func (ks *FileBasedKeyStore) createKeyStore() error {
   378  	// Create keystore directory root if it doesn't exist yet
   379  	ksPath := ks.path
   380  	logger.Debugf("Creating KeyStore at [%s]...", ksPath)
   381  
   382  	os.MkdirAll(ksPath, 0755)
   383  
   384  	logger.Debugf("KeyStore created at [%s].", ksPath)
   385  	return nil
   386  }
   387  
   388  func (ks *FileBasedKeyStore) deleteKeyStore() error {
   389  	logger.Debugf("Removing KeyStore at [%s].", ks.path)
   390  
   391  	return os.RemoveAll(ks.path)
   392  }
   393  
   394  func (ks *FileBasedKeyStore) openKeyStore() error {
   395  	if ks.isOpen {
   396  		return nil
   397  	}
   398  
   399  	logger.Debugf("KeyStore opened at [%s]...done", ks.path)
   400  
   401  	return nil
   402  }
   403  
   404  func (ks *FileBasedKeyStore) getPathForAlias(alias, suffix string) string {
   405  	return filepath.Join(ks.path, alias+"_"+suffix)
   406  }