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