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 }