|
|
|
@ -31,13 +31,18 @@ package ecies
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"crypto/ecdsa"
|
|
|
|
|
"crypto/elliptic"
|
|
|
|
|
"crypto/rand"
|
|
|
|
|
"crypto/sha256"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"math/big"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var dumpEnc bool
|
|
|
|
@ -65,7 +70,6 @@ func TestKDF(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var skLen int
|
|
|
|
|
var ErrBadSharedKeys = fmt.Errorf("ecies: shared keys don't match")
|
|
|
|
|
|
|
|
|
|
// cmpParams compares a set of ECIES parameters. We assume, as per the
|
|
|
|
@ -117,7 +121,7 @@ func TestSharedKey(t *testing.T) {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
t.FailNow()
|
|
|
|
|
}
|
|
|
|
|
skLen = MaxSharedKeyLength(&prv1.PublicKey) / 2
|
|
|
|
|
skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2
|
|
|
|
|
|
|
|
|
|
prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
@ -143,6 +147,44 @@ func TestSharedKey(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSharedKeyPadding(t *testing.T) {
|
|
|
|
|
// sanity checks
|
|
|
|
|
prv0 := hexKey("1adf5c18167d96a1f9a0b1ef63be8aa27eaf6032c233b2b38f7850cf5b859fd9")
|
|
|
|
|
prv1 := hexKey("97a076fc7fcd9208240668e31c9abee952cbb6e375d1b8febc7499d6e16f1a")
|
|
|
|
|
x0, _ := new(big.Int).SetString("1a8ed022ff7aec59dc1b440446bdda5ff6bcb3509a8b109077282b361efffbd8", 16)
|
|
|
|
|
x1, _ := new(big.Int).SetString("6ab3ac374251f638d0abb3ef596d1dc67955b507c104e5f2009724812dc027b8", 16)
|
|
|
|
|
y0, _ := new(big.Int).SetString("e040bd480b1deccc3bc40bd5b1fdcb7bfd352500b477cb9471366dbd4493f923", 16)
|
|
|
|
|
y1, _ := new(big.Int).SetString("8ad915f2b503a8be6facab6588731fefeb584fd2dfa9a77a5e0bba1ec439e4fa", 16)
|
|
|
|
|
|
|
|
|
|
if prv0.PublicKey.X.Cmp(x0) != 0 {
|
|
|
|
|
t.Errorf("mismatched prv0.X:\nhave: %x\nwant: %x\n", prv0.PublicKey.X.Bytes(), x0.Bytes())
|
|
|
|
|
}
|
|
|
|
|
if prv0.PublicKey.Y.Cmp(y0) != 0 {
|
|
|
|
|
t.Errorf("mismatched prv0.Y:\nhave: %x\nwant: %x\n", prv0.PublicKey.Y.Bytes(), y0.Bytes())
|
|
|
|
|
}
|
|
|
|
|
if prv1.PublicKey.X.Cmp(x1) != 0 {
|
|
|
|
|
t.Errorf("mismatched prv1.X:\nhave: %x\nwant: %x\n", prv1.PublicKey.X.Bytes(), x1.Bytes())
|
|
|
|
|
}
|
|
|
|
|
if prv1.PublicKey.Y.Cmp(y1) != 0 {
|
|
|
|
|
t.Errorf("mismatched prv1.Y:\nhave: %x\nwant: %x\n", prv1.PublicKey.Y.Bytes(), y1.Bytes())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// test shared secret generation
|
|
|
|
|
sk1, err := prv0.GenerateShared(&prv1.PublicKey, 16, 16)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sk2, err := prv1.GenerateShared(&prv0.PublicKey, 16, 16)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !bytes.Equal(sk1, sk2) {
|
|
|
|
|
t.Fatal(ErrBadSharedKeys.Error())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Verify that the key generation code fails when too much key data is
|
|
|
|
|
// requested.
|
|
|
|
|
func TestTooBigSharedKey(t *testing.T) {
|
|
|
|
@ -158,13 +200,13 @@ func TestTooBigSharedKey(t *testing.T) {
|
|
|
|
|
t.FailNow()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err = prv1.GenerateShared(&prv2.PublicKey, skLen*2, skLen*2)
|
|
|
|
|
_, err = prv1.GenerateShared(&prv2.PublicKey, 32, 32)
|
|
|
|
|
if err != ErrSharedKeyTooBig {
|
|
|
|
|
fmt.Println("ecdh: shared key should be too large for curve")
|
|
|
|
|
t.FailNow()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err = prv2.GenerateShared(&prv1.PublicKey, skLen*2, skLen*2)
|
|
|
|
|
_, err = prv2.GenerateShared(&prv1.PublicKey, 32, 32)
|
|
|
|
|
if err != ErrSharedKeyTooBig {
|
|
|
|
|
fmt.Println("ecdh: shared key should be too large for curve")
|
|
|
|
|
t.FailNow()
|
|
|
|
@ -176,25 +218,21 @@ func TestTooBigSharedKey(t *testing.T) {
|
|
|
|
|
func TestMarshalPublic(t *testing.T) {
|
|
|
|
|
prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
t.FailNow()
|
|
|
|
|
t.Fatalf("GenerateKey error: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out, err := MarshalPublic(&prv.PublicKey)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
t.FailNow()
|
|
|
|
|
t.Fatalf("MarshalPublic error: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub, err := UnmarshalPublic(out)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
t.FailNow()
|
|
|
|
|
t.Fatalf("UnmarshalPublic error: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !cmpPublic(prv.PublicKey, *pub) {
|
|
|
|
|
fmt.Println("ecies: failed to unmarshal public key")
|
|
|
|
|
t.FailNow()
|
|
|
|
|
t.Fatal("ecies: failed to unmarshal public key")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -304,9 +342,26 @@ func BenchmarkGenSharedKeyP256(b *testing.B) {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
b.FailNow()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
_, err := prv.GenerateShared(&prv.PublicKey, skLen, skLen)
|
|
|
|
|
_, err := prv.GenerateShared(&prv.PublicKey, 16, 16)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
b.FailNow()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Benchmark the generation of S256 shared keys.
|
|
|
|
|
func BenchmarkGenSharedKeyS256(b *testing.B) {
|
|
|
|
|
prv, err := GenerateKey(rand.Reader, secp256k1.S256(), nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
b.FailNow()
|
|
|
|
|
}
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
|
_, err := prv.GenerateShared(&prv.PublicKey, 16, 16)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
b.FailNow()
|
|
|
|
@ -511,3 +566,43 @@ func TestBasicKeyValidation(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Verify GenerateShared against static values - useful when
|
|
|
|
|
// debugging changes in underlying libs
|
|
|
|
|
func TestSharedKeyStatic(t *testing.T) {
|
|
|
|
|
prv1 := hexKey("7ebbc6a8358bc76dd73ebc557056702c8cfc34e5cfcd90eb83af0347575fd2ad")
|
|
|
|
|
prv2 := hexKey("6a3d6396903245bba5837752b9e0348874e72db0c4e11e9c485a81b4ea4353b9")
|
|
|
|
|
|
|
|
|
|
skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2
|
|
|
|
|
|
|
|
|
|
sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
t.FailNow()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err.Error())
|
|
|
|
|
t.FailNow()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !bytes.Equal(sk1, sk2) {
|
|
|
|
|
fmt.Println(ErrBadSharedKeys.Error())
|
|
|
|
|
t.FailNow()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sk, _ := hex.DecodeString("167ccc13ac5e8a26b131c3446030c60fbfac6aa8e31149d0869f93626a4cdf62")
|
|
|
|
|
if !bytes.Equal(sk1, sk) {
|
|
|
|
|
t.Fatalf("shared secret mismatch: want: %x have: %x", sk, sk1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: remove after refactoring packages crypto and crypto/ecies
|
|
|
|
|
func hexKey(prv string) *PrivateKey {
|
|
|
|
|
priv := new(ecdsa.PrivateKey)
|
|
|
|
|
priv.PublicKey.Curve = secp256k1.S256()
|
|
|
|
|
priv.D, _ = new(big.Int).SetString(prv, 16)
|
|
|
|
|
priv.PublicKey.X, priv.PublicKey.Y = secp256k1.S256().ScalarBaseMult(priv.D.Bytes())
|
|
|
|
|
return ImportECDSA(priv)
|
|
|
|
|
}
|
|
|
|
|