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 }