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