github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/crypto/crypto_test.go (about)

     1  // Copyright 2021 The adkgo Authors
     2  // This file is part of the adkgo library (adapted for adkgo from go--ethereum v1.10.8).
     3  //
     4  // the adkgo 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 adkgo 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 adkgo 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/aidoskuneen/adk-node/common"
    30  	"github.com/aidoskuneen/adk-node/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 != 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 != 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)
   142  	caddr1 := CreateAddress(addr, 1)
   143  	caddr2 := CreateAddress(addr, 2)
   144  	checkAddr(t, common.HexToAddress("333c3310824b7c685133f2bedb2ca4b8b4df633d"), caddr0)
   145  	checkAddr(t, common.HexToAddress("8bda78331c916a08481428e4b07c96d3e916d165"), caddr1)
   146  	checkAddr(t, common.HexToAddress("c9ddedf451bc62ce88bf9292afb13df35b670699"), caddr2)
   147  }
   148  
   149  func TestLoadECDSA(t *testing.T) {
   150  	tests := []struct {
   151  		input string
   152  		err   string
   153  	}{
   154  		// good
   155  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"},
   156  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n"},
   157  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\r"},
   158  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n"},
   159  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\n"},
   160  		{input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\r"},
   161  		// bad
   162  		{
   163  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde",
   164  			err:   "key file too short, want 64 hex characters",
   165  		},
   166  		{
   167  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde\n",
   168  			err:   "key file too short, want 64 hex characters",
   169  		},
   170  		{
   171  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdeX",
   172  			err:   "invalid hex character 'X' in private key",
   173  		},
   174  		{
   175  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefX",
   176  			err:   "invalid character 'X' at end of key file",
   177  		},
   178  		{
   179  			input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\n\n",
   180  			err:   "key file too long, want 64 hex characters",
   181  		},
   182  	}
   183  
   184  	for _, test := range tests {
   185  		f, err := ioutil.TempFile("", "loadecdsa_test.*.txt")
   186  		if err != nil {
   187  			t.Fatal(err)
   188  		}
   189  		filename := f.Name()
   190  		f.WriteString(test.input)
   191  		f.Close()
   192  
   193  		_, err = LoadECDSA(filename)
   194  		switch {
   195  		case err != nil && test.err == "":
   196  			t.Fatalf("unexpected error for input %q:\n  %v", test.input, err)
   197  		case err != nil && err.Error() != test.err:
   198  			t.Fatalf("wrong error for input %q:\n  %v", test.input, err)
   199  		case err == nil && test.err != "":
   200  			t.Fatalf("LoadECDSA did not return error for input %q", test.input)
   201  		}
   202  	}
   203  }
   204  
   205  func TestSaveECDSA(t *testing.T) {
   206  	f, err := ioutil.TempFile("", "saveecdsa_test.*.txt")
   207  	if err != nil {
   208  		t.Fatal(err)
   209  	}
   210  	file := f.Name()
   211  	f.Close()
   212  	defer os.Remove(file)
   213  
   214  	key, _ := HexToECDSA(testPrivHex)
   215  	if err := SaveECDSA(file, key); err != nil {
   216  		t.Fatal(err)
   217  	}
   218  	loaded, err := LoadECDSA(file)
   219  	if err != nil {
   220  		t.Fatal(err)
   221  	}
   222  	if !reflect.DeepEqual(key, loaded) {
   223  		t.Fatal("loaded key not equal to saved key")
   224  	}
   225  }
   226  
   227  func TestValidateSignatureValues(t *testing.T) {
   228  	check := func(expected bool, v byte, r, s *big.Int) {
   229  		if ValidateSignatureValues(v, r, s, false) != expected {
   230  			t.Errorf("mismatch for v: %d r: %d s: %d want: %v", v, r, s, expected)
   231  		}
   232  	}
   233  	minusOne := big.NewInt(-1)
   234  	one := common.Big1
   235  	zero := common.Big0
   236  	secp256k1nMinus1 := new(big.Int).Sub(secp256k1N, common.Big1)
   237  
   238  	// correct v,r,s
   239  	check(true, 0, one, one)
   240  	check(true, 1, one, one)
   241  	// incorrect v, correct r,s,
   242  	check(false, 2, one, one)
   243  	check(false, 3, one, one)
   244  
   245  	// incorrect v, combinations of incorrect/correct r,s at lower limit
   246  	check(false, 2, zero, zero)
   247  	check(false, 2, zero, one)
   248  	check(false, 2, one, zero)
   249  	check(false, 2, one, one)
   250  
   251  	// correct v for any combination of incorrect r,s
   252  	check(false, 0, zero, zero)
   253  	check(false, 0, zero, one)
   254  	check(false, 0, one, zero)
   255  
   256  	check(false, 1, zero, zero)
   257  	check(false, 1, zero, one)
   258  	check(false, 1, one, zero)
   259  
   260  	// correct sig with max r,s
   261  	check(true, 0, secp256k1nMinus1, secp256k1nMinus1)
   262  	// correct v, combinations of incorrect r,s at upper limit
   263  	check(false, 0, secp256k1N, secp256k1nMinus1)
   264  	check(false, 0, secp256k1nMinus1, secp256k1N)
   265  	check(false, 0, secp256k1N, secp256k1N)
   266  
   267  	// current callers ensures r,s cannot be negative, but let's test for that too
   268  	// as crypto package could be used stand-alone
   269  	check(false, 0, minusOne, one)
   270  	check(false, 0, one, minusOne)
   271  }
   272  
   273  func checkhash(t *testing.T, name string, f func([]byte) []byte, msg, exp []byte) {
   274  	sum := f(msg)
   275  	if !bytes.Equal(exp, sum) {
   276  		t.Fatalf("hash %s mismatch: want: %x have: %x", name, exp, sum)
   277  	}
   278  }
   279  
   280  func checkAddr(t *testing.T, addr0, addr1 common.Address) {
   281  	if addr0 != addr1 {
   282  		t.Fatalf("address mismatch: want: %x have: %x", addr0, addr1)
   283  	}
   284  }
   285  
   286  // test to help Python team with integration of libsecp256k1
   287  // skip but keep it after they are done
   288  func TestPythonIntegration(t *testing.T) {
   289  	kh := "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
   290  	k0, _ := HexToECDSA(kh)
   291  
   292  	msg0 := Keccak256([]byte("foo"))
   293  	sig0, _ := Sign(msg0, k0)
   294  
   295  	msg1 := common.FromHex("00000000000000000000000000000000")
   296  	sig1, _ := Sign(msg0, k0)
   297  
   298  	t.Logf("msg: %x, privkey: %s sig: %x\n", msg0, kh, sig0)
   299  	t.Logf("msg: %x, privkey: %s sig: %x\n", msg1, kh, sig1)
   300  }