github.com/dominant-strategies/go-quai@v0.28.2/crypto/crypto_test.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package crypto
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/ecdsa"
    22  	"encoding/hex"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"os"
    26  	"reflect"
    27  	"testing"
    28  
    29  	"github.com/dominant-strategies/go-quai/common"
    30  	"github.com/dominant-strategies/go-quai/common/hexutil"
    31  )
    32  
    33  var testAddrHex = "970e8128ab834e8eac17ab8e3812f010678cf791"
    34  var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
    35  
    36  // These tests are sanity checks.
    37  // They should ensure that we don't e.g. use Sha3-224 instead of Sha3-256
    38  // and that the sha3 library uses keccak-f permutation.
    39  func TestKeccak256Hash(t *testing.T) {
    40  	msg := []byte("abc")
    41  	exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
    42  	checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Keccak256Hash(in); return h[:] }, msg, exp)
    43  }
    44  
    45  func TestKeccak256Hasher(t *testing.T) {
    46  	msg := []byte("abc")
    47  	exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
    48  	hasher := NewKeccakState()
    49  	checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := HashData(hasher, in); return h[:] }, msg, exp)
    50  }
    51  
    52  func TestToECDSAErrors(t *testing.T) {
    53  	if _, err := HexToECDSA("0000000000000000000000000000000000000000000000000000000000000000"); err == nil {
    54  		t.Fatal("HexToECDSA should've returned error")
    55  	}
    56  	if _, err := HexToECDSA("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); err == nil {
    57  		t.Fatal("HexToECDSA should've returned error")
    58  	}
    59  }
    60  
    61  func BenchmarkSha3(b *testing.B) {
    62  	a := []byte("hello world")
    63  	for i := 0; i < b.N; i++ {
    64  		Keccak256(a)
    65  	}
    66  }
    67  
    68  func TestUnmarshalPubkey(t *testing.T) {
    69  	key, err := UnmarshalPubkey(nil)
    70  	if err != errInvalidPubkey || key != nil {
    71  		t.Fatalf("expected error, got %v, %v", err, key)
    72  	}
    73  	key, err = UnmarshalPubkey([]byte{1, 2, 3})
    74  	if err != errInvalidPubkey || key != nil {
    75  		t.Fatalf("expected error, got %v, %v", err, key)
    76  	}
    77  
    78  	var (
    79  		enc, _ = hex.DecodeString("04760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1b01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d")
    80  		dec    = &ecdsa.PublicKey{
    81  			Curve: S256(),
    82  			X:     hexutil.MustDecodeBig("0x760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1"),
    83  			Y:     hexutil.MustDecodeBig("0xb01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d"),
    84  		}
    85  	)
    86  	key, err = UnmarshalPubkey(enc)
    87  	if err != nil {
    88  		t.Fatalf("expected no error, got %v", err)
    89  	}
    90  	if !reflect.DeepEqual(key, dec) {
    91  		t.Fatal("wrong result")
    92  	}
    93  }
    94  
    95  func TestSign(t *testing.T) {
    96  	key, _ := HexToECDSA(testPrivHex)
    97  	addr := common.HexToAddress(testAddrHex)
    98  
    99  	msg := Keccak256([]byte("foo"))
   100  	sig, err := Sign(msg, key)
   101  	if err != nil {
   102  		t.Errorf("Sign error: %s", err)
   103  	}
   104  	recoveredPub, err := Ecrecover(msg, sig)
   105  	if err != nil {
   106  		t.Errorf("ECRecover error: %s", err)
   107  	}
   108  	pubKey, _ := UnmarshalPubkey(recoveredPub)
   109  	recoveredAddr := PubkeyToAddress(*pubKey)
   110  	if !addr.Equal(recoveredAddr) {
   111  		t.Errorf("Address mismatch: want: %x have: %x", addr, recoveredAddr)
   112  	}
   113  
   114  	// should be equal to SigToPub
   115  	recoveredPub2, err := SigToPub(msg, sig)
   116  	if err != nil {
   117  		t.Errorf("ECRecover error: %s", err)
   118  	}
   119  	recoveredAddr2 := PubkeyToAddress(*recoveredPub2)
   120  	if !addr.Equal(recoveredAddr2) {
   121  		t.Errorf("Address mismatch: want: %x have: %x", addr, recoveredAddr2)
   122  	}
   123  }
   124  
   125  func TestInvalidSign(t *testing.T) {
   126  	if _, err := Sign(make([]byte, 1), nil); err == nil {
   127  		t.Errorf("expected sign with hash 1 byte to error")
   128  	}
   129  	if _, err := Sign(make([]byte, 33), nil); err == nil {
   130  		t.Errorf("expected sign with hash 33 byte to error")
   131  	}
   132  }
   133  
   134  func TestNewContractAddress(t *testing.T) {
   135  	key, _ := HexToECDSA(testPrivHex)
   136  	addr := common.HexToAddress(testAddrHex)
   137  	genAddr := PubkeyToAddress(key.PublicKey)
   138  	// sanity check before using addr to create contract address
   139  	checkAddr(t, genAddr, addr)
   140  
   141  	caddr0 := CreateAddress(addr, 0, []byte{})
   142  	caddr1 := CreateAddress(addr, 1, []byte{})
   143  	caddr2 := CreateAddress(addr, 2, []byte{})
   144  
   145  	checkAddr(t, common.HexToAddress("30263b910ca0cbef50074e481948ae8f874c572c"), caddr0)
   146  	checkAddr(t, common.HexToAddress("70d2bda1ce21c19581734aa7e4b09e5b103b2fbb"), caddr1)
   147  	checkAddr(t, common.HexToAddress("d2e000cd536ab443658780b4bafc9cd37bd19e72"), caddr2)
   148  }
   149  
   150  func TestLoadECDSA(t *testing.T) {
   151  	tests := []struct {
   152  		input string
   153  		err   string
   154  	}{
   155  		// good
   156  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"},
   157  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n"},
   158  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\r"},
   159  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n"},
   160  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\n"},
   161  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\r"},
   162  		// bad
   163  		{
   164  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde",
   165  			err:   "key file too short, want 64 hex characters",
   166  		},
   167  		{
   168  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde\n",
   169  			err:   "key file too short, want 64 hex characters",
   170  		},
   171  		{
   172  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdeX",
   173  			err:   "invalid hex character 'X' in private key",
   174  		},
   175  		{
   176  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefX",
   177  			err:   "invalid character 'X' at end of key file",
   178  		},
   179  		{
   180  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\n\n",
   181  			err:   "key file too long, want 64 hex characters",
   182  		},
   183  	}
   184  
   185  	for _, test := range tests {
   186  		f, err := ioutil.TempFile("", "loadecdsa_test.*.txt")
   187  		if err != nil {
   188  			t.Fatal(err)
   189  		}
   190  		filename := f.Name()
   191  		f.WriteString(test.input)
   192  		f.Close()
   193  
   194  		_, err = LoadECDSA(filename)
   195  		switch {
   196  		case err != nil && test.err == "":
   197  			t.Fatalf("unexpected error for input %q:\n  %v", test.input, err)
   198  		case err != nil && err.Error() != test.err:
   199  			t.Fatalf("wrong error for input %q:\n  %v", test.input, err)
   200  		case err == nil && test.err != "":
   201  			t.Fatalf("LoadECDSA did not return error for input %q", test.input)
   202  		}
   203  	}
   204  }
   205  
   206  func TestSaveECDSA(t *testing.T) {
   207  	f, err := ioutil.TempFile("", "saveecdsa_test.*.txt")
   208  	if err != nil {
   209  		t.Fatal(err)
   210  	}
   211  	file := f.Name()
   212  	f.Close()
   213  	defer os.Remove(file)
   214  
   215  	key, _ := HexToECDSA(testPrivHex)
   216  	if err := SaveECDSA(file, key); err != nil {
   217  		t.Fatal(err)
   218  	}
   219  	loaded, err := LoadECDSA(file)
   220  	if err != nil {
   221  		t.Fatal(err)
   222  	}
   223  	if !reflect.DeepEqual(key, loaded) {
   224  		t.Fatal("loaded key not equal to saved key")
   225  	}
   226  }
   227  
   228  func TestValidateSignatureValues(t *testing.T) {
   229  	check := func(expected bool, v byte, r, s *big.Int) {
   230  		if ValidateSignatureValues(v, r, s) != expected {
   231  			t.Errorf("mismatch for v: %d r: %d s: %d want: %v", v, r, s, expected)
   232  		}
   233  	}
   234  	minusOne := big.NewInt(-1)
   235  	one := common.Big1
   236  	zero := common.Big0
   237  	secp256k1nMinus1 := new(big.Int).Sub(secp256k1N, common.Big1)
   238  
   239  	// correct v,r,s
   240  	check(true, 0, one, one)
   241  	check(true, 1, one, one)
   242  	// incorrect v, correct r,s,
   243  	check(false, 2, one, one)
   244  	check(false, 3, one, one)
   245  
   246  	// incorrect v, combinations of incorrect/correct r,s at lower limit
   247  	check(false, 2, zero, zero)
   248  	check(false, 2, zero, one)
   249  	check(false, 2, one, zero)
   250  	check(false, 2, one, one)
   251  
   252  	// correct v for any combination of incorrect r,s
   253  	check(false, 0, zero, zero)
   254  	check(false, 0, zero, one)
   255  	check(false, 0, one, zero)
   256  
   257  	check(false, 1, zero, zero)
   258  	check(false, 1, zero, one)
   259  	check(false, 1, one, zero)
   260  
   261  	// correct sig with max r and s above upper limit
   262  	check(false, 0, secp256k1nMinus1, secp256k1nMinus1)
   263  	// correct v, combinations of incorrect r,s at upper limit
   264  	check(false, 0, secp256k1N, secp256k1nMinus1)
   265  	check(false, 0, secp256k1nMinus1, secp256k1N)
   266  	check(false, 0, secp256k1N, secp256k1N)
   267  
   268  	// current callers ensures r,s cannot be negative, but let's test for that too
   269  	// as crypto package could be used stand-alone
   270  	check(false, 0, minusOne, one)
   271  	check(false, 0, one, minusOne)
   272  }
   273  
   274  func checkhash(t *testing.T, name string, f func([]byte) []byte, msg, exp []byte) {
   275  	sum := f(msg)
   276  	if !bytes.Equal(exp, sum) {
   277  		t.Fatalf("hash %s mismatch: want: %x have: %x", name, exp, sum)
   278  	}
   279  }
   280  
   281  func checkAddr(t *testing.T, addr0, addr1 common.Address) {
   282  	if !addr0.Equal(addr1) {
   283  		t.Fatalf("address mismatch: want: %x have: %x", addr0, addr1)
   284  	}
   285  }
   286  
   287  // test to help Python team with integration of libsecp256k1
   288  // skip but keep it after they are done
   289  func TestPythonIntegration(t *testing.T) {
   290  	kh := "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
   291  	k0, _ := HexToECDSA(kh)
   292  
   293  	msg0 := Keccak256([]byte("foo"))
   294  	sig0, _ := Sign(msg0, k0)
   295  
   296  	msg1 := common.FromHex("00000000000000000000000000000000")
   297  	sig1, _ := Sign(msg0, k0)
   298  
   299  	t.Logf("msg: %x, privkey: %s sig: %x\n", msg0, kh, sig0)
   300  	t.Logf("msg: %x, privkey: %s sig: %x\n", msg1, kh, sig1)
   301  }