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