keys/wallet: add Destroy/Close/Close
PrivateKey can be destroyed and Account/Wallet can be closed (destroying keys in the process).
This commit is contained in:
parent
a30e73a0d7
commit
62be6f959c
6 changed files with 39 additions and 5 deletions
|
@ -117,6 +117,15 @@ func (p *PrivateKey) WIF() string {
|
|||
return w
|
||||
}
|
||||
|
||||
// Destroy wipes the contents of the private key from memory. Any operations
|
||||
// with the key after call to Destroy have undefined behavior.
|
||||
func (p *PrivateKey) Destroy() {
|
||||
bits := p.D.Bits()
|
||||
for i := range bits {
|
||||
bits[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Address derives the public NEO address that is coupled with the private key, and
|
||||
// returns it as a string.
|
||||
func (p *PrivateKey) Address() string {
|
||||
|
|
|
@ -2,6 +2,7 @@ package keys
|
|||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -27,6 +28,9 @@ func TestPrivateKey(t *testing.T) {
|
|||
assert.Equal(t, testCase.Wif, wif)
|
||||
pubKey := privKey.PublicKey()
|
||||
assert.Equal(t, hex.EncodeToString(pubKey.Bytes()), testCase.PublicKey)
|
||||
oldD := new(big.Int).Set(privKey.D)
|
||||
privKey.Destroy()
|
||||
assert.NotEqual(t, oldD, privKey.D)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -175,6 +175,17 @@ func (a *Account) PrivateKey() *keys.PrivateKey {
|
|||
return a.privateKey
|
||||
}
|
||||
|
||||
// Close cleans up the private key used by Account and disassociates it from
|
||||
// Account. The Account can no longer sign anything after this call, but Decrypt
|
||||
// can make it usable again.
|
||||
func (a *Account) Close() {
|
||||
if a.privateKey == nil {
|
||||
return
|
||||
}
|
||||
a.privateKey.Destroy()
|
||||
a.privateKey = nil
|
||||
}
|
||||
|
||||
// NewAccountFromWIF creates a new Account from the given WIF.
|
||||
func NewAccountFromWIF(wif string) (*Account, error) {
|
||||
privKey, err := keys.NewPrivateKeyFromWIF(wif)
|
||||
|
|
|
@ -141,9 +141,11 @@ func TestContractSignTx(t *testing.T) {
|
|||
require.Error(t, acc2.SignTx(0, tx)) // Locked account.
|
||||
|
||||
acc2.Locked = false
|
||||
acc2.privateKey = nil
|
||||
acc2.Close()
|
||||
require.False(t, acc2.CanSign())
|
||||
require.Error(t, acc2.SignTx(0, tx)) // No private key.
|
||||
acc2.Close() // No-op.
|
||||
require.False(t, acc2.CanSign())
|
||||
|
||||
tx.Scripts = append(tx.Scripts, transaction.Witness{
|
||||
VerificationScript: acc.Contract.Script,
|
||||
|
|
|
@ -168,9 +168,14 @@ func (w *Wallet) JSON() ([]byte, error) {
|
|||
return json.MarshalIndent(w, " ", " ")
|
||||
}
|
||||
|
||||
// Deprecated: Close is deprecated.
|
||||
// Close performs nothing and is left for backwards compatibility.
|
||||
func (w *Wallet) Close() {}
|
||||
// Close closes all Wallet accounts making them incapable of signing anything
|
||||
// (unless they're decrypted again). It's not doing anything to the underlying
|
||||
// wallet file.
|
||||
func (w *Wallet) Close() {
|
||||
for _, acc := range w.Accounts {
|
||||
acc.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// GetAccount returns an account corresponding to the provided scripthash.
|
||||
func (w *Wallet) GetAccount(h util.Uint160) *Account {
|
||||
|
|
|
@ -34,13 +34,16 @@ func TestNewWalletFromFile_Negative_NoFile(t *testing.T) {
|
|||
require.Errorf(t, err, "open testWallet: no such file or directory")
|
||||
}
|
||||
|
||||
func TestCreateAccount(t *testing.T) {
|
||||
func TestCreateAccountAndClose(t *testing.T) {
|
||||
wallet := checkWalletConstructor(t)
|
||||
|
||||
errAcc := wallet.CreateAccount("testName", "testPass")
|
||||
require.NoError(t, errAcc)
|
||||
accounts := wallet.Accounts
|
||||
require.Len(t, accounts, 1)
|
||||
require.True(t, wallet.Accounts[0].CanSign())
|
||||
wallet.Close()
|
||||
require.False(t, wallet.Accounts[0].CanSign())
|
||||
}
|
||||
|
||||
func TestAddAccount(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue