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
|
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
|
// Address derives the public NEO address that is coupled with the private key, and
|
||||||
// returns it as a string.
|
// returns it as a string.
|
||||||
func (p *PrivateKey) Address() string {
|
func (p *PrivateKey) Address() string {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package keys
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -27,6 +28,9 @@ func TestPrivateKey(t *testing.T) {
|
||||||
assert.Equal(t, testCase.Wif, wif)
|
assert.Equal(t, testCase.Wif, wif)
|
||||||
pubKey := privKey.PublicKey()
|
pubKey := privKey.PublicKey()
|
||||||
assert.Equal(t, hex.EncodeToString(pubKey.Bytes()), testCase.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
|
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.
|
// NewAccountFromWIF creates a new Account from the given WIF.
|
||||||
func NewAccountFromWIF(wif string) (*Account, error) {
|
func NewAccountFromWIF(wif string) (*Account, error) {
|
||||||
privKey, err := keys.NewPrivateKeyFromWIF(wif)
|
privKey, err := keys.NewPrivateKeyFromWIF(wif)
|
||||||
|
|
|
@ -141,9 +141,11 @@ func TestContractSignTx(t *testing.T) {
|
||||||
require.Error(t, acc2.SignTx(0, tx)) // Locked account.
|
require.Error(t, acc2.SignTx(0, tx)) // Locked account.
|
||||||
|
|
||||||
acc2.Locked = false
|
acc2.Locked = false
|
||||||
acc2.privateKey = nil
|
acc2.Close()
|
||||||
require.False(t, acc2.CanSign())
|
require.False(t, acc2.CanSign())
|
||||||
require.Error(t, acc2.SignTx(0, tx)) // No private key.
|
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{
|
tx.Scripts = append(tx.Scripts, transaction.Witness{
|
||||||
VerificationScript: acc.Contract.Script,
|
VerificationScript: acc.Contract.Script,
|
||||||
|
|
|
@ -168,9 +168,14 @@ func (w *Wallet) JSON() ([]byte, error) {
|
||||||
return json.MarshalIndent(w, " ", " ")
|
return json.MarshalIndent(w, " ", " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Close is deprecated.
|
// Close closes all Wallet accounts making them incapable of signing anything
|
||||||
// Close performs nothing and is left for backwards compatibility.
|
// (unless they're decrypted again). It's not doing anything to the underlying
|
||||||
func (w *Wallet) Close() {}
|
// wallet file.
|
||||||
|
func (w *Wallet) Close() {
|
||||||
|
for _, acc := range w.Accounts {
|
||||||
|
acc.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetAccount returns an account corresponding to the provided scripthash.
|
// GetAccount returns an account corresponding to the provided scripthash.
|
||||||
func (w *Wallet) GetAccount(h util.Uint160) *Account {
|
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")
|
require.Errorf(t, err, "open testWallet: no such file or directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateAccount(t *testing.T) {
|
func TestCreateAccountAndClose(t *testing.T) {
|
||||||
wallet := checkWalletConstructor(t)
|
wallet := checkWalletConstructor(t)
|
||||||
|
|
||||||
errAcc := wallet.CreateAccount("testName", "testPass")
|
errAcc := wallet.CreateAccount("testName", "testPass")
|
||||||
require.NoError(t, errAcc)
|
require.NoError(t, errAcc)
|
||||||
accounts := wallet.Accounts
|
accounts := wallet.Accounts
|
||||||
require.Len(t, accounts, 1)
|
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) {
|
func TestAddAccount(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue