github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/accounts/keystore_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 accounts 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 "crypto/rand" 23 "encoding/hex" 24 "encoding/json" 25 "fmt" 26 "io/ioutil" 27 "os" 28 "reflect" 29 "strings" 30 "testing" 31 32 "github.com/ethereumproject/go-ethereum/common" 33 "github.com/ethereumproject/go-ethereum/crypto" 34 "github.com/ethereumproject/go-ethereum/crypto/secp256k1" 35 ) 36 37 func tmpKeyStore(t *testing.T) (dir string, ks *keyStore) { 38 dir, err := ioutil.TempDir("", "geth-keystore-test") 39 if err != nil { 40 t.Fatal(err) 41 } 42 43 store, err := newKeyStore(dir, veryLightScryptN, veryLightScryptP) 44 if err != nil { 45 t.Fatal(err) 46 } 47 48 return dir, store 49 } 50 51 func TestKeyStore(t *testing.T) { 52 dir, ks := tmpKeyStore(t) 53 defer os.RemoveAll(dir) 54 55 pass := "foo" 56 key, account, err := storeNewKey(ks, pass) 57 if err != nil { 58 t.Fatal(err) 59 } 60 61 got, err := ks.Lookup(account.File, pass) 62 if err != nil { 63 t.Fatal(err) 64 } 65 if !reflect.DeepEqual(got.Address, key.Address) { 66 t.Errorf("got address %x, want %x", got.Address, key.Address) 67 } 68 if !reflect.DeepEqual(key.PrivateKey, key.PrivateKey) { 69 t.Errorf("got private key %x, want %x", got.PrivateKey, key.PrivateKey) 70 } 71 } 72 73 func TestKeyStoreDecryptionFail(t *testing.T) { 74 dir, ks := tmpKeyStore(t) 75 defer os.RemoveAll(dir) 76 77 pass := "foo" 78 _, account, err := storeNewKey(ks, pass) 79 if err != nil { 80 t.Fatal(err) 81 } 82 if _, err = ks.Lookup(account.File, "bar"); err != ErrDecrypt { 83 t.Fatalf("wrong error for invalid passphrase\ngot %q\nwant %q", err, ErrDecrypt) 84 } 85 } 86 87 func TestImportPreSaleKey(t *testing.T) { 88 dir, ks := tmpKeyStore(t) 89 defer os.RemoveAll(dir) 90 91 // file content of a presale key file generated with: 92 // python pyethsaletool.py genwallet 93 // with password "foo" 94 fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}" 95 pass := "foo" 96 account, _, err := importPreSaleKey(ks, []byte(fileContent), pass) 97 if err != nil { 98 t.Fatal(err) 99 } 100 if account.Address != common.HexToAddress("d4584b5f6229b7be90727b0fc8c6b91bb427821f") { 101 t.Errorf("imported account has wrong address %x", account.Address) 102 } 103 if !strings.HasPrefix(account.File, dir) { 104 t.Errorf("imported account file not in keystore directory: %q", account.File) 105 } 106 } 107 108 // Test and utils for the key store tests in the Ethereum JSON tests; 109 // testdataKeyStoreTests/basic_tests.json 110 type KeyStoreTestV3 struct { 111 Json web3v3 112 Password string 113 Priv string 114 } 115 116 type KeyStoreTestV1 struct { 117 Json web3v1 118 Password string 119 Priv string 120 } 121 122 func TestV3_PBKDF2_1(t *testing.T) { 123 t.Parallel() 124 tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t) 125 testDecryptV3(tests["wikipage_test_vector_pbkdf2"], t) 126 } 127 128 func TestV3_PBKDF2_2(t *testing.T) { 129 t.Parallel() 130 tests := loadKeyStoreTestV3("../tests/files/KeyStoreTests/basic_tests.json", t) 131 testDecryptV3(tests["test1"], t) 132 } 133 134 func TestV3_PBKDF2_3(t *testing.T) { 135 t.Parallel() 136 tests := loadKeyStoreTestV3("../tests/files/KeyStoreTests/basic_tests.json", t) 137 testDecryptV3(tests["python_generated_test_with_odd_iv"], t) 138 } 139 140 func TestV3_PBKDF2_4(t *testing.T) { 141 t.Parallel() 142 tests := loadKeyStoreTestV3("../tests/files/KeyStoreTests/basic_tests.json", t) 143 testDecryptV3(tests["evilnonce"], t) 144 } 145 146 func TestV3_Scrypt_1(t *testing.T) { 147 t.Parallel() 148 tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t) 149 testDecryptV3(tests["wikipage_test_vector_scrypt"], t) 150 } 151 152 func TestV3_Scrypt_2(t *testing.T) { 153 t.Parallel() 154 tests := loadKeyStoreTestV3("../tests/files/KeyStoreTests/basic_tests.json", t) 155 testDecryptV3(tests["test2"], t) 156 } 157 158 func TestV1_1(t *testing.T) { 159 t.Parallel() 160 tests := loadKeyStoreTestV1("testdata/v1_test_vector.json", t) 161 testDecryptV1(tests["test1"], t) 162 } 163 164 func TestV1_2(t *testing.T) { 165 t.Parallel() 166 store, err := newKeyStore("testdata/v1", LightScryptN, LightScryptP) 167 if err != nil { 168 t.Fatal(err) 169 } 170 171 key, err := store.Lookup("cb61d5a9c4896fb9658090b597ef0e7be6f7b67e/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e", "g") 172 if err != nil { 173 t.Fatal(err) 174 } 175 176 got := hex.EncodeToString(key.Address[:]) 177 want := "cb61d5a9c4896fb9658090b597ef0e7be6f7b67e" 178 if got != want { 179 t.Errorf("got address %s, want %s", got, want) 180 } 181 182 got = hex.EncodeToString(crypto.FromECDSA(key.PrivateKey)) 183 want = "d1b1178d3529626a1a93e073f65028370d14c7eb0936eb42abef05db6f37ad7d" 184 if got != want { 185 t.Errorf("got private key %s, want %s", got, want) 186 } 187 } 188 189 func testDecryptV3(test KeyStoreTestV3, t *testing.T) { 190 privBytes, err := decryptKeyV3(&test.Json, test.Password) 191 if err != nil { 192 t.Fatal(err) 193 } 194 privHex := hex.EncodeToString(privBytes) 195 if test.Priv != privHex { 196 t.Fatal(fmt.Errorf("Decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex)) 197 } 198 } 199 200 func testDecryptV1(test KeyStoreTestV1, t *testing.T) { 201 privBytes, err := decryptKeyV1(&test.Json, test.Password) 202 if err != nil { 203 t.Fatal(err) 204 } 205 privHex := hex.EncodeToString(privBytes) 206 if test.Priv != privHex { 207 t.Fatal(fmt.Errorf("Decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex)) 208 } 209 } 210 211 func loadKeyStoreTestV3(file string, t *testing.T) map[string]KeyStoreTestV3 { 212 tests := make(map[string]KeyStoreTestV3) 213 bytes, err := ioutil.ReadFile(file) 214 if err != nil { 215 t.Fatal(err) 216 } 217 if err = json.Unmarshal(bytes, &tests); err != nil { 218 t.Fatal(err) 219 } 220 return tests 221 } 222 223 func loadKeyStoreTestV1(file string, t *testing.T) map[string]KeyStoreTestV1 { 224 tests := make(map[string]KeyStoreTestV1) 225 bytes, err := ioutil.ReadFile(file) 226 if err != nil { 227 t.Fatal(err) 228 } 229 if err = json.Unmarshal(bytes, &tests); err != nil { 230 t.Fatal(err) 231 } 232 return tests 233 } 234 235 // WTF? 236 // newKeyForDirectICAP generates a key whose address fits into < 155 bits so it can fit 237 // into the Direct ICAP spec. for simplicity and easier compatibility with other libs, we 238 // retry until the first byte is 0. 239 func TestKeyForDirectICAP(t *testing.T) { 240 t.Parallel() 241 242 for { 243 randBytes := make([]byte, 64) 244 _, err := rand.Read(randBytes) 245 if err != nil { 246 t.Fatalf("key generation: could not read from random source: %s", err) 247 } 248 249 privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), bytes.NewReader(randBytes)) 250 if err != nil { 251 t.Fatalf("key generation: ecdsa.GenerateKey failed: %s", err) 252 } 253 254 key, err := newKeyFromECDSA(privateKeyECDSA) 255 if err != nil { 256 t.Fatal(err) 257 } 258 259 if key.Address[0] == 0 { 260 return 261 } 262 } 263 } 264 265 const ( 266 veryLightScryptN = 2 267 veryLightScryptP = 1 268 ) 269 270 // Tests that a JSON key file can be decrypted and encrypted in multiple rounds. 271 func TestKeyEncryptDecrypt(t *testing.T) { 272 keyjson, err := ioutil.ReadFile("testdata/very-light-scrypt.json") 273 if err != nil { 274 t.Fatal(err) 275 } 276 password := "" 277 address := common.HexToAddress("45dea0fb0bba44f4fcf290bba71fd57d7117cbb8") 278 279 // Do a few rounds of decryption and encryption 280 for i := 0; i < 3; i++ { 281 // try a bad password first 282 if _, err := decryptKey(keyjson, password+"bad"); err == nil { 283 t.Errorf("test %d: json key decrypted with bad password", i) 284 } 285 // decrypt with the correct password 286 key, err := decryptKey(keyjson, password) 287 if err != nil { 288 t.Errorf("test %d: json key failed to decrypt: %v", i, err) 289 } 290 if key.Address != address { 291 t.Errorf("test %d: key address mismatch: have %x, want %x", i, key.Address, address) 292 } 293 // recrypt with a new password and start over 294 password += "new data appended" 295 if keyjson, err = encryptKey(key, password, veryLightScryptN, veryLightScryptP); err != nil { 296 t.Errorf("test %d: failed to recrypt key %v", i, err) 297 } 298 } 299 }