2019-08-27 13:29:42 +00:00
|
|
|
package keys
|
2018-03-21 16:11:04 +00:00
|
|
|
|
|
|
|
import (
|
2020-07-13 09:59:41 +00:00
|
|
|
"crypto/elliptic"
|
2018-03-25 10:45:54 +00:00
|
|
|
"encoding/hex"
|
2020-03-18 14:11:19 +00:00
|
|
|
"encoding/json"
|
2019-11-24 15:40:07 +00:00
|
|
|
"math/rand"
|
2024-08-23 21:07:41 +00:00
|
|
|
"slices"
|
2019-11-24 15:40:07 +00:00
|
|
|
"sort"
|
2018-03-21 16:11:04 +00:00
|
|
|
"testing"
|
|
|
|
|
2020-11-23 11:09:00 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
2019-11-21 10:19:08 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2023-10-18 21:52:29 +00:00
|
|
|
"gopkg.in/yaml.v3"
|
2018-03-21 16:11:04 +00:00
|
|
|
)
|
|
|
|
|
2018-03-25 10:45:54 +00:00
|
|
|
func TestEncodeDecodeInfinity(t *testing.T) {
|
2019-09-04 21:12:39 +00:00
|
|
|
key := &PublicKey{}
|
2020-03-26 14:43:24 +00:00
|
|
|
b, err := testserdes.EncodeBinary(key)
|
|
|
|
require.NoError(t, err)
|
2019-11-21 10:19:08 +00:00
|
|
|
require.Equal(t, 1, len(b))
|
2018-03-25 10:45:54 +00:00
|
|
|
|
|
|
|
keyDecode := &PublicKey{}
|
2019-11-21 10:19:08 +00:00
|
|
|
require.NoError(t, keyDecode.DecodeBytes(b))
|
|
|
|
require.Equal(t, []byte{0x00}, keyDecode.Bytes())
|
2018-03-25 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
2018-03-21 16:11:04 +00:00
|
|
|
func TestEncodeDecodePublicKey(t *testing.T) {
|
2024-08-30 18:41:02 +00:00
|
|
|
for range 4 {
|
2019-09-04 20:03:25 +00:00
|
|
|
k, err := NewPrivateKey()
|
2019-11-21 10:19:08 +00:00
|
|
|
require.NoError(t, err)
|
2019-09-05 06:35:02 +00:00
|
|
|
p := k.PublicKey()
|
2020-03-26 14:43:24 +00:00
|
|
|
testserdes.EncodeDecodeBinary(t, p, new(PublicKey))
|
2018-03-21 16:11:04 +00:00
|
|
|
}
|
2019-11-24 15:40:07 +00:00
|
|
|
|
|
|
|
errCases := [][]byte{{}, {0x02}, {0x04}}
|
|
|
|
|
|
|
|
for _, tc := range errCases {
|
2020-03-26 14:43:24 +00:00
|
|
|
require.Error(t, testserdes.DecodeBinary(tc, new(PublicKey)))
|
2019-11-24 15:40:07 +00:00
|
|
|
}
|
2018-03-21 16:11:04 +00:00
|
|
|
}
|
2018-03-25 10:45:54 +00:00
|
|
|
|
2020-06-29 07:44:31 +00:00
|
|
|
func TestPublicKeys_Copy(t *testing.T) {
|
2024-04-27 09:18:48 +00:00
|
|
|
require.Nil(t, (PublicKeys)(nil).Copy())
|
|
|
|
|
2024-04-27 18:36:17 +00:00
|
|
|
pubz := make([]*PublicKey, 5)
|
|
|
|
for i := range pubz {
|
2020-06-29 07:44:31 +00:00
|
|
|
priv, err := NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
2024-04-27 18:36:17 +00:00
|
|
|
pubz[i] = priv.PublicKey()
|
2020-06-29 07:44:31 +00:00
|
|
|
}
|
2024-04-27 18:36:17 +00:00
|
|
|
pubs := PublicKeys(pubz)
|
2020-06-29 07:44:31 +00:00
|
|
|
|
|
|
|
cp := pubs.Copy()
|
2024-04-27 18:36:17 +00:00
|
|
|
var pubx = ([]*PublicKey)(cp)
|
|
|
|
require.Equal(t, pubz, pubx)
|
|
|
|
|
2020-06-29 07:44:31 +00:00
|
|
|
priv, err := NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
cp[0] = priv.PublicKey()
|
|
|
|
|
|
|
|
require.NotEqual(t, pubs[0], cp[0])
|
|
|
|
require.Equal(t, pubs[1:], cp[1:])
|
|
|
|
}
|
|
|
|
|
2020-04-07 07:55:56 +00:00
|
|
|
func TestNewPublicKeyFromBytes(t *testing.T) {
|
|
|
|
priv, err := NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
b := priv.PublicKey().Bytes()
|
2020-07-13 09:59:41 +00:00
|
|
|
pub, err := NewPublicKeyFromBytes(b, elliptic.P256())
|
2020-04-07 07:55:56 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, priv.PublicKey(), pub)
|
2020-08-29 19:37:31 +00:00
|
|
|
// Test cached access
|
|
|
|
pub2, err := NewPublicKeyFromBytes(b, elliptic.P256())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Same(t, pub, pub2)
|
2021-08-13 07:37:24 +00:00
|
|
|
|
|
|
|
_, err = NewPublicKeyFromBytes([]byte{0x00, 0x01}, elliptic.P256())
|
|
|
|
require.Error(t, err)
|
2020-04-07 07:55:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-25 10:45:54 +00:00
|
|
|
func TestDecodeFromString(t *testing.T) {
|
|
|
|
str := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
|
|
|
pubKey, err := NewPublicKeyFromString(str)
|
2019-11-21 10:19:08 +00:00
|
|
|
require.NoError(t, err)
|
2024-04-09 09:13:43 +00:00
|
|
|
require.Equal(t, str, pubKey.StringCompressed())
|
2019-11-24 15:40:07 +00:00
|
|
|
|
|
|
|
_, err = NewPublicKeyFromString(str[2:])
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
str = "zzb209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
|
|
|
_, err = NewPublicKeyFromString(str)
|
|
|
|
require.Error(t, err)
|
2018-03-25 10:45:54 +00:00
|
|
|
}
|
2019-08-27 13:29:42 +00:00
|
|
|
|
2019-12-25 14:44:30 +00:00
|
|
|
func TestDecodeFromStringBadCompressed(t *testing.T) {
|
|
|
|
str := "02ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
|
|
|
_, err := NewPublicKeyFromString(str)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2019-12-25 15:01:54 +00:00
|
|
|
func TestDecodeFromStringBadXMoreThanP(t *testing.T) {
|
|
|
|
str := "02ffffffff00000001000000000000000000000001ffffffffffffffffffffffff"
|
|
|
|
_, err := NewPublicKeyFromString(str)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2019-12-25 15:00:25 +00:00
|
|
|
func TestDecodeFromStringNotOnCurve(t *testing.T) {
|
|
|
|
str := "04ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
|
|
|
_, err := NewPublicKeyFromString(str)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
2019-12-25 15:06:25 +00:00
|
|
|
func TestDecodeFromStringUncompressed(t *testing.T) {
|
|
|
|
str := "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
|
|
|
|
_, err := NewPublicKeyFromString(str)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2019-08-27 13:29:42 +00:00
|
|
|
func TestPubkeyToAddress(t *testing.T) {
|
|
|
|
pubKey, err := NewPublicKeyFromString("031ee4e73a17d8f76dc02532e2620bcb12425b33c0c9f9694cc2caa8226b68cad4")
|
2019-11-21 10:19:08 +00:00
|
|
|
require.NoError(t, err)
|
2019-08-27 14:16:33 +00:00
|
|
|
actual := pubKey.Address()
|
2021-05-11 13:32:09 +00:00
|
|
|
expected := "NdxG5MZQy8h2qseawfSt8tTYG2iQPTwsn9"
|
2019-11-21 10:19:08 +00:00
|
|
|
require.Equal(t, expected, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDecodeBytes(t *testing.T) {
|
|
|
|
pubKey := getPubKey(t)
|
2020-06-10 16:14:13 +00:00
|
|
|
var testBytesFunction = func(t *testing.T, bytesFunction func() []byte) {
|
|
|
|
decodedPubKey := &PublicKey{}
|
|
|
|
err := decodedPubKey.DecodeBytes(bytesFunction())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, pubKey, decodedPubKey)
|
|
|
|
}
|
|
|
|
t.Run("compressed", func(t *testing.T) { testBytesFunction(t, pubKey.Bytes) })
|
|
|
|
t.Run("uncompressed", func(t *testing.T) { testBytesFunction(t, pubKey.UncompressedBytes) })
|
2019-11-21 10:19:08 +00:00
|
|
|
}
|
|
|
|
|
2019-11-24 15:40:07 +00:00
|
|
|
func TestSort(t *testing.T) {
|
|
|
|
pubs1 := make(PublicKeys, 10)
|
|
|
|
for i := range pubs1 {
|
|
|
|
priv, err := NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
pubs1[i] = priv.PublicKey()
|
|
|
|
}
|
|
|
|
|
2024-08-23 21:07:41 +00:00
|
|
|
pubs2 := slices.Clone(pubs1)
|
2019-11-24 15:40:07 +00:00
|
|
|
|
|
|
|
sort.Sort(pubs1)
|
|
|
|
|
|
|
|
rand.Shuffle(len(pubs2), func(i, j int) {
|
|
|
|
pubs2[i], pubs2[j] = pubs2[j], pubs2[i]
|
|
|
|
})
|
|
|
|
sort.Sort(pubs2)
|
|
|
|
|
|
|
|
// Check that sort on the same set of values produce the same result.
|
|
|
|
require.Equal(t, pubs1, pubs2)
|
|
|
|
}
|
|
|
|
|
2019-11-21 10:19:08 +00:00
|
|
|
func TestContains(t *testing.T) {
|
|
|
|
pubKey := getPubKey(t)
|
|
|
|
pubKeys := &PublicKeys{getPubKey(t)}
|
|
|
|
pubKeys.Contains(pubKey)
|
|
|
|
require.True(t, pubKeys.Contains(pubKey))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnique(t *testing.T) {
|
|
|
|
pubKeys := &PublicKeys{getPubKey(t), getPubKey(t)}
|
|
|
|
unique := pubKeys.Unique()
|
|
|
|
require.Equal(t, 1, unique.Len())
|
|
|
|
}
|
|
|
|
|
2021-08-25 12:18:26 +00:00
|
|
|
func getPubKey(t testing.TB) *PublicKey {
|
2019-11-21 10:19:08 +00:00
|
|
|
pubKey, err := NewPublicKeyFromString("031ee4e73a17d8f76dc02532e2620bcb12425b33c0c9f9694cc2caa8226b68cad4")
|
|
|
|
require.NoError(t, err)
|
|
|
|
return pubKey
|
2019-08-27 13:29:42 +00:00
|
|
|
}
|
2020-03-18 14:11:19 +00:00
|
|
|
|
|
|
|
func TestMarshallJSON(t *testing.T) {
|
|
|
|
str := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
|
|
|
pubKey, err := NewPublicKeyFromString(str)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
bytes, err := json.Marshal(&pubKey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, []byte(`"`+str+`"`), bytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshallJSON(t *testing.T) {
|
|
|
|
str := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
|
|
|
expected, err := NewPublicKeyFromString(str)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
actual := &PublicKey{}
|
|
|
|
err = json.Unmarshal([]byte(`"`+str+`"`), actual)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, expected, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshallJSONBadCompresed(t *testing.T) {
|
|
|
|
str := `"02ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`
|
|
|
|
actual := &PublicKey{}
|
|
|
|
err := json.Unmarshal([]byte(str), actual)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshallJSONNotAHex(t *testing.T) {
|
|
|
|
str := `"04Tb17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"`
|
|
|
|
actual := &PublicKey{}
|
|
|
|
err := json.Unmarshal([]byte(str), actual)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshallJSONBadFormat(t *testing.T) {
|
|
|
|
str := "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
|
|
|
|
actual := &PublicKey{}
|
|
|
|
err := json.Unmarshal([]byte(str), actual)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
2021-08-25 12:18:26 +00:00
|
|
|
|
|
|
|
func BenchmarkPublicEqual(t *testing.B) {
|
|
|
|
k11 := getPubKey(t)
|
|
|
|
k12 := getPubKey(t)
|
|
|
|
k2, err := NewPublicKeyFromString("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c")
|
|
|
|
require.NoError(t, err)
|
2024-08-30 18:41:02 +00:00
|
|
|
for range t.N {
|
2021-08-25 12:18:26 +00:00
|
|
|
_ = k11.Equal(k12)
|
|
|
|
_ = k11.Equal(k2)
|
|
|
|
}
|
|
|
|
}
|
2021-08-25 12:43:08 +00:00
|
|
|
|
|
|
|
func BenchmarkPublicBytes(t *testing.B) {
|
|
|
|
k := getPubKey(t)
|
2024-08-30 18:41:02 +00:00
|
|
|
for range t.N {
|
2021-08-25 12:43:08 +00:00
|
|
|
_ = k.Bytes()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkPublicUncompressedBytes(t *testing.B) {
|
|
|
|
k := getPubKey(t)
|
2024-08-30 18:41:02 +00:00
|
|
|
for range t.N {
|
2021-08-25 12:43:08 +00:00
|
|
|
_ = k.Bytes()
|
|
|
|
}
|
|
|
|
}
|
2021-08-25 16:19:33 +00:00
|
|
|
|
|
|
|
func BenchmarkPublicDecodeBytes(t *testing.B) {
|
|
|
|
keyBytes, err := hex.DecodeString("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c")
|
|
|
|
require.NoError(t, err)
|
|
|
|
k := new(PublicKey)
|
2024-08-30 18:41:02 +00:00
|
|
|
for range t.N {
|
2021-08-25 16:19:33 +00:00
|
|
|
require.NoError(t, k.DecodeBytes(keyBytes))
|
|
|
|
}
|
|
|
|
}
|
2023-10-18 21:52:29 +00:00
|
|
|
|
|
|
|
func TestMarshallYAML(t *testing.T) {
|
|
|
|
str := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
|
|
|
pubKey, err := NewPublicKeyFromString(str)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
bytes, err := yaml.Marshal(&pubKey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
expected := []byte(str + "\n") // YAML marshaller adds new line in the end which is expected.
|
|
|
|
require.Equal(t, expected, bytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshallYAML(t *testing.T) {
|
|
|
|
str := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
|
|
|
expected, err := NewPublicKeyFromString(str)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
actual := &PublicKey{}
|
|
|
|
err = yaml.Unmarshal([]byte(str), actual)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, expected, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshallYAMLBadCompresed(t *testing.T) {
|
|
|
|
str := `"02ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`
|
|
|
|
actual := &PublicKey{}
|
|
|
|
err := yaml.Unmarshal([]byte(str), actual)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Contains(t, err.Error(), "error computing Y for compressed point")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshallYAMLNotAHex(t *testing.T) {
|
|
|
|
str := `"04Tb17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"`
|
|
|
|
actual := &PublicKey{}
|
|
|
|
err := yaml.Unmarshal([]byte(str), actual)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Contains(t, err.Error(), "failed to decode public key from hex bytes")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshallYAMLUncompressed(t *testing.T) {
|
|
|
|
str := "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
|
|
|
|
expected, err := NewPublicKeyFromString(str)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
actual := &PublicKey{}
|
|
|
|
err = yaml.Unmarshal([]byte(str), actual)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, expected, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarshalUnmarshalYAML(t *testing.T) {
|
|
|
|
str := "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"
|
|
|
|
expected, err := NewPublicKeyFromString(str)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
testserdes.MarshalUnmarshalYAML(t, expected, new(PublicKey))
|
|
|
|
}
|