keys: make NEP2Decrypt return a PrivateKey rather than WIF

There is no point in encoding the output of this function in a WIF format,
most of the users actually want the real key and those who need a WIF can
easily get if from the key (and it's simpler than getting the key from the
WIF).

It also fixes a severe bug in NEP2Decrypt, base58 decoding errors were not
processed correctly.
This commit is contained in:
Roman Khimov 2020-01-09 17:27:12 +03:00
parent 9a8f5c2a5d
commit b5b05a969c
4 changed files with 13 additions and 23 deletions

View file

@ -14,7 +14,6 @@ import (
"github.com/CityOfZion/neo-go/pkg/smartcontract"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
"github.com/CityOfZion/neo-go/pkg/wallet"
"github.com/nspcc-dev/dbft"
"github.com/nspcc-dev/dbft/block"
"github.com/nspcc-dev/dbft/crypto"
@ -178,16 +177,12 @@ func (s *service) validatePayload(p *Payload) bool {
}
func getKeyPair(cfg *config.WalletConfig) (crypto.PrivateKey, crypto.PublicKey) {
acc, err := wallet.DecryptAccount(cfg.Path, cfg.Password)
// TODO: replace with wallet opening from the given path (#588)
key, err := keys.NEP2Decrypt(cfg.Path, cfg.Password)
if err != nil {
return nil, nil
}
key := acc.PrivateKey()
if key == nil {
return nil, nil
}
return &privateKey{PrivateKey: key}, &publicKey{PublicKey: key.PublicKey()}
}

View file

@ -77,13 +77,13 @@ func NEP2Encrypt(priv *PrivateKey, passphrase string) (s string, err error) {
// NEP2Decrypt decrypts an encrypted key using a given passphrase
// under the NEP-2 standard.
func NEP2Decrypt(key, passphrase string) (s string, err error) {
func NEP2Decrypt(key, passphrase string) (*PrivateKey, error) {
b, err := base58.CheckDecode(key)
if err != nil {
return s, nil
return nil, err
}
if err := validateNEP2Format(b); err != nil {
return s, err
return nil, err
}
addrHash := b[3:7]
@ -91,7 +91,7 @@ func NEP2Decrypt(key, passphrase string) (s string, err error) {
phraseNorm := norm.NFC.Bytes([]byte(passphrase))
derivedKey, err := scrypt.Key(phraseNorm, addrHash, n, r, p, keyLen)
if err != nil {
return s, err
return nil, err
}
derivedKey1 := derivedKey[:32]
@ -100,7 +100,7 @@ func NEP2Decrypt(key, passphrase string) (s string, err error) {
decrypted, err := aesDecrypt(encryptedBytes, derivedKey2)
if err != nil {
return s, err
return nil, err
}
privBytes := xor(decrypted, derivedKey1)
@ -108,14 +108,14 @@ func NEP2Decrypt(key, passphrase string) (s string, err error) {
// Rebuild the private key.
privKey, err := NewPrivateKeyFromBytes(privBytes)
if err != nil {
return s, err
return nil, err
}
if !compareAddressHash(privKey, addrHash) {
return s, errors.New("password mismatch")
return nil, errors.New("password mismatch")
}
return privKey.WIF(), nil
return privKey, nil
}
func compareAddressHash(priv *PrivateKey, inhash []byte) bool {

View file

@ -27,18 +27,13 @@ func TestNEP2Encrypt(t *testing.T) {
func TestNEP2Decrypt(t *testing.T) {
for _, testCase := range keytestcases.Arr {
privKeyString, err := NEP2Decrypt(testCase.EncryptedWif, testCase.Passphrase)
privKey, err := NEP2Decrypt(testCase.EncryptedWif, testCase.Passphrase)
if testCase.Invalid {
assert.Error(t, err)
continue
}
assert.Nil(t, err)
privKey, err := NewPrivateKeyFromWIF(privKeyString)
assert.Nil(t, err)
assert.Equal(t, testCase.PrivateKey, privKey.String())
wif := privKey.WIF()

View file

@ -63,11 +63,11 @@ func NewAccount() (*Account, error) {
// DecryptAccount decrypts the encryptedWIF with the given passphrase and
// return the decrypted Account.
func DecryptAccount(encryptedWIF, passphrase string) (*Account, error) {
wif, err := keys.NEP2Decrypt(encryptedWIF, passphrase)
key, err := keys.NEP2Decrypt(encryptedWIF, passphrase)
if err != nil {
return nil, err
}
return NewAccountFromWIF(wif)
return newAccountFromPrivateKey(key), nil
}
// Encrypt encrypts the wallet's PrivateKey with the given passphrase