github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/crypto/crypto_test.go (about)

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