crypto/wallet: move public/private key into the new keys package

And drop associated _pkg.dev remnants (refs. #307).

Original `dev` branch had two separate packages for public and private keys,
but those are so intertwined (`TestHelper` subpackage is a proof) that it's
better unite them and all associated code (like WIF and NEP-2) in one
package. This patch also:
 * creates internal `keytestcases` package to share things with wallet (maybe
   it'll be changed in some future)
 * ports some tests from `dev`
 * ports Verify() method for public key from `dev`
 * expands TestPrivateKey() with public key check
This commit is contained in:
Roman Khimov 2019-08-27 16:29:42 +03:00
parent b19190b32f
commit b77e533d13
35 changed files with 298 additions and 657 deletions

View file

@ -1,125 +0,0 @@
package privatekey
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
"math/big"
"github.com/CityOfZion/neo-go/pkg/crypto/publickey"
"github.com/CityOfZion/neo-go/pkg/crypto/base58"
"github.com/CityOfZion/neo-go/pkg/crypto/elliptic"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/rfc6979"
)
// PrivateKey represents a NEO private key.
type PrivateKey struct {
b []byte
}
// NewPrivateKey will create a new private key
// With curve as Secp256r1
func NewPrivateKey() (*PrivateKey, error) {
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
b := make([]byte, curve.N.BitLen()/8+8)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return nil, err
}
d := new(big.Int).SetBytes(b)
d.Mod(d, new(big.Int).Sub(curve.N, big.NewInt(1)))
d.Add(d, big.NewInt(1))
p := &PrivateKey{b: d.Bytes()}
return p, nil
}
// NewPrivateKeyFromHex will create a new private key hex string
func NewPrivateKeyFromHex(str string) (*PrivateKey, error) {
b, err := hex.DecodeString(str)
if err != nil {
return nil, err
}
return NewPrivateKeyFromBytes(b)
}
// NewPrivateKeyFromBytes returns a NEO PrivateKey from the given byte slice.
func NewPrivateKeyFromBytes(b []byte) (*PrivateKey, error) {
if len(b) != 32 {
return nil, fmt.Errorf(
"invalid byte length: expected %d bytes got %d", 32, len(b),
)
}
return &PrivateKey{b}, nil
}
// PublicKey returns a the public corresponding to the private key
// For the curve secp256r1
func (p *PrivateKey) PublicKey() (*publickey.PublicKey, error) {
var (
c = elliptic.NewEllipticCurve(elliptic.Secp256r1)
q = new(big.Int).SetBytes(p.b)
)
p1, p2 := c.ScalarBaseMult(q.Bytes())
point := elliptic.Point{
X: p1,
Y: p2,
}
if !c.IsOnCurve(p1, p2) {
return nil, errors.New("failed to derive public key using elliptic curve")
}
return &publickey.PublicKey{
Curve: c,
Point: point,
}, nil
}
// WIFEncode will converts a private key
// to the Wallet Import Format for NEO
func WIFEncode(key []byte) (s string) {
if len(key) != 32 {
return "invalid private key length"
}
buf := new(bytes.Buffer)
buf.WriteByte(0x80)
buf.Write(key)
buf.WriteByte(0x01)
checksum, _ := hash.Checksum(buf.Bytes())
buf.Write(checksum)
WIF := base58.Encode(buf.Bytes())
return WIF
}
// Sign will sign the corresponding data using the private key
func (p *PrivateKey) Sign(data []byte) ([]byte, error) {
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
key := p.b
digest, _ := hash.Sha256(data)
r, s, err := rfc6979.SignECDSA(curve, key, digest[:], sha256.New)
if err != nil {
return nil, err
}
curveOrderByteSize := curve.P.BitLen() / 8
rBytes, sBytes := r.Bytes(), s.Bytes()
signature := make([]byte, curveOrderByteSize*2)
copy(signature[curveOrderByteSize-len(rBytes):], rBytes)
copy(signature[curveOrderByteSize*2-len(sBytes):], sBytes)
return signature, nil
}

View file

@ -1,48 +0,0 @@
package privatekey
import (
"encoding/hex"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestPrivateKeyToPublicKey(t *testing.T) {
input := "495d528227c7dcc234c690af1222e67cde916dac1652cad97e0263825a8268a6"
privateKey, err := NewPrivateKeyFromHex(input)
if err != nil {
t.Fatal(err)
}
pubKey, _ := privateKey.PublicKey()
pubKeyBytes := pubKey.Bytes()
actual := hex.EncodeToString(pubKeyBytes)
expected := "03cd4c4ee9c8e1fae9d12ecf7c96cb3a057b550393f9e82182c4dae1139871682e"
assert.Equal(t, expected, actual)
}
func TestWIFEncode(t *testing.T) {
input := "29bbf53185a973d2e3803cb92908fd08117486d1f2e7bab73ed0d00255511637"
inputBytes, _ := hex.DecodeString(input)
actual := WIFEncode(inputBytes)
expected := "KxcqV28rGDcpVR3fYg7R9vricLpyZ8oZhopyFLAWuRv7Y8TE9WhW"
assert.Equal(t, expected, actual)
}
func TestSigning(t *testing.T) {
// These were taken from the rfcPage:https://tools.ietf.org/html/rfc6979#page-33
// public key: U = xG
//Ux = 60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6
//Uy = 7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299
PrivateKey, _ := NewPrivateKeyFromHex("C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721")
data, err := PrivateKey.Sign([]byte("sample"))
if err != nil {
t.Fatal(err)
}
r := "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716"
s := "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"
assert.Equal(t, strings.ToLower(r+s), hex.EncodeToString(data))
}

View file

@ -1,33 +0,0 @@
package pubkeytesthelper
import (
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto/privatekey"
)
// SignDataWithRandomPrivateKey will sign data with
// a random private key, then verify said data
// returning true if Verify returns true
func SignDataWithRandomPrivateKey(data []byte) (bool, error) {
hashedData, err := hash.Sha256(data)
if err != nil {
return false, err
}
privKey, err := privatekey.NewPrivateKey()
if err != nil {
return false, err
}
signedData, err := privKey.Sign(data)
if err != nil {
return false, err
}
pubKey, err := privKey.PublicKey()
if err != nil {
return false, err
}
result := pubKey.Verify(signedData, hashedData.Bytes())
return result, nil
}

View file

@ -1,34 +0,0 @@
package pubkeytesthelper
import (
"testing"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto/privatekey"
"github.com/stretchr/testify/assert"
)
func TestPubKeyVerify(t *testing.T) {
actual, err := SignDataWithRandomPrivateKey([]byte("sample"))
if err != nil {
t.Fatal(err)
}
expected := true
assert.Equal(t, expected, actual)
}
func TestWrongPubKey(t *testing.T) {
privKey, _ := privatekey.NewPrivateKey()
sample := []byte("sample")
hashedData, _ := hash.Sha256(sample)
signedData, _ := privKey.Sign(sample)
secondPrivKey, _ := privatekey.NewPrivateKey()
wrongPubKey, _ := secondPrivKey.PublicKey()
actual := wrongPubKey.Verify(signedData, hashedData.Bytes())
expcted := false
assert.Equal(t, expcted, actual)
}

View file

@ -1,164 +0,0 @@
package publickey
import (
"bytes"
"crypto/ecdsa"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"math/big"
"github.com/CityOfZion/neo-go/pkg/crypto/base58"
"github.com/CityOfZion/neo-go/pkg/crypto/elliptic"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
)
// PublicKeys is a list of public keys.
type PublicKeys []*PublicKey
func (keys PublicKeys) Len() int { return len(keys) }
func (keys PublicKeys) Swap(i, j int) { keys[i], keys[j] = keys[j], keys[i] }
func (keys PublicKeys) Less(i, j int) bool {
if keys[i].X.Cmp(keys[j].X) == -1 {
return true
}
if keys[i].X.Cmp(keys[j].X) == 1 {
return false
}
if keys[i].X.Cmp(keys[j].X) == 0 {
return false
}
return keys[i].Y.Cmp(keys[j].Y) == -1
}
// PublicKey represents a public key and provides a high level
// API around the ECPoint.
type PublicKey struct {
Curve elliptic.Curve
elliptic.Point
}
// NewPublicKeyFromString return a public key created from the
// given hex string.
func NewPublicKeyFromString(s string) (*PublicKey, error) {
b, err := hex.DecodeString(s)
if err != nil {
return nil, err
}
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
pubKey := &PublicKey{curve, elliptic.Point{}}
if err := pubKey.DecodeBinary(bytes.NewReader(b)); err != nil {
return nil, err
}
return pubKey, nil
}
// Bytes returns the byte array representation of the public key.
func (p *PublicKey) Bytes() []byte {
if p.Curve.IsInfinity(p.Point) {
return []byte{0x00}
}
var (
x = p.X.Bytes()
paddedX = append(bytes.Repeat([]byte{0x00}, 32-len(x)), x...)
prefix = byte(0x03)
)
if p.Y.Bit(0) == 0 {
prefix = byte(0x02)
}
return append([]byte{prefix}, paddedX...)
}
// ToAddress will convert a public key to it's neo-address
func (p *PublicKey) ToAddress() string {
publicKeyBytes := p.Bytes()
publicKeyBytes = append([]byte{0x21}, publicKeyBytes...) // 0x21 = length of pubKey
publicKeyBytes = append(publicKeyBytes, 0xAC) // 0xAC = CheckSig
hash160PubKey, _ := hash.Hash160(publicKeyBytes)
versionHash160PubKey := append([]byte{0x17}, hash160PubKey.Bytes()...)
checksum, _ := hash.Checksum(versionHash160PubKey)
checkVersionHash160 := append(versionHash160PubKey, checksum...)
address := base58.Encode(checkVersionHash160)
return address
}
// DecodeBinary decodes a PublicKey from the given io.Reader.
func (p *PublicKey) DecodeBinary(r io.Reader) error {
var prefix uint8
if err := binary.Read(r, binary.LittleEndian, &prefix); err != nil {
return err
}
// Infinity
if prefix == 0x00 {
p.Point = elliptic.Point{}
return nil
}
// Compressed public keys.
if prefix == 0x02 || prefix == 0x03 {
b := make([]byte, 32)
if err := binary.Read(r, binary.LittleEndian, b); err != nil {
return err
}
var err error
p.Point, err = p.Curve.Decompress(new(big.Int).SetBytes(b), uint(prefix&0x1))
if err != nil {
return err
}
} else if prefix == 0x04 {
buf := make([]byte, 65)
if err := binary.Read(r, binary.LittleEndian, buf); err != nil {
return err
}
p.X = new(big.Int).SetBytes(buf[1:33])
p.Y = new(big.Int).SetBytes(buf[33:65])
} else {
return fmt.Errorf("invalid prefix %d", prefix)
}
return nil
}
// EncodeBinary encodes a PublicKey to the given io.Writer.
func (p *PublicKey) EncodeBinary(w io.Writer) error {
return binary.Write(w, binary.LittleEndian, p.Bytes())
}
// Verify returns true if the signature is valid and corresponds
// to the hash and public key
func (p *PublicKey) Verify(signature []byte, hash []byte) bool {
publicKey := &ecdsa.PublicKey{}
publicKey.Curve = p.Curve
publicKey.X = p.X
publicKey.Y = p.Y
if p.X == nil || p.Y == nil {
return false
}
rBytes := new(big.Int).SetBytes(signature[0:32])
sBytes := new(big.Int).SetBytes(signature[32:64])
return ecdsa.Verify(publicKey, hash, rBytes, sBytes)
}

View file

@ -1,81 +0,0 @@
package publickey
import (
"bytes"
"crypto/rand"
"encoding/hex"
"io"
"math/big"
"testing"
"github.com/CityOfZion/neo-go/pkg/crypto/elliptic"
"github.com/stretchr/testify/assert"
)
func TestDecodeFromString(t *testing.T) {
str := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
pubKey, err := NewPublicKeyFromString(str)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, str, hex.EncodeToString(pubKey.Bytes()))
}
func TestEncodeDecodeInfinity(t *testing.T) {
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
key := &PublicKey{curve, elliptic.Point{}}
buf := new(bytes.Buffer)
assert.Nil(t, key.EncodeBinary(buf))
assert.Equal(t, 1, buf.Len())
keyDecode := &PublicKey{}
assert.Nil(t, keyDecode.DecodeBinary(buf))
assert.Equal(t, []byte{0x00}, keyDecode.Bytes())
}
func TestEncodeDecodePublicKey(t *testing.T) {
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
for i := 0; i < 4; i++ {
p := &PublicKey{curve, randomECPoint()}
buf := new(bytes.Buffer)
assert.Nil(t, p.EncodeBinary(buf))
pDecode := &PublicKey{curve, elliptic.Point{}}
assert.Nil(t, pDecode.DecodeBinary(buf))
assert.Equal(t, p.X, pDecode.X)
}
}
func TestPubkeyToAddress(t *testing.T) {
pubKey, err := NewPublicKeyFromString("031ee4e73a17d8f76dc02532e2620bcb12425b33c0c9f9694cc2caa8226b68cad4")
if err != nil {
t.Fatal(err)
}
actual := pubKey.ToAddress()
expected := "AUpGsNCHzSimeMRVPQfhwrVdiUp8Q2N2Qx"
assert.Equal(t, expected, actual)
}
func randomECPoint() elliptic.Point {
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
b := make([]byte, curve.N.BitLen()/8+8)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return elliptic.Point{}
}
d := new(big.Int).SetBytes(b)
d.Mod(d, new(big.Int).Sub(curve.N, big.NewInt(1)))
d.Add(d, big.NewInt(1))
q := new(big.Int).SetBytes(d.Bytes())
P1, P2 := curve.ScalarBaseMult(q.Bytes())
return elliptic.Point{
X: P1,
Y: P2,
}
}

View file

@ -7,7 +7,7 @@ import (
"io"
"github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
)
@ -52,7 +52,7 @@ type AccountState struct {
Version uint8
ScriptHash util.Uint160
IsFrozen bool
Votes []*crypto.PublicKey
Votes []*keys.PublicKey
Balances map[util.Uint256]util.Fixed8
}
@ -62,7 +62,7 @@ func NewAccountState(scriptHash util.Uint160) *AccountState {
Version: 0,
ScriptHash: scriptHash,
IsFrozen: false,
Votes: []*crypto.PublicKey{},
Votes: []*keys.PublicKey{},
Balances: make(map[util.Uint256]util.Fixed8),
}
}
@ -80,9 +80,9 @@ func (s *AccountState) DecodeBinary(r io.Reader) error {
}
lenVotes := util.ReadVarUint(r)
s.Votes = make([]*crypto.PublicKey, lenVotes)
s.Votes = make([]*keys.PublicKey, lenVotes)
for i := 0; i < int(lenVotes); i++ {
s.Votes[i] = &crypto.PublicKey{}
s.Votes[i] = &keys.PublicKey{}
if err := s.Votes[i].DecodeBinary(r); err != nil {
return err
}

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert"
)
@ -13,11 +14,11 @@ func TestDecodeEncodeAccountState(t *testing.T) {
var (
n = 10
balances = make(map[util.Uint256]util.Fixed8)
votes = make([]*crypto.PublicKey, n)
votes = make([]*keys.PublicKey, n)
)
for i := 0; i < n; i++ {
balances[randomUint256()] = util.Fixed8(int64(randomInt(1, 10000)))
votes[i] = &crypto.PublicKey{
votes[i] = &keys.PublicKey{
ECPoint: crypto.RandomECPoint(),
}
}

View file

@ -7,7 +7,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
)
@ -39,7 +39,7 @@ type AssetState struct {
Precision uint8
FeeMode uint8
FeeAddress util.Uint160
Owner *crypto.PublicKey
Owner *keys.PublicKey
Admin util.Uint160
Issuer util.Uint160
Expiration uint32
@ -77,7 +77,7 @@ func (a *AssetState) DecodeBinary(r io.Reader) error {
return err
}
a.Owner = &crypto.PublicKey{}
a.Owner = &keys.PublicKey{}
if err := a.Owner.DecodeBinary(r); err != nil {
return err
}

View file

@ -5,7 +5,7 @@ import (
"testing"
"github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert"
)
@ -19,7 +19,7 @@ func TestEncodeDecodeAssetState(t *testing.T) {
Available: util.Fixed8(100),
Precision: 0,
FeeMode: feeMode,
Owner: &crypto.PublicKey{},
Owner: &keys.PublicKey{},
Admin: randomUint160(),
Issuer: randomUint160(),
Expiration: 10,

View file

@ -3,7 +3,7 @@ package transaction
import (
"io"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
)
// A Enrollment transaction represents an enrollment form, which indicates
@ -13,12 +13,12 @@ import (
// The way to cancel the registration is: Spend the deposit on the address of the PublicKey.
type EnrollmentTX struct {
// PublicKey of the validator
PublicKey *crypto.PublicKey
PublicKey *keys.PublicKey
}
// DecodeBinary implements the Payload interface.
func (tx *EnrollmentTX) DecodeBinary(r io.Reader) error {
tx.PublicKey = &crypto.PublicKey{}
tx.PublicKey = &keys.PublicKey{}
return tx.PublicKey.DecodeBinary(r)
}

View file

@ -4,7 +4,7 @@ import (
"encoding/binary"
"io"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
)
@ -25,7 +25,7 @@ type RegisterTX struct {
Precision uint8
// Public key of the owner
Owner *crypto.PublicKey
Owner *keys.PublicKey
Admin util.Uint160
}
@ -50,7 +50,7 @@ func (tx *RegisterTX) DecodeBinary(r io.Reader) error {
return err
}
tx.Owner = &crypto.PublicKey{}
tx.Owner = &keys.PublicKey{}
if err := tx.Owner.DecodeBinary(r); err != nil {
return err
}

View file

@ -6,6 +6,7 @@ import (
"testing"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert"
)
@ -20,7 +21,7 @@ func TestRegisterTX(t *testing.T) {
Name: "this is some token I created",
Amount: util.Fixed8FromInt64(1000000),
Precision: 8,
Owner: &crypto.PublicKey{},
Owner: &keys.PublicKey{},
Admin: someuint160,
},
}
@ -51,7 +52,7 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
assert.Equal(t, "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]", txData.Name)
assert.Equal(t, util.Fixed8FromInt64(100000000), txData.Amount)
assert.Equal(t, uint8(0), txData.Precision)
assert.Equal(t, &crypto.PublicKey{}, txData.Owner)
assert.Equal(t, &keys.PublicKey{}, txData.Owner)
assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", crypto.AddressFromUint160(txData.Admin))
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().ReverseString())

View file

@ -8,8 +8,8 @@ import (
"github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/smartcontract"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/CityOfZion/neo-go/pkg/vm"
@ -101,7 +101,7 @@ func governingTokenTX() *transaction.Transaction {
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]",
Amount: util.Fixed8FromInt64(100000000),
Precision: 0,
Owner: &crypto.PublicKey{},
Owner: &keys.PublicKey{},
Admin: admin,
}
@ -124,7 +124,7 @@ func utilityTokenTX() *transaction.Transaction {
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
Amount: calculateUtilityAmount(),
Precision: 8,
Owner: &crypto.PublicKey{},
Owner: &keys.PublicKey{},
Admin: admin,
}
tx := &transaction.Transaction{
@ -139,10 +139,10 @@ func utilityTokenTX() *transaction.Transaction {
return tx
}
func getValidators(cfg config.ProtocolConfiguration) ([]*crypto.PublicKey, error) {
validators := make([]*crypto.PublicKey, len(cfg.StandbyValidators))
func getValidators(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) {
validators := make([]*keys.PublicKey, len(cfg.StandbyValidators))
for i, pubKeyStr := range cfg.StandbyValidators {
pubKey, err := crypto.NewPublicKeyFromString(pubKeyStr)
pubKey, err := keys.NewPublicKeyFromString(pubKeyStr)
if err != nil {
return nil, err
}
@ -151,7 +151,7 @@ func getValidators(cfg config.ProtocolConfiguration) ([]*crypto.PublicKey, error
return validators, nil
}
func getNextConsensusAddress(validators []*crypto.PublicKey) (val util.Uint160, err error) {
func getNextConsensusAddress(validators []*keys.PublicKey) (val util.Uint160, err error) {
vlen := len(validators)
raw, err := smartcontract.CreateMultiSigRedeemScript(
vlen-(vlen-1)/3,

View file

@ -1,16 +1,16 @@
package core
import (
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
)
// Validators is a mapping between public keys and ValidatorState.
type Validators map[*crypto.PublicKey]*ValidatorState
type Validators map[*keys.PublicKey]*ValidatorState
// ValidatorState holds the state of a validator.
type ValidatorState struct {
PublicKey *crypto.PublicKey
PublicKey *keys.PublicKey
Registered bool
Votes util.Fixed8
}

View file

@ -1,4 +1,4 @@
package wallet
package keys
import (
"bytes"
@ -24,20 +24,21 @@ const (
var nepHeader = []byte{0x01, 0x42}
type scryptParams struct {
type ScryptParams struct {
N int `json:"n"`
R int `json:"r"`
P int `json:"p"`
}
func newScryptParams() scryptParams {
return scryptParams{
func NEP2ScryptParams() ScryptParams {
return ScryptParams{
N: n,
R: r,
P: p,
}
}
// NEP2Encrypt encrypts a the PrivateKey using a given passphrase
// under the NEP-2 standard.
func NEP2Encrypt(priv *PrivateKey, passphrase string) (s string, err error) {

View file

@ -1,32 +1,34 @@
package wallet
package keys
import (
"testing"
"github.com/CityOfZion/neo-go/pkg/internal/keytestcases"
)
func TestNEP2Encrypt(t *testing.T) {
for _, testCase := range testKeyCases {
for _, testCase := range keytestcases.Arr {
privKey, err := NewPrivateKeyFromHex(testCase.privateKey)
privKey, err := NewPrivateKeyFromHex(testCase.PrivateKey)
if err != nil {
t.Fatal(err)
}
encryptedWif, err := NEP2Encrypt(privKey, testCase.passphrase)
encryptedWif, err := NEP2Encrypt(privKey, testCase.Passphrase)
if err != nil {
t.Fatal(err)
}
if want, have := testCase.encryptedWif, encryptedWif; want != have {
if want, have := testCase.EncryptedWif, encryptedWif; want != have {
t.Fatalf("expected %s got %s", want, have)
}
}
}
func TestNEP2Decrypt(t *testing.T) {
for _, testCase := range testKeyCases {
for _, testCase := range keytestcases.Arr {
privKeyString, err := NEP2Decrypt(testCase.encryptedWif, testCase.passphrase)
privKeyString, err := NEP2Decrypt(testCase.EncryptedWif, testCase.Passphrase)
if err != nil {
t.Fatal(err)
@ -37,7 +39,7 @@ func TestNEP2Decrypt(t *testing.T) {
t.Fatal(err)
}
if want, have := testCase.privateKey, privKey.String(); want != have {
if want, have := testCase.PrivateKey, privKey.String(); want != have {
t.Fatalf("expected %s got %s", want, have)
}
@ -45,7 +47,7 @@ func TestNEP2Decrypt(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if want, have := testCase.wif, wif; want != have {
if want, have := testCase.Wif, wif; want != have {
t.Fatalf("expected %s got %s", want, have)
}
@ -53,7 +55,7 @@ func TestNEP2Decrypt(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if want, have := testCase.address, address; want != have {
if want, have := testCase.Address, address; want != have {
t.Fatalf("expected %s got %s", want, have)
}
}

View file

@ -1,4 +1,4 @@
package wallet
package keys
import (
"bytes"
@ -67,10 +67,10 @@ func NewPrivateKeyFromRawBytes(b []byte) (*PrivateKey, error) {
}
// PublicKey derives the public key from the private key.
func (p *PrivateKey) PublicKey() (*crypto.PublicKey, error) {
func (p *PrivateKey) PublicKey() (*PublicKey, error) {
var (
err error
pk crypto.PublicKey
pk PublicKey
c = crypto.NewEllipticCurve()
q = new(big.Int).SetBytes(p.b)
)

View file

@ -0,0 +1,65 @@
package keys
import (
"encoding/hex"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/CityOfZion/neo-go/pkg/internal/keytestcases"
)
func TestPrivateKey(t *testing.T) {
for _, testCase := range keytestcases.Arr {
privKey, err := NewPrivateKeyFromHex(testCase.PrivateKey)
if err != nil {
t.Fatal(err)
}
address, err := privKey.Address()
if err != nil {
t.Fatal(err)
}
if want, have := testCase.Address, address; want != have {
t.Fatalf("expected %s got %s", want, have)
}
wif, err := privKey.WIF()
if err != nil {
t.Fatal(err)
}
if want, have := testCase.Wif, wif; want != have {
t.Fatalf("expected %s got %s", want, have)
}
pubKey, _ := privKey.PublicKey()
assert.Equal(t, hex.EncodeToString(pubKey.Bytes()), testCase.PublicKey)
}
}
func TestPrivateKeyFromWIF(t *testing.T) {
for _, testCase := range keytestcases.Arr {
key, err := NewPrivateKeyFromWIF(testCase.Wif)
if err != nil {
t.Fatal(err)
}
if want, have := testCase.PrivateKey, key.String(); want != have {
t.Fatalf("expected %s got %s", want, have)
}
}
}
func TestSigning(t *testing.T) {
// These were taken from the rfcPage:https://tools.ietf.org/html/rfc6979#page-33
// public key: U = xG
//Ux = 60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6
//Uy = 7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299
PrivateKey, _ := NewPrivateKeyFromHex("C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721")
data, err := PrivateKey.Sign([]byte("sample"))
if err != nil {
t.Fatal(err)
}
r := "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716"
s := "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"
assert.Equal(t, strings.ToLower(r+s), hex.EncodeToString(data))
}

View file

@ -1,8 +1,9 @@
package crypto
package keys
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/x509"
"encoding/binary"
"encoding/hex"
@ -10,6 +11,7 @@ import (
"math/big"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/pkg/errors"
)
@ -35,7 +37,7 @@ func (keys PublicKeys) Less(i, j int) bool {
// PublicKey represents a public key and provides a high level
// API around the ECPoint.
type PublicKey struct {
ECPoint
crypto.ECPoint
}
// NewPublicKeyFromString return a public key created from the
@ -87,7 +89,7 @@ func NewPublicKeyFromRawBytes(data []byte) (*PublicKey, error) {
return nil, errors.New("given bytes aren't ECDSA public key")
}
key := PublicKey{
ECPoint{
crypto.ECPoint{
X: pk.X,
Y: pk.Y,
},
@ -102,14 +104,14 @@ func (p *PublicKey) DecodeBytes(data []byte) error {
switch prefix := data[0]; prefix {
// Infinity
case 0x00:
p.ECPoint = ECPoint{}
p.ECPoint = crypto.ECPoint{}
// Compressed public keys
case 0x02, 0x03:
if l < 33 {
return errors.Errorf("bad binary size(%d)", l)
}
c := NewEllipticCurve()
c := crypto.NewEllipticCurve()
var err error
p.ECPoint, err = c.Decompress(new(big.Int).SetBytes(data[1:]), uint(prefix&0x1))
if err != nil {
@ -139,7 +141,7 @@ func (p *PublicKey) DecodeBinary(r io.Reader) error {
// Infinity
switch prefix {
case 0x00:
p.ECPoint = ECPoint{}
p.ECPoint = crypto.ECPoint{}
return nil
// Compressed public keys
case 0x02, 0x03:
@ -190,6 +192,22 @@ func (p *PublicKey) Address() (string, error) {
csum := hash.Checksum(b)
b = append(b, csum...)
address := Base58Encode(b)
address := crypto.Base58Encode(b)
return address, nil
}
// Verify returns true if the signature is valid and corresponds
// to the hash and public key
func (p *PublicKey) Verify(signature []byte, hash []byte) bool {
publicKey := &ecdsa.PublicKey{}
publicKey.Curve = elliptic.P256()
publicKey.X = p.X
publicKey.Y = p.Y
if p.X == nil || p.Y == nil {
return false
}
rBytes := new(big.Int).SetBytes(signature[0:32])
sBytes := new(big.Int).SetBytes(signature[32:64])
return ecdsa.Verify(publicKey, hash, rBytes, sBytes)
}

View file

@ -1,15 +1,16 @@
package crypto
package keys
import (
"bytes"
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeInfinity(t *testing.T) {
key := &PublicKey{ECPoint{}}
key := &PublicKey{crypto.ECPoint{}}
buf := new(bytes.Buffer)
assert.Nil(t, key.EncodeBinary(buf))
assert.Equal(t, 1, buf.Len())
@ -21,7 +22,7 @@ func TestEncodeDecodeInfinity(t *testing.T) {
func TestEncodeDecodePublicKey(t *testing.T) {
for i := 0; i < 4; i++ {
p := &PublicKey{RandomECPoint()}
p := &PublicKey{crypto.RandomECPoint()}
buf := new(bytes.Buffer)
assert.Nil(t, p.EncodeBinary(buf))
@ -39,3 +40,14 @@ func TestDecodeFromString(t *testing.T) {
}
assert.Equal(t, str, hex.EncodeToString(pubKey.Bytes()))
}
func TestPubkeyToAddress(t *testing.T) {
pubKey, err := NewPublicKeyFromString("031ee4e73a17d8f76dc02532e2620bcb12425b33c0c9f9694cc2caa8226b68cad4")
if err != nil {
t.Fatal(err)
}
actual, _ := pubKey.Address()
expected := "AUpGsNCHzSimeMRVPQfhwrVdiUp8Q2N2Qx"
assert.Equal(t, expected, actual)
}

View file

@ -0,0 +1,56 @@
package keys
import (
"testing"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/stretchr/testify/assert"
)
// SignDataWithRandomPrivateKey will sign data with
// a random private key, then verify said data
// returning true if Verify returns true
func SignDataWithRandomPrivateKey(data []byte) (bool, error) {
hashedData := hash.Sha256(data)
privKey, err := NewPrivateKey()
if err != nil {
return false, err
}
signedData, err := privKey.Sign(data)
if err != nil {
return false, err
}
pubKey, err := privKey.PublicKey()
if err != nil {
return false, err
}
result := pubKey.Verify(signedData, hashedData.Bytes())
return result, nil
}
func TestPubKeyVerify(t *testing.T) {
actual, err := SignDataWithRandomPrivateKey([]byte("sample"))
if err != nil {
t.Fatal(err)
}
expected := true
assert.Equal(t, expected, actual)
}
func TestWrongPubKey(t *testing.T) {
privKey, _ := NewPrivateKey()
sample := []byte("sample")
hashedData := hash.Sha256(sample)
signedData, _ := privKey.Sign(sample)
secondPrivKey, _ := NewPrivateKey()
wrongPubKey, _ := secondPrivKey.PublicKey()
actual := wrongPubKey.Verify(signedData, hashedData.Bytes())
expcted := false
assert.Equal(t, expcted, actual)
}

View file

@ -1,4 +1,4 @@
package wallet
package keys
import (
"bytes"
@ -98,7 +98,7 @@ func (wif WIF) GetVerificationScript() ([]byte, error) {
)
var (
vScript []byte
pubkey *crypto.PublicKey
pubkey *PublicKey
)
pubkey, err := wif.PrivateKey.PublicKey()
if err != nil {

View file

@ -1,4 +1,4 @@
package wallet
package keys
import (
"encoding/hex"

View file

@ -0,0 +1,37 @@
package keytestcases
type Ktype struct {
Address,
PrivateKey,
PublicKey,
Wif,
Passphrase,
EncryptedWif string
}
var Arr = []Ktype{
{
Address: "ALq7AWrhAueN6mJNqk6FHJjnsEoPRytLdW",
PrivateKey: "7d128a6d096f0c14c3a25a2b0c41cf79661bfcb4a8cc95aaaea28bde4d732344",
PublicKey: "02028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
Wif: "L1QqQJnpBwbsPGAuutuzPTac8piqvbR1HRjrY5qHup48TBCBFe4g",
Passphrase: "city of zion",
EncryptedWif: "6PYLHmDf6AjF4AsVtosmxHuPYeuyJL3SLuw7J1U8i7HxKAnYNsp61HYRfF",
},
{
Address: "ALfnhLg7rUyL6Jr98bzzoxz5J7m64fbR4s",
PrivateKey: "9ab7e154840daca3a2efadaf0df93cd3a5b51768c632f5433f86909d9b994a69",
PublicKey: "031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
Wif: "L2QTooFoDFyRFTxmtiVHt5CfsXfVnexdbENGDkkrrgTTryiLsPMG",
Passphrase: "我的密码",
EncryptedWif: "6PYWVp3xfgvnuNKP7ZavSViYvvim2zuzx9Q33vuWZr8aURiKeJ6Zm7BfPQ",
},
{
Address: "AVf4UGKevVrMR1j3UkPsuoYKSC4ocoAkKx",
PrivateKey: "3edee7036b8fd9cef91de47386b191dd76db2888a553e7736bb02808932a915b",
PublicKey: "02232ce8d2e2063dce0451131851d47421bfc4fc1da4db116fca5302c0756462fa",
Wif: "KyKvWLZsNwBJx5j9nurHYRwhYfdQUu9tTEDsLCUHDbYBL8cHxMiG",
Passphrase: "MyL33tP@33w0rd",
EncryptedWif: "6PYNoc1EG5J38MTqGN9Anphfdd6UwbS4cpFCzHhrkSKBBbV1qkbJJZQnkn",
},
}

View file

@ -11,7 +11,7 @@ import (
"sync"
"time"
"github.com/CityOfZion/neo-go/pkg/wallet"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/pkg/errors"
)
@ -32,7 +32,7 @@ type Client struct {
ctx context.Context
version string
wifMu *sync.Mutex
wif *wallet.WIF
wif *keys.WIF
balancerMu *sync.Mutex
balancer BalanceGetter
}
@ -93,10 +93,10 @@ func NewClient(ctx context.Context, endpoint string, opts ClientOptions) (*Clien
}, nil
}
func (c *Client) WIF() wallet.WIF {
func (c *Client) WIF() keys.WIF {
c.wifMu.Lock()
defer c.wifMu.Unlock()
return wallet.WIF{
return keys.WIF{
Version: c.wif.Version,
Compressed: c.wif.Compressed,
PrivateKey: c.wif.PrivateKey,
@ -109,7 +109,7 @@ func (c *Client) WIF() wallet.WIF {
func (c *Client) SetWIF(wif string) error {
c.wifMu.Lock()
defer c.wifMu.Unlock()
decodedWif, err := wallet.WIFDecode(wif, 0x00)
decodedWif, err := keys.WIFDecode(wif, 0x00)
if err != nil {
return errors.Wrap(err, "Failed to decode WIF; failed to add WIF to client ")
}

View file

@ -5,8 +5,8 @@ import (
"github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/CityOfZion/neo-go/pkg/wallet"
errs "github.com/pkg/errors"
)
@ -67,7 +67,7 @@ func CreateRawContractTransaction(params ContractTxParams) (*transaction.Transac
return tx, nil
}
func GetInvocationScript(tx *transaction.Transaction, wif wallet.WIF) ([]byte, error) {
func GetInvocationScript(tx *transaction.Transaction, wif keys.WIF) ([]byte, error) {
const (
pushbytes64 = 0x40
)

View file

@ -8,7 +8,7 @@ package rpc
import (
"github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/CityOfZion/neo-go/pkg/wallet"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
)
type (
@ -19,7 +19,7 @@ type (
assetId util.Uint256
address string
value util.Fixed8
wif wallet.WIF // a WIF to send the transaction
wif keys.WIF // a WIF to send the transaction
// since there are many ways to provide unspents,
// transaction composer stays agnostic to that how
// unspents was got;

View file

@ -5,7 +5,7 @@ import (
"sort"
"github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
)
@ -15,7 +15,7 @@ type AccountState struct {
Version uint8 `json:"version"`
ScriptHash util.Uint160 `json:"script_hash"`
IsFrozen bool `json:"frozen"`
Votes []*crypto.PublicKey `json:"votes"`
Votes []*keys.PublicKey `json:"votes"`
Balances []Balance `json:"balances"`
}

View file

@ -5,12 +5,12 @@ import (
"fmt"
"sort"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/vm"
)
// CreateMultiSigRedeemScript will create a script runnable by the VM.
func CreateMultiSigRedeemScript(m int, publicKeys crypto.PublicKeys) ([]byte, error) {
func CreateMultiSigRedeemScript(m int, publicKeys keys.PublicKeys) ([]byte, error) {
if m <= 1 {
return nil, fmt.Errorf("param m cannot be smaller or equal to 1 got %d", m)
}

View file

@ -4,18 +4,18 @@ import (
"bytes"
"testing"
"github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/CityOfZion/neo-go/pkg/vm"
"github.com/stretchr/testify/assert"
)
func TestCreateMultiSigRedeemScript(t *testing.T) {
val1, _ := crypto.NewPublicKeyFromString("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c")
val2, _ := crypto.NewPublicKeyFromString("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093")
val3, _ := crypto.NewPublicKeyFromString("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a")
val1, _ := keys.NewPublicKeyFromString("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c")
val2, _ := keys.NewPublicKeyFromString("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093")
val3, _ := keys.NewPublicKeyFromString("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a")
validators := []*crypto.PublicKey{val1, val2, val3}
validators := []*keys.PublicKey{val1, val2, val3}
out, err := CreateMultiSigRedeemScript(3, validators)
if err != nil {

View file

@ -1,12 +1,15 @@
package wallet
import "github.com/CityOfZion/neo-go/pkg/util"
import (
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
)
// Account represents a NEO account. It holds the private and public key
// along with some metadata.
type Account struct {
// NEO private key.
privateKey *PrivateKey
privateKey *keys.PrivateKey
// NEO public key.
publicKey []byte
@ -50,7 +53,7 @@ type Contract struct {
// NewAccount creates a new Account with a random generated PrivateKey.
func NewAccount() (*Account, error) {
priv, err := NewPrivateKey()
priv, err := keys.NewPrivateKey()
if err != nil {
return nil, err
}
@ -60,7 +63,7 @@ func NewAccount() (*Account, error) {
// DecryptAccount decrypt the encryptedWIF with the given passphrase and
// return the decrypted Account.
func DecryptAccount(encryptedWIF, passphrase string) (*Account, error) {
wif, err := NEP2Decrypt(encryptedWIF, passphrase)
wif, err := keys.NEP2Decrypt(encryptedWIF, passphrase)
if err != nil {
return nil, err
}
@ -70,7 +73,7 @@ func DecryptAccount(encryptedWIF, passphrase string) (*Account, error) {
// Encrypt encrypts the wallet's PrivateKey with the given passphrase
// under the NEP-2 standard.
func (a *Account) Encrypt(passphrase string) error {
wif, err := NEP2Encrypt(a.privateKey, passphrase)
wif, err := keys.NEP2Encrypt(a.privateKey, passphrase)
if err != nil {
return err
}
@ -80,7 +83,7 @@ func (a *Account) Encrypt(passphrase string) error {
// NewAccountFromWIF creates a new Account from the given WIF.
func NewAccountFromWIF(wif string) (*Account, error) {
privKey, err := NewPrivateKeyFromWIF(wif)
privKey, err := keys.NewPrivateKeyFromWIF(wif)
if err != nil {
return nil, err
}
@ -88,7 +91,7 @@ func NewAccountFromWIF(wif string) (*Account, error) {
}
// newAccountFromPrivateKey created a wallet from the given PrivateKey.
func newAccountFromPrivateKey(p *PrivateKey) (*Account, error) {
func newAccountFromPrivateKey(p *keys.PrivateKey) (*Account, error) {
pubKey, err := p.PublicKey()
if err != nil {
return nil, err

View file

@ -3,11 +3,13 @@ package wallet
import (
"encoding/hex"
"testing"
"github.com/CityOfZion/neo-go/pkg/internal/keytestcases"
)
func TestNewAccount(t *testing.T) {
for _, testCase := range testKeyCases {
acc, err := NewAccountFromWIF(testCase.wif)
for _, testCase := range keytestcases.Arr {
acc, err := NewAccountFromWIF(testCase.Wif)
if err != nil {
t.Fatal(err)
}
@ -16,8 +18,8 @@ func TestNewAccount(t *testing.T) {
}
func TestDecryptAccount(t *testing.T) {
for _, testCase := range testKeyCases {
acc, err := DecryptAccount(testCase.encryptedWif, testCase.passphrase)
for _, testCase := range keytestcases.Arr {
acc, err := DecryptAccount(testCase.EncryptedWif, testCase.Passphrase)
if err != nil {
t.Fatal(err)
}
@ -26,8 +28,8 @@ func TestDecryptAccount(t *testing.T) {
}
func TestNewFromWif(t *testing.T) {
for _, testCase := range testKeyCases {
acc, err := NewAccountFromWIF(testCase.wif)
for _, testCase := range keytestcases.Arr {
acc, err := NewAccountFromWIF(testCase.Wif)
if err != nil {
t.Fatal(err)
}
@ -35,17 +37,17 @@ func TestNewFromWif(t *testing.T) {
}
}
func compareFields(t *testing.T, tk testKey, acc *Account) {
if want, have := tk.address, acc.Address; want != have {
func compareFields(t *testing.T, tk keytestcases.Ktype, acc *Account) {
if want, have := tk.Address, acc.Address; want != have {
t.Fatalf("expected %s got %s", want, have)
}
if want, have := tk.wif, acc.wif; want != have {
if want, have := tk.Wif, acc.wif; want != have {
t.Fatalf("expected %s got %s", want, have)
}
if want, have := tk.publicKey, hex.EncodeToString(acc.publicKey); want != have {
if want, have := tk.PublicKey, hex.EncodeToString(acc.publicKey); want != have {
t.Fatalf("expected %s got %s", want, have)
}
if want, have := tk.privateKey, acc.privateKey.String(); want != have {
if want, have := tk.PrivateKey, acc.privateKey.String(); want != have {
t.Fatalf("expected %s got %s", want, have)
}
}

View file

@ -1,74 +0,0 @@
package wallet
import "testing"
type testKey struct {
address,
privateKey,
publicKey,
wif,
passphrase,
encryptedWif string
}
var testKeyCases = []testKey{
{
address: "ALq7AWrhAueN6mJNqk6FHJjnsEoPRytLdW",
privateKey: "7d128a6d096f0c14c3a25a2b0c41cf79661bfcb4a8cc95aaaea28bde4d732344",
publicKey: "02028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
wif: "L1QqQJnpBwbsPGAuutuzPTac8piqvbR1HRjrY5qHup48TBCBFe4g",
passphrase: "city of zion",
encryptedWif: "6PYLHmDf6AjF4AsVtosmxHuPYeuyJL3SLuw7J1U8i7HxKAnYNsp61HYRfF",
},
{
address: "ALfnhLg7rUyL6Jr98bzzoxz5J7m64fbR4s",
privateKey: "9ab7e154840daca3a2efadaf0df93cd3a5b51768c632f5433f86909d9b994a69",
publicKey: "031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
wif: "L2QTooFoDFyRFTxmtiVHt5CfsXfVnexdbENGDkkrrgTTryiLsPMG",
passphrase: "我的密码",
encryptedWif: "6PYWVp3xfgvnuNKP7ZavSViYvvim2zuzx9Q33vuWZr8aURiKeJ6Zm7BfPQ",
},
{
address: "AVf4UGKevVrMR1j3UkPsuoYKSC4ocoAkKx",
privateKey: "3edee7036b8fd9cef91de47386b191dd76db2888a553e7736bb02808932a915b",
publicKey: "02232ce8d2e2063dce0451131851d47421bfc4fc1da4db116fca5302c0756462fa",
wif: "KyKvWLZsNwBJx5j9nurHYRwhYfdQUu9tTEDsLCUHDbYBL8cHxMiG",
passphrase: "MyL33tP@33w0rd",
encryptedWif: "6PYNoc1EG5J38MTqGN9Anphfdd6UwbS4cpFCzHhrkSKBBbV1qkbJJZQnkn",
},
}
func TestPrivateKey(t *testing.T) {
for _, testCase := range testKeyCases {
privKey, err := NewPrivateKeyFromHex(testCase.privateKey)
if err != nil {
t.Fatal(err)
}
address, err := privKey.Address()
if err != nil {
t.Fatal(err)
}
if want, have := testCase.address, address; want != have {
t.Fatalf("expected %s got %s", want, have)
}
wif, err := privKey.WIF()
if err != nil {
t.Fatal(err)
}
if want, have := testCase.wif, wif; want != have {
t.Fatalf("expected %s got %s", want, have)
}
}
}
func TestPrivateKeyFromWIF(t *testing.T) {
for _, testCase := range testKeyCases {
key, err := NewPrivateKeyFromWIF(testCase.wif)
if err != nil {
t.Fatal(err)
}
if want, have := testCase.privateKey, key.String(); want != have {
t.Fatalf("expected %s got %s", want, have)
}
}
}

View file

@ -4,6 +4,8 @@ import (
"encoding/json"
"io"
"os"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
)
const (
@ -20,7 +22,7 @@ type Wallet struct {
// in the wallet.
Accounts []*Account `json:"accounts"`
Scrypt scryptParams `json:"scrypt"`
Scrypt keys.ScryptParams `json:"scrypt"`
// Extra metadata can be used for storing arbitrary data.
// This field can be empty.
@ -66,7 +68,7 @@ func newWallet(rw io.ReadWriter) *Wallet {
return &Wallet{
Version: walletVersion,
Accounts: []*Account{},
Scrypt: newScryptParams(),
Scrypt: keys.NEP2ScryptParams(),
rw: rw,
path: path,
}