github.com/clem109/go-ethereum@v1.8.3-0.20180316121352-fe6cf00f480a/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  	"testing"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  )
    30  
    31  var testAddrHex = "970e8128ab834e8eac17ab8e3812f010678cf791"
    32  var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
    33  
    34  // These tests are sanity checks.
    35  // They should ensure that we don't e.g. use Sha3-224 instead of Sha3-256
    36  // and that the sha3 library uses keccak-f permutation.
    37  func TestKeccak256Hash(t *testing.T) {
    38  	msg := []byte("abc")
    39  	exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
    40  	checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Keccak256Hash(in); return h[:] }, msg, exp)
    41  }
    42  
    43  func TestToECDSAErrors(t *testing.T) {
    44  	if _, err := HexToECDSA("0000000000000000000000000000000000000000000000000000000000000000"); err == nil {
    45  		t.Fatal("HexToECDSA should've returned error")
    46  	}
    47  	if _, err := HexToECDSA("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); err == nil {
    48  		t.Fatal("HexToECDSA should've returned error")
    49  	}
    50  }
    51  
    52  func BenchmarkSha3(b *testing.B) {
    53  	a := []byte("hello world")
    54  	for i := 0; i < b.N; i++ {
    55  		Keccak256(a)
    56  	}
    57  }
    58  
    59  func TestSign(t *testing.T) {
    60  	key, _ := HexToECDSA(testPrivHex)
    61  	addr := common.HexToAddress(testAddrHex)
    62  
    63  	msg := Keccak256([]byte("foo"))
    64  	sig, err := Sign(msg, key)
    65  	if err != nil {
    66  		t.Errorf("Sign error: %s", err)
    67  	}
    68  	recoveredPub, err := Ecrecover(msg, sig)
    69  	if err != nil {
    70  		t.Errorf("ECRecover error: %s", err)
    71  	}
    72  	pubKey := ToECDSAPub(recoveredPub)
    73  	recoveredAddr := PubkeyToAddress(*pubKey)
    74  	if addr != recoveredAddr {
    75  		t.Errorf("Address mismatch: want: %x have: %x", addr, recoveredAddr)
    76  	}
    77  
    78  	// should be equal to SigToPub
    79  	recoveredPub2, err := SigToPub(msg, sig)
    80  	if err != nil {
    81  		t.Errorf("ECRecover error: %s", err)
    82  	}
    83  	recoveredAddr2 := PubkeyToAddress(*recoveredPub2)
    84  	if addr != recoveredAddr2 {
    85  		t.Errorf("Address mismatch: want: %x have: %x", addr, recoveredAddr2)
    86  	}
    87  }
    88  
    89  func TestInvalidSign(t *testing.T) {
    90  	if _, err := Sign(make([]byte, 1), nil); err == nil {
    91  		t.Errorf("expected sign with hash 1 byte to error")
    92  	}
    93  	if _, err := Sign(make([]byte, 33), nil); err == nil {
    94  		t.Errorf("expected sign with hash 33 byte to error")
    95  	}
    96  }
    97  
    98  func TestNewContractAddress(t *testing.T) {
    99  	key, _ := HexToECDSA(testPrivHex)
   100  	addr := common.HexToAddress(testAddrHex)
   101  	genAddr := PubkeyToAddress(key.PublicKey)
   102  	// sanity check before using addr to create contract address
   103  	checkAddr(t, genAddr, addr)
   104  
   105  	caddr0 := CreateAddress(addr, 0)
   106  	caddr1 := CreateAddress(addr, 1)
   107  	caddr2 := CreateAddress(addr, 2)
   108  	checkAddr(t, common.HexToAddress("333c3310824b7c685133f2bedb2ca4b8b4df633d"), caddr0)
   109  	checkAddr(t, common.HexToAddress("8bda78331c916a08481428e4b07c96d3e916d165"), caddr1)
   110  	checkAddr(t, common.HexToAddress("c9ddedf451bc62ce88bf9292afb13df35b670699"), caddr2)
   111  }
   112  
   113  func TestLoadECDSAFile(t *testing.T) {
   114  	keyBytes := common.FromHex(testPrivHex)
   115  	fileName0 := "test_key0"
   116  	fileName1 := "test_key1"
   117  	checkKey := func(k *ecdsa.PrivateKey) {
   118  		checkAddr(t, PubkeyToAddress(k.PublicKey), common.HexToAddress(testAddrHex))
   119  		loadedKeyBytes := FromECDSA(k)
   120  		if !bytes.Equal(loadedKeyBytes, keyBytes) {
   121  			t.Fatalf("private key mismatch: want: %x have: %x", keyBytes, loadedKeyBytes)
   122  		}
   123  	}
   124  
   125  	ioutil.WriteFile(fileName0, []byte(testPrivHex), 0600)
   126  	defer os.Remove(fileName0)
   127  
   128  	key0, err := LoadECDSA(fileName0)
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	checkKey(key0)
   133  
   134  	// again, this time with SaveECDSA instead of manual save:
   135  	err = SaveECDSA(fileName1, key0)
   136  	if err != nil {
   137  		t.Fatal(err)
   138  	}
   139  	defer os.Remove(fileName1)
   140  
   141  	key1, err := LoadECDSA(fileName1)
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  	checkKey(key1)
   146  }
   147  
   148  func TestValidateSignatureValues(t *testing.T) {
   149  	check := func(expected bool, v byte, r, s *big.Int) {
   150  		if ValidateSignatureValues(v, r, s, false) != expected {
   151  			t.Errorf("mismatch for v: %d r: %d s: %d want: %v", v, r, s, expected)
   152  		}
   153  	}
   154  	minusOne := big.NewInt(-1)
   155  	one := common.Big1
   156  	zero := common.Big0
   157  	secp256k1nMinus1 := new(big.Int).Sub(secp256k1_N, common.Big1)
   158  
   159  	// correct v,r,s
   160  	check(true, 0, one, one)
   161  	check(true, 1, one, one)
   162  	// incorrect v, correct r,s,
   163  	check(false, 2, one, one)
   164  	check(false, 3, one, one)
   165  
   166  	// incorrect v, combinations of incorrect/correct r,s at lower limit
   167  	check(false, 2, zero, zero)
   168  	check(false, 2, zero, one)
   169  	check(false, 2, one, zero)
   170  	check(false, 2, one, one)
   171  
   172  	// correct v for any combination of incorrect r,s
   173  	check(false, 0, zero, zero)
   174  	check(false, 0, zero, one)
   175  	check(false, 0, one, zero)
   176  
   177  	check(false, 1, zero, zero)
   178  	check(false, 1, zero, one)
   179  	check(false, 1, one, zero)
   180  
   181  	// correct sig with max r,s
   182  	check(true, 0, secp256k1nMinus1, secp256k1nMinus1)
   183  	// correct v, combinations of incorrect r,s at upper limit
   184  	check(false, 0, secp256k1_N, secp256k1nMinus1)
   185  	check(false, 0, secp256k1nMinus1, secp256k1_N)
   186  	check(false, 0, secp256k1_N, secp256k1_N)
   187  
   188  	// current callers ensures r,s cannot be negative, but let's test for that too
   189  	// as crypto package could be used stand-alone
   190  	check(false, 0, minusOne, one)
   191  	check(false, 0, one, minusOne)
   192  }
   193  
   194  func checkhash(t *testing.T, name string, f func([]byte) []byte, msg, exp []byte) {
   195  	sum := f(msg)
   196  	if !bytes.Equal(exp, sum) {
   197  		t.Fatalf("hash %s mismatch: want: %x have: %x", name, exp, sum)
   198  	}
   199  }
   200  
   201  func checkAddr(t *testing.T, addr0, addr1 common.Address) {
   202  	if addr0 != addr1 {
   203  		t.Fatalf("address mismatch: want: %x have: %x", addr0, addr1)
   204  	}
   205  }
   206  
   207  // test to help Python team with integration of libsecp256k1
   208  // skip but keep it after they are done
   209  func TestPythonIntegration(t *testing.T) {
   210  	kh := "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
   211  	k0, _ := HexToECDSA(kh)
   212  
   213  	msg0 := Keccak256([]byte("foo"))
   214  	sig0, _ := Sign(msg0, k0)
   215  
   216  	msg1 := common.FromHex("00000000000000000000000000000000")
   217  	sig1, _ := Sign(msg0, k0)
   218  
   219  	t.Logf("msg: %x, privkey: %s sig: %x\n", msg0, kh, sig0)
   220  	t.Logf("msg: %x, privkey: %s sig: %x\n", msg1, kh, sig1)
   221  }