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