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 }