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