github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/accounts/keystore/keystore.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package keystore implements encrypted storage of secp256k1 private keys. 18 // 19 // Keys are stored as encrypted JSON files according to the Web3 Secret Storage specification. 20 package keystore 21 22 import ( 23 "bytes" 24 "crypto/ecdsa" 25 crand "crypto/rand" 26 "encoding/json" 27 "errors" 28 "fmt" 29 "math/big" 30 "os" 31 "path/filepath" 32 "reflect" 33 "runtime" 34 "sync" 35 "time" 36 37 "github.com/vntchain/go-vnt/accounts" 38 "github.com/vntchain/go-vnt/common" 39 "github.com/vntchain/go-vnt/core/types" 40 "github.com/vntchain/go-vnt/crypto" 41 "github.com/vntchain/go-vnt/event" 42 ) 43 44 var ( 45 ErrLocked = accounts.NewAuthNeededError("password or unlock") 46 ErrNoMatch = errors.New("no key for given address or file") 47 ErrDecrypt = errors.New("could not decrypt key with given passphrase") 48 ) 49 50 // KeyStoreType is the reflect type of a keystore backend. 51 var KeyStoreType = reflect.TypeOf(&KeyStore{}) 52 53 // KeyStoreScheme is the protocol scheme prefixing account and wallet URLs. 54 var KeyStoreScheme = "keystore" 55 56 // Maximum time between wallet refreshes (if filesystem notifications don't work). 57 const walletRefreshCycle = 3 * time.Second 58 59 // KeyStore manages a key storage directory on disk. 60 type KeyStore struct { 61 storage keyStore // Storage backend, might be cleartext or encrypted 62 cache *accountCache // In-memory account cache over the filesystem storage 63 changes chan struct{} // Channel receiving change notifications from the cache 64 unlocked map[common.Address]*unlocked // Currently unlocked account (decrypted private keys) 65 66 wallets []accounts.Wallet // Wallet wrappers around the individual key files 67 updateFeed event.Feed // Event feed to notify wallet additions/removals 68 updateScope event.SubscriptionScope // Subscription scope tracking current live listeners 69 updating bool // Whether the event notification loop is running 70 71 mu sync.RWMutex 72 } 73 74 type unlocked struct { 75 *Key 76 abort chan struct{} 77 } 78 79 // NewKeyStore creates a keystore for the given directory. 80 func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore { 81 keydir, _ = filepath.Abs(keydir) 82 ks := &KeyStore{storage: &keyStorePassphrase{keydir, scryptN, scryptP}} 83 ks.init(keydir) 84 return ks 85 } 86 87 func NewSecureEnclaveKeyStore(keyjson []byte) *KeyStore { 88 var ( 89 keystores PackKeyStore 90 ) 91 err := json.NewDecoder(bytes.NewBuffer(keyjson)).Decode(&keystores) 92 if err != nil { 93 return nil 94 } 95 vntks := make(map[common.Address]encryptedKeyJSONV3) 96 for _, v := range keystores.VNTKeystore { 97 vntks[common.HexToAddress(v.Address)] = v 98 } 99 ks := &KeyStore{storage: &keyStoreSecureEnclave{vntks}} 100 ks.initWithKeyJson(keystores.VNTKeystore) 101 return ks 102 } 103 104 // NewPlaintextKeyStore creates a keystore for the given directory. 105 // Deprecated: Use NewKeyStore. 106 func NewPlaintextKeyStore(keydir string) *KeyStore { 107 keydir, _ = filepath.Abs(keydir) 108 ks := &KeyStore{storage: &keyStorePlain{keydir}} 109 ks.init(keydir) 110 return ks 111 } 112 113 func (ks *KeyStore) init(keydir string) { 114 // Lock the mutex since the account cache might call back with events 115 ks.mu.Lock() 116 defer ks.mu.Unlock() 117 118 // Initialize the set of unlocked keys and the account cache 119 ks.unlocked = make(map[common.Address]*unlocked) 120 ks.cache, ks.changes = newAccountCache(keydir) 121 122 // TODO: In order for this finalizer to work, there must be no references 123 // to ks. addressCache doesn't keep a reference but unlocked keys do, 124 // so the finalizer will not trigger until all timed unlocks have expired. 125 runtime.SetFinalizer(ks, func(m *KeyStore) { 126 m.cache.close() 127 }) 128 // Create the initial list of wallets from the cache 129 accs := ks.cache.accounts() 130 ks.wallets = make([]accounts.Wallet, len(accs)) 131 for i := 0; i < len(accs); i++ { 132 ks.wallets[i] = &keystoreWallet{account: accs[i], keystore: ks} 133 } 134 } 135 136 func (ks *KeyStore) initWithKeyJson(keyjson []encryptedKeyJSONV3) { 137 ks.mu.Lock() 138 defer ks.mu.Unlock() 139 ks.cache = &accountCache{ 140 byAddr: make(map[common.Address][]accounts.Account), 141 } 142 readAccount := func(ks encryptedKeyJSONV3) *accounts.Account { 143 addr := common.HexToAddress(ks.Address) 144 return &accounts.Account{Address: addr} 145 } 146 for _, v := range keyjson { 147 ac := readAccount(v) 148 ks.cache.byAddr[ac.Address] = []accounts.Account{*ac} 149 ks.cache.all = append(ks.cache.all, *ac) 150 } 151 ks.unlocked = make(map[common.Address]*unlocked) 152 ks.cache.watcher = newWatcher(ks.cache) 153 } 154 155 // Wallets implements accounts.Backend, returning all single-key wallets from the 156 // keystore directory. 157 func (ks *KeyStore) Wallets() []accounts.Wallet { 158 // Make sure the list of wallets is in sync with the account cache 159 ks.refreshWallets() 160 161 ks.mu.RLock() 162 defer ks.mu.RUnlock() 163 164 cpy := make([]accounts.Wallet, len(ks.wallets)) 165 copy(cpy, ks.wallets) 166 return cpy 167 } 168 169 // refreshWallets retrieves the current account list and based on that does any 170 // necessary wallet refreshes. 171 func (ks *KeyStore) refreshWallets() { 172 // Retrieve the current list of accounts 173 ks.mu.Lock() 174 accs := ks.cache.accounts() 175 176 // Transform the current list of wallets into the new one 177 wallets := make([]accounts.Wallet, 0, len(accs)) 178 events := []accounts.WalletEvent{} 179 180 for _, account := range accs { 181 // Drop wallets while they were in front of the next account 182 for len(ks.wallets) > 0 && ks.wallets[0].URL().Cmp(account.URL) < 0 { 183 events = append(events, accounts.WalletEvent{Wallet: ks.wallets[0], Kind: accounts.WalletDropped}) 184 ks.wallets = ks.wallets[1:] 185 } 186 // If there are no more wallets or the account is before the next, wrap new wallet 187 if len(ks.wallets) == 0 || ks.wallets[0].URL().Cmp(account.URL) > 0 { 188 wallet := &keystoreWallet{account: account, keystore: ks} 189 190 events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived}) 191 wallets = append(wallets, wallet) 192 continue 193 } 194 // If the account is the same as the first wallet, keep it 195 if ks.wallets[0].Accounts()[0] == account { 196 wallets = append(wallets, ks.wallets[0]) 197 ks.wallets = ks.wallets[1:] 198 continue 199 } 200 } 201 // Drop any leftover wallets and set the new batch 202 for _, wallet := range ks.wallets { 203 events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped}) 204 } 205 ks.wallets = wallets 206 ks.mu.Unlock() 207 208 // Fire all wallet events and return 209 for _, event := range events { 210 ks.updateFeed.Send(event) 211 } 212 } 213 214 // Subscribe implements accounts.Backend, creating an async subscription to 215 // receive notifications on the addition or removal of keystore wallets. 216 func (ks *KeyStore) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { 217 // We need the mutex to reliably start/stop the update loop 218 ks.mu.Lock() 219 defer ks.mu.Unlock() 220 221 // Subscribe the caller and track the subscriber count 222 sub := ks.updateScope.Track(ks.updateFeed.Subscribe(sink)) 223 224 // Subscribers require an active notification loop, start it 225 if !ks.updating { 226 ks.updating = true 227 go ks.updater() 228 } 229 return sub 230 } 231 232 // updater is responsible for maintaining an up-to-date list of wallets stored in 233 // the keystore, and for firing wallet addition/removal events. It listens for 234 // account change events from the underlying account cache, and also periodically 235 // forces a manual refresh (only triggers for systems where the filesystem notifier 236 // is not running). 237 func (ks *KeyStore) updater() { 238 for { 239 // Wait for an account update or a refresh timeout 240 select { 241 case <-ks.changes: 242 case <-time.After(walletRefreshCycle): 243 } 244 // Run the wallet refresher 245 ks.refreshWallets() 246 247 // If all our subscribers left, stop the updater 248 ks.mu.Lock() 249 if ks.updateScope.Count() == 0 { 250 ks.updating = false 251 ks.mu.Unlock() 252 return 253 } 254 ks.mu.Unlock() 255 } 256 } 257 258 // HasAddress reports whether a key with the given address is present. 259 func (ks *KeyStore) HasAddress(addr common.Address) bool { 260 return ks.cache.hasAddress(addr) 261 } 262 263 // Accounts returns all key files present in the directory. 264 func (ks *KeyStore) Accounts() []accounts.Account { 265 return ks.cache.accounts() 266 } 267 268 // Delete deletes the key matched by account if the passphrase is correct. 269 // If the account contains no filename, the address must match a unique key. 270 func (ks *KeyStore) Delete(a accounts.Account, passphrase string) error { 271 // Decrypting the key isn't really necessary, but we do 272 // it anyway to check the password and zero out the key 273 // immediately afterwards. 274 a, key, err := ks.getDecryptedKey(a, passphrase) 275 if key != nil { 276 zeroKey(key.PrivateKey) 277 } 278 if err != nil { 279 return err 280 } 281 // The order is crucial here. The key is dropped from the 282 // cache after the file is gone so that a reload happening in 283 // between won't insert it into the cache again. 284 err = os.Remove(a.URL.Path) 285 if err == nil { 286 ks.cache.delete(a) 287 ks.refreshWallets() 288 } 289 return err 290 } 291 292 // SignHash calculates a ECDSA signature for the given hash. The produced 293 // signature is in the [R || S || V] format where V is 0 or 1. 294 func (ks *KeyStore) SignHash(a accounts.Account, hash []byte) ([]byte, error) { 295 // Look up the key to sign with and abort if it cannot be found 296 ks.mu.RLock() 297 defer ks.mu.RUnlock() 298 299 unlockedKey, found := ks.unlocked[a.Address] 300 if !found { 301 return nil, ErrLocked 302 } 303 // Sign the hash using plain ECDSA operations 304 return crypto.Sign(hash, unlockedKey.PrivateKey) 305 } 306 307 // SignTx signs the given transaction with the requested account. 308 func (ks *KeyStore) SignTx(a accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { 309 // Look up the key to sign with and abort if it cannot be found 310 ks.mu.RLock() 311 defer ks.mu.RUnlock() 312 313 unlockedKey, found := ks.unlocked[a.Address] 314 if !found { 315 return nil, ErrLocked 316 } 317 return types.SignTx(tx, types.NewHubbleSigner(chainID), unlockedKey.PrivateKey) 318 } 319 320 // SignHashWithPassphrase signs hash if the private key matching the given address 321 // can be decrypted with the given passphrase. The produced signature is in the 322 // [R || S || V] format where V is 0 or 1. 323 func (ks *KeyStore) SignHashWithPassphrase(a accounts.Account, passphrase string, hash []byte) (signature []byte, err error) { 324 _, key, err := ks.getDecryptedKey(a, passphrase) 325 if err != nil { 326 return nil, err 327 } 328 defer zeroKey(key.PrivateKey) 329 return crypto.Sign(hash, key.PrivateKey) 330 } 331 332 // SignTxWithPassphrase signs the transaction if the private key matching the 333 // given address can be decrypted with the given passphrase. 334 func (ks *KeyStore) SignTxWithPassphrase(a accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { 335 _, key, err := ks.getDecryptedKey(a, passphrase) 336 if err != nil { 337 return nil, err 338 } 339 defer zeroKey(key.PrivateKey) 340 341 return types.SignTx(tx, types.NewHubbleSigner(chainID), key.PrivateKey) 342 } 343 344 // Unlock unlocks the given account indefinitely. 345 func (ks *KeyStore) Unlock(a accounts.Account, passphrase string) error { 346 return ks.TimedUnlock(a, passphrase, 0) 347 } 348 349 // Lock removes the private key with the given address from memory. 350 func (ks *KeyStore) Lock(addr common.Address) error { 351 ks.mu.Lock() 352 if unl, found := ks.unlocked[addr]; found { 353 ks.mu.Unlock() 354 ks.expire(addr, unl, time.Duration(0)*time.Nanosecond) 355 } else { 356 ks.mu.Unlock() 357 } 358 return nil 359 } 360 361 // TimedUnlock unlocks the given account with the passphrase. The account 362 // stays unlocked for the duration of timeout. A timeout of 0 unlocks the account 363 // until the program exits. The account must match a unique key file. 364 // 365 // If the account address is already unlocked for a duration, TimedUnlock extends or 366 // shortens the active unlock timeout. If the address was previously unlocked 367 // indefinitely the timeout is not altered. 368 func (ks *KeyStore) TimedUnlock(a accounts.Account, passphrase string, timeout time.Duration) error { 369 a, key, err := ks.getDecryptedKey(a, passphrase) 370 if err != nil { 371 return err 372 } 373 374 ks.mu.Lock() 375 defer ks.mu.Unlock() 376 u, found := ks.unlocked[a.Address] 377 if found { 378 if u.abort == nil { 379 // The address was unlocked indefinitely, so unlocking 380 // it with a timeout would be confusing. 381 zeroKey(key.PrivateKey) 382 return nil 383 } 384 // Terminate the expire goroutine and replace it below. 385 close(u.abort) 386 } 387 if timeout > 0 { 388 u = &unlocked{Key: key, abort: make(chan struct{})} 389 go ks.expire(a.Address, u, timeout) 390 } else { 391 u = &unlocked{Key: key} 392 } 393 ks.unlocked[a.Address] = u 394 return nil 395 } 396 397 // Find resolves the given account into a unique entry in the keystore. 398 func (ks *KeyStore) Find(a accounts.Account) (accounts.Account, error) { 399 ks.cache.maybeReload() 400 ks.cache.mu.Lock() 401 a, err := ks.cache.find(a) 402 ks.cache.mu.Unlock() 403 return a, err 404 } 405 406 func (ks *KeyStore) getDecryptedKey(a accounts.Account, auth string) (accounts.Account, *Key, error) { 407 a, err := ks.Find(a) 408 if err != nil { 409 return a, nil, err 410 } 411 key, err := ks.storage.GetKey(a.Address, a.URL.Path, auth) 412 return a, key, err 413 } 414 415 func (ks *KeyStore) expire(addr common.Address, u *unlocked, timeout time.Duration) { 416 t := time.NewTimer(timeout) 417 defer t.Stop() 418 select { 419 case <-u.abort: 420 // just quit 421 case <-t.C: 422 ks.mu.Lock() 423 // only drop if it's still the same key instance that dropLater 424 // was launched with. we can check that using pointer equality 425 // because the map stores a new pointer every time the key is 426 // unlocked. 427 if ks.unlocked[addr] == u { 428 zeroKey(u.PrivateKey) 429 delete(ks.unlocked, addr) 430 } 431 ks.mu.Unlock() 432 } 433 } 434 435 // NewAccount generates a new key and stores it into the key directory, 436 // encrypting it with the passphrase. 437 func (ks *KeyStore) NewAccount(passphrase string) (accounts.Account, error) { 438 _, account, err := storeNewKey(ks.storage, crand.Reader, passphrase) 439 if err != nil { 440 return accounts.Account{}, err 441 } 442 // Add the account to the cache immediately rather 443 // than waiting for file system notifications to pick it up. 444 ks.cache.add(account) 445 ks.refreshWallets() 446 return account, nil 447 } 448 449 // Export exports as a JSON key, encrypted with newPassphrase. 450 func (ks *KeyStore) Export(a accounts.Account, passphrase, newPassphrase string) (keyJSON []byte, err error) { 451 _, key, err := ks.getDecryptedKey(a, passphrase) 452 if err != nil { 453 return nil, err 454 } 455 var N, P int 456 if store, ok := ks.storage.(*keyStorePassphrase); ok { 457 N, P = store.scryptN, store.scryptP 458 } else if _, ok := ks.storage.(*keyStoreSecureEnclave); ok { 459 N, P = LightScryptN, LightScryptP 460 } else { 461 N, P = StandardScryptN, StandardScryptP 462 } 463 return EncryptKey(key, newPassphrase, N, P) 464 } 465 466 // Import stores the given encrypted JSON key into the key directory. 467 func (ks *KeyStore) Import(keyJSON []byte, passphrase, newPassphrase string) (accounts.Account, error) { 468 key, err := DecryptKey(keyJSON, passphrase) 469 if key != nil && key.PrivateKey != nil { 470 defer zeroKey(key.PrivateKey) 471 } 472 if err != nil { 473 return accounts.Account{}, err 474 } 475 return ks.importKey(key, newPassphrase) 476 } 477 478 // ImportECDSA stores the given key into the key directory, encrypting it with the passphrase. 479 func (ks *KeyStore) ImportECDSA(priv *ecdsa.PrivateKey, passphrase string) (accounts.Account, error) { 480 key := newKeyFromECDSA(priv) 481 if ks.cache.hasAddress(key.Address) { 482 return accounts.Account{}, fmt.Errorf("account already exists") 483 } 484 return ks.importKey(key, passphrase) 485 } 486 487 func (ks *KeyStore) importKey(key *Key, passphrase string) (accounts.Account, error) { 488 a := accounts.Account{Address: key.Address, URL: accounts.URL{Scheme: KeyStoreScheme, Path: ks.storage.JoinPath(keyFileName(key.Address))}} 489 if err := ks.storage.StoreKey(a.URL.Path, key, passphrase); err != nil { 490 return accounts.Account{}, err 491 } 492 ks.cache.add(a) 493 ks.refreshWallets() 494 return a, nil 495 } 496 497 // Update changes the passphrase of an existing account. 498 func (ks *KeyStore) Update(a accounts.Account, passphrase, newPassphrase string) error { 499 a, key, err := ks.getDecryptedKey(a, passphrase) 500 if err != nil { 501 return err 502 } 503 return ks.storage.StoreKey(a.URL.Path, key, newPassphrase) 504 } 505 506 // ImportPreSaleKey decrypts the given VNT presale wallet and stores 507 // a key file in the key directory. The key file is encrypted with the same passphrase. 508 func (ks *KeyStore) ImportPreSaleKey(keyJSON []byte, passphrase string) (accounts.Account, error) { 509 a, _, err := importPreSaleKey(ks.storage, keyJSON, passphrase) 510 if err != nil { 511 return a, err 512 } 513 ks.cache.add(a) 514 ks.refreshWallets() 515 return a, nil 516 } 517 518 // zeroKey zeroes a private key in memory. 519 func zeroKey(k *ecdsa.PrivateKey) { 520 b := k.D.Bits() 521 for i := range b { 522 b[i] = 0 523 } 524 }