github.com/lzy4123/fabric@v2.1.1+incompatible/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 }