// PrivKey returns the private key for the address. It can fail if the address // manager is watching-only or locked, or the address does not have any keys. // // This is part of the ManagedPubKeyAddress interface implementation. func (a *managedAddress) PrivKey() (*btcec.PrivateKey, error) { // No private keys are available for a watching-only address manager. if a.manager.watchingOnly { return nil, managerError(ErrWatchingOnly, errWatchingOnly, nil) } a.manager.mtx.Lock() defer a.manager.mtx.Unlock() // Account manager must be unlocked to decrypt the private key. if a.manager.locked { return nil, managerError(ErrLocked, errLocked, nil) } // Decrypt the key as needed. Also, make sure it's a copy since the // private key stored in memory can be cleared at any time. Otherwise // the returned private key could be invalidated from under the caller. privKeyCopy, err := a.unlock(a.manager.cryptoKeyPriv) if err != nil { return nil, err } privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyCopy) zero.Bytes(privKeyCopy) return privKey, nil }
// lock zeroes the associated clear text private key. func (a *scriptAddress) lock() { // Zero and nil the clear text script associated with this address. a.scriptMutex.Lock() zero.Bytes(a.scriptCT) a.scriptCT = nil a.scriptMutex.Unlock() }
// lock zeroes the associated clear text private key. func (a *managedAddress) lock() { // Zero and nil the clear text private key associated with this // address. a.privKeyMutex.Lock() zero.Bytes(a.privKeyCT) a.privKeyCT = nil a.privKeyMutex.Unlock() }
// decryptExtendedKey uses Manager.Decrypt() to decrypt the encrypted byte slice and return // an extended (public or private) key representing it. // // This method must be called with the Pool's manager unlocked. func (p *Pool) decryptExtendedKey(keyType waddrmgr.CryptoKeyType, encrypted []byte) (*hdkeychain.ExtendedKey, error) { decrypted, err := p.manager.Decrypt(keyType, encrypted) if err != nil { str := fmt.Sprintf("cannot decrypt key %v", encrypted) return nil, newError(ErrCrypto, str, err) } result, err := hdkeychain.NewKeyFromString(string(decrypted)) zero.Bytes(decrypted) if err != nil { str := fmt.Sprintf("cannot get key from string %v", decrypted) return nil, newError(ErrKeyChain, str, err) } return result, nil }
// deriveKey fills out the Key field. func (sk *SecretKey) deriveKey(password *[]byte) error { key, err := scrypt.Key(*password, sk.Parameters.Salt[:], sk.Parameters.N, sk.Parameters.R, sk.Parameters.P, len(sk.Key)) if err != nil { return err } copy(sk.Key[:], key) zero.Bytes(key) // I'm not a fan of forced garbage collections, but scrypt allocates a // ton of memory and calling it back to back without a GC cycle in // between means you end up needing twice the amount of memory. For // example, if your scrypt parameters are such that you require 1GB and // you call it twice in a row, without this you end up allocating 2GB // since the first GB probably hasn't been released yet. debug.FreeOSMemory() return nil }