github.com/0xsequence/ethkit@v1.25.0/go-ethereum/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 "math/big" 24 "os" 25 "reflect" 26 "testing" 27 28 "github.com/0xsequence/ethkit/go-ethereum/common" 29 "github.com/0xsequence/ethkit/go-ethereum/common/hexutil" 30 ) 31 32 var testAddrHex = "970e8128ab834e8eac17ab8e3812f010678cf791" 33 var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032" 34 35 // These tests are sanity checks. 36 // They should ensure that we don't e.g. use Sha3-224 instead of Sha3-256 37 // and that the sha3 library uses keccak-f permutation. 38 func TestKeccak256Hash(t *testing.T) { 39 msg := []byte("abc") 40 exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45") 41 checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Keccak256Hash(in); return h[:] }, msg, exp) 42 } 43 44 func TestKeccak256Hasher(t *testing.T) { 45 msg := []byte("abc") 46 exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45") 47 hasher := NewKeccakState() 48 checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := HashData(hasher, in); return h[:] }, msg, exp) 49 } 50 51 func TestToECDSAErrors(t *testing.T) { 52 if _, err := HexToECDSA("0000000000000000000000000000000000000000000000000000000000000000"); err == nil { 53 t.Fatal("HexToECDSA should've returned error") 54 } 55 if _, err := HexToECDSA("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); err == nil { 56 t.Fatal("HexToECDSA should've returned error") 57 } 58 } 59 60 func BenchmarkSha3(b *testing.B) { 61 a := []byte("hello world") 62 for i := 0; i < b.N; i++ { 63 Keccak256(a) 64 } 65 } 66 67 func TestUnmarshalPubkey(t *testing.T) { 68 key, err := UnmarshalPubkey(nil) 69 if err != errInvalidPubkey || key != nil { 70 t.Fatalf("expected error, got %v, %v", err, key) 71 } 72 key, err = UnmarshalPubkey([]byte{1, 2, 3}) 73 if err != errInvalidPubkey || key != nil { 74 t.Fatalf("expected error, got %v, %v", err, key) 75 } 76 77 var ( 78 enc, _ = hex.DecodeString("04760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1b01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d") 79 dec = &ecdsa.PublicKey{ 80 Curve: S256(), 81 X: hexutil.MustDecodeBig("0x760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1"), 82 Y: hexutil.MustDecodeBig("0xb01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d"), 83 } 84 ) 85 key, err = UnmarshalPubkey(enc) 86 if err != nil { 87 t.Fatalf("expected no error, got %v", err) 88 } 89 if !reflect.DeepEqual(key, dec) { 90 t.Fatal("wrong result") 91 } 92 } 93 94 func TestSign(t *testing.T) { 95 key, _ := HexToECDSA(testPrivHex) 96 addr := common.HexToAddress(testAddrHex) 97 98 msg := Keccak256([]byte("foo")) 99 sig, err := Sign(msg, key) 100 if err != nil { 101 t.Errorf("Sign error: %s", err) 102 } 103 recoveredPub, err := Ecrecover(msg, sig) 104 if err != nil { 105 t.Errorf("ECRecover error: %s", err) 106 } 107 pubKey, _ := UnmarshalPubkey(recoveredPub) 108 recoveredAddr := PubkeyToAddress(*pubKey) 109 if addr != recoveredAddr { 110 t.Errorf("Address mismatch: want: %x have: %x", addr, recoveredAddr) 111 } 112 113 // should be equal to SigToPub 114 recoveredPub2, err := SigToPub(msg, sig) 115 if err != nil { 116 t.Errorf("ECRecover error: %s", err) 117 } 118 recoveredAddr2 := PubkeyToAddress(*recoveredPub2) 119 if addr != recoveredAddr2 { 120 t.Errorf("Address mismatch: want: %x have: %x", addr, recoveredAddr2) 121 } 122 } 123 124 func TestInvalidSign(t *testing.T) { 125 if _, err := Sign(make([]byte, 1), nil); err == nil { 126 t.Errorf("expected sign with hash 1 byte to error") 127 } 128 if _, err := Sign(make([]byte, 33), nil); err == nil { 129 t.Errorf("expected sign with hash 33 byte to error") 130 } 131 } 132 133 func TestNewContractAddress(t *testing.T) { 134 key, _ := HexToECDSA(testPrivHex) 135 addr := common.HexToAddress(testAddrHex) 136 genAddr := PubkeyToAddress(key.PublicKey) 137 // sanity check before using addr to create contract address 138 checkAddr(t, genAddr, addr) 139 140 caddr0 := CreateAddress(addr, 0) 141 caddr1 := CreateAddress(addr, 1) 142 caddr2 := CreateAddress(addr, 2) 143 checkAddr(t, common.HexToAddress("333c3310824b7c685133f2bedb2ca4b8b4df633d"), caddr0) 144 checkAddr(t, common.HexToAddress("8bda78331c916a08481428e4b07c96d3e916d165"), caddr1) 145 checkAddr(t, common.HexToAddress("c9ddedf451bc62ce88bf9292afb13df35b670699"), caddr2) 146 } 147 148 func TestLoadECDSA(t *testing.T) { 149 tests := []struct { 150 input string 151 err string 152 }{ 153 // good 154 {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, 155 {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n"}, 156 {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\r"}, 157 {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n"}, 158 {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\n"}, 159 {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\r"}, 160 // bad 161 { 162 input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde", 163 err: "key file too short, want 64 hex characters", 164 }, 165 { 166 input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde\n", 167 err: "key file too short, want 64 hex characters", 168 }, 169 { 170 input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdeX", 171 err: "invalid hex character 'X' in private key", 172 }, 173 { 174 input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefX", 175 err: "invalid character 'X' at end of key file", 176 }, 177 { 178 input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\n\n", 179 err: "key file too long, want 64 hex characters", 180 }, 181 } 182 183 for _, test := range tests { 184 f, err := os.CreateTemp("", "loadecdsa_test.*.txt") 185 if err != nil { 186 t.Fatal(err) 187 } 188 filename := f.Name() 189 f.WriteString(test.input) 190 f.Close() 191 192 _, err = LoadECDSA(filename) 193 switch { 194 case err != nil && test.err == "": 195 t.Fatalf("unexpected error for input %q:\n %v", test.input, err) 196 case err != nil && err.Error() != test.err: 197 t.Fatalf("wrong error for input %q:\n %v", test.input, err) 198 case err == nil && test.err != "": 199 t.Fatalf("LoadECDSA did not return error for input %q", test.input) 200 } 201 } 202 } 203 204 func TestSaveECDSA(t *testing.T) { 205 f, err := os.CreateTemp("", "saveecdsa_test.*.txt") 206 if err != nil { 207 t.Fatal(err) 208 } 209 file := f.Name() 210 f.Close() 211 defer os.Remove(file) 212 213 key, _ := HexToECDSA(testPrivHex) 214 if err := SaveECDSA(file, key); err != nil { 215 t.Fatal(err) 216 } 217 loaded, err := LoadECDSA(file) 218 if err != nil { 219 t.Fatal(err) 220 } 221 if !reflect.DeepEqual(key, loaded) { 222 t.Fatal("loaded key not equal to saved key") 223 } 224 } 225 226 func TestValidateSignatureValues(t *testing.T) { 227 check := func(expected bool, v byte, r, s *big.Int) { 228 if ValidateSignatureValues(v, r, s, false) != expected { 229 t.Errorf("mismatch for v: %d r: %d s: %d want: %v", v, r, s, expected) 230 } 231 } 232 minusOne := big.NewInt(-1) 233 one := common.Big1 234 zero := common.Big0 235 secp256k1nMinus1 := new(big.Int).Sub(secp256k1N, common.Big1) 236 237 // correct v,r,s 238 check(true, 0, one, one) 239 check(true, 1, one, one) 240 // incorrect v, correct r,s, 241 check(false, 2, one, one) 242 check(false, 3, one, one) 243 244 // incorrect v, combinations of incorrect/correct r,s at lower limit 245 check(false, 2, zero, zero) 246 check(false, 2, zero, one) 247 check(false, 2, one, zero) 248 check(false, 2, one, one) 249 250 // correct v for any combination of incorrect r,s 251 check(false, 0, zero, zero) 252 check(false, 0, zero, one) 253 check(false, 0, one, zero) 254 255 check(false, 1, zero, zero) 256 check(false, 1, zero, one) 257 check(false, 1, one, zero) 258 259 // correct sig with max r,s 260 check(true, 0, secp256k1nMinus1, secp256k1nMinus1) 261 // correct v, combinations of incorrect r,s at upper limit 262 check(false, 0, secp256k1N, secp256k1nMinus1) 263 check(false, 0, secp256k1nMinus1, secp256k1N) 264 check(false, 0, secp256k1N, secp256k1N) 265 266 // current callers ensures r,s cannot be negative, but let's test for that too 267 // as crypto package could be used stand-alone 268 check(false, 0, minusOne, one) 269 check(false, 0, one, minusOne) 270 } 271 272 func checkhash(t *testing.T, name string, f func([]byte) []byte, msg, exp []byte) { 273 sum := f(msg) 274 if !bytes.Equal(exp, sum) { 275 t.Fatalf("hash %s mismatch: want: %x have: %x", name, exp, sum) 276 } 277 } 278 279 func checkAddr(t *testing.T, addr0, addr1 common.Address) { 280 if addr0 != addr1 { 281 t.Fatalf("address mismatch: want: %x have: %x", addr0, addr1) 282 } 283 } 284 285 // test to help Python team with integration of libsecp256k1 286 // skip but keep it after they are done 287 func TestPythonIntegration(t *testing.T) { 288 kh := "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032" 289 k0, _ := HexToECDSA(kh) 290 291 msg0 := Keccak256([]byte("foo")) 292 sig0, _ := Sign(msg0, k0) 293 294 msg1 := common.FromHex("00000000000000000000000000000000") 295 sig1, _ := Sign(msg0, k0) 296 297 t.Logf("msg: %x, privkey: %s sig: %x\n", msg0, kh, sig0) 298 t.Logf("msg: %x, privkey: %s sig: %x\n", msg1, kh, sig1) 299 }