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