github.com/amazechain/amc@v0.1.3/accounts/keystore/plain_test.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  package keystore
    17  
    18  import (
    19  	"crypto/rand"
    20  	"encoding/hex"
    21  	"fmt"
    22  	"path/filepath"
    23  	"reflect"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/amazechain/amc/common/crypto"
    28  	"github.com/amazechain/amc/common/types"
    29  	"github.com/amazechain/amc/internal/avm/common"
    30  )
    31  
    32  func tmpKeyStoreIface(t *testing.T, encrypted bool) (dir string, ks keyStore) {
    33  	d := t.TempDir()
    34  	if encrypted {
    35  		ks = &keyStorePassphrase{d, veryLightScryptN, veryLightScryptP, true}
    36  	} else {
    37  		ks = &keyStorePlain{d}
    38  	}
    39  	return d, ks
    40  }
    41  
    42  func TestKeyStorePlain(t *testing.T) {
    43  	_, ks := tmpKeyStoreIface(t, false)
    44  
    45  	pass := "" // not used but required by API
    46  	k1, account, err := storeNewKey(ks, rand.Reader, pass)
    47  	if err != nil {
    48  		t.Fatal(err)
    49  	}
    50  	k2, err := ks.GetKey(k1.Address, account.URL.Path, pass)
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  	if !reflect.DeepEqual(k1.Address, k2.Address) {
    55  		t.Fatal(err)
    56  	}
    57  	if !reflect.DeepEqual(k1.PrivateKey, k2.PrivateKey) {
    58  		t.Fatal(err)
    59  	}
    60  }
    61  
    62  func TestKeyStorePassphrase(t *testing.T) {
    63  	_, ks := tmpKeyStoreIface(t, true)
    64  
    65  	pass := "foo"
    66  	k1, account, err := storeNewKey(ks, rand.Reader, pass)
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	k2, err := ks.GetKey(k1.Address, account.URL.Path, pass)
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	if !reflect.DeepEqual(k1.Address, k2.Address) {
    75  		t.Fatal(err)
    76  	}
    77  	if !reflect.DeepEqual(k1.PrivateKey, k2.PrivateKey) {
    78  		t.Fatal(err)
    79  	}
    80  }
    81  
    82  func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
    83  	_, ks := tmpKeyStoreIface(t, true)
    84  
    85  	pass := "foo"
    86  	k1, account, err := storeNewKey(ks, rand.Reader, pass)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  	if _, err = ks.GetKey(k1.Address, account.URL.Path, "bar"); err != ErrDecrypt {
    91  		t.Fatalf("wrong error for invalid password\ngot %q\nwant %q", err, ErrDecrypt)
    92  	}
    93  }
    94  
    95  func TestImportPreSaleKey(t *testing.T) {
    96  	dir, ks := tmpKeyStoreIface(t, true)
    97  
    98  	// file content of a presale key file generated with:
    99  	// python pyethsaletool.py genwallet
   100  	// with password "foo"
   101  	fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}"
   102  	pass := "foo"
   103  	account, _, err := importPreSaleKey(ks, []byte(fileContent), pass)
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	if account.Address != types.HexToAddress("d4584b5f6229b7be90727b0fc8c6b91bb427821f") {
   108  		t.Errorf("imported account has wrong address %x", account.Address)
   109  	}
   110  	if !strings.HasPrefix(account.URL.Path, dir) {
   111  		t.Errorf("imported account file not in keystore directory: %q", account.URL)
   112  	}
   113  }
   114  
   115  // Test and utils for the key store tests in the Ethereum JSON tests;
   116  // testdataKeyStoreTests/basic_tests.json
   117  type KeyStoreTestV3 struct {
   118  	Json     encryptedKeyJSONV3
   119  	Password string
   120  	Priv     string
   121  }
   122  
   123  type KeyStoreTestV1 struct {
   124  	Json     encryptedKeyJSONV1
   125  	Password string
   126  	Priv     string
   127  }
   128  
   129  func TestV3_PBKDF2_1(t *testing.T) {
   130  	t.Parallel()
   131  	tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t)
   132  	testDecryptV3(tests["wikipage_test_vector_pbkdf2"], t)
   133  }
   134  
   135  var testsSubmodule = filepath.Join("..", "..", "tests", "testdata", "KeyStoreTests")
   136  
   137  func skipIfSubmoduleMissing(t *testing.T) {
   138  	if !common.FileExist(testsSubmodule) {
   139  		t.Skipf("can't find JSON tests from submodule at %s", testsSubmodule)
   140  	}
   141  }
   142  
   143  func TestV3_PBKDF2_2(t *testing.T) {
   144  	skipIfSubmoduleMissing(t)
   145  	t.Parallel()
   146  	tests := loadKeyStoreTestV3(filepath.Join(testsSubmodule, "basic_tests.json"), t)
   147  	testDecryptV3(tests["test1"], t)
   148  }
   149  
   150  func TestV3_PBKDF2_3(t *testing.T) {
   151  	skipIfSubmoduleMissing(t)
   152  	t.Parallel()
   153  	tests := loadKeyStoreTestV3(filepath.Join(testsSubmodule, "basic_tests.json"), t)
   154  	testDecryptV3(tests["python_generated_test_with_odd_iv"], t)
   155  }
   156  
   157  func TestV3_PBKDF2_4(t *testing.T) {
   158  	skipIfSubmoduleMissing(t)
   159  	t.Parallel()
   160  	tests := loadKeyStoreTestV3(filepath.Join(testsSubmodule, "basic_tests.json"), t)
   161  	testDecryptV3(tests["evilnonce"], t)
   162  }
   163  
   164  func TestV3_Scrypt_1(t *testing.T) {
   165  	t.Parallel()
   166  	tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t)
   167  	testDecryptV3(tests["wikipage_test_vector_scrypt"], t)
   168  }
   169  
   170  func TestV3_Scrypt_2(t *testing.T) {
   171  	skipIfSubmoduleMissing(t)
   172  	t.Parallel()
   173  	tests := loadKeyStoreTestV3(filepath.Join(testsSubmodule, "basic_tests.json"), t)
   174  	testDecryptV3(tests["test2"], t)
   175  }
   176  
   177  func TestV1_1(t *testing.T) {
   178  	t.Parallel()
   179  	tests := loadKeyStoreTestV1("testdata/v1_test_vector.json", t)
   180  	testDecryptV1(tests["test1"], t)
   181  }
   182  
   183  func TestV1_2(t *testing.T) {
   184  	t.Parallel()
   185  	ks := &keyStorePassphrase{"testdata/v1", LightScryptN, LightScryptP, true}
   186  	addr := types.HexToAddress("cb61d5a9c4896fb9658090b597ef0e7be6f7b67e")
   187  	file := "testdata/v1/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e"
   188  	k, err := ks.GetKey(addr, file, "g")
   189  	if err != nil {
   190  		t.Fatal(err)
   191  	}
   192  	privHex := hex.EncodeToString(crypto.FromECDSA(k.PrivateKey))
   193  	expectedHex := "d1b1178d3529626a1a93e073f65028370d14c7eb0936eb42abef05db6f37ad7d"
   194  	if privHex != expectedHex {
   195  		t.Fatal(fmt.Errorf("Unexpected privkey: %v, expected %v", privHex, expectedHex))
   196  	}
   197  }
   198  
   199  func testDecryptV3(test KeyStoreTestV3, t *testing.T) {
   200  	privBytes, _, err := decryptKeyV3(&test.Json, test.Password)
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  	privHex := hex.EncodeToString(privBytes)
   205  	if test.Priv != privHex {
   206  		t.Fatal(fmt.Errorf("Decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex))
   207  	}
   208  }
   209  
   210  func testDecryptV1(test KeyStoreTestV1, t *testing.T) {
   211  	privBytes, _, err := decryptKeyV1(&test.Json, test.Password)
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  	privHex := hex.EncodeToString(privBytes)
   216  	if test.Priv != privHex {
   217  		t.Fatal(fmt.Errorf("Decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex))
   218  	}
   219  }
   220  
   221  func loadKeyStoreTestV3(file string, t *testing.T) map[string]KeyStoreTestV3 {
   222  	tests := make(map[string]KeyStoreTestV3)
   223  	err := common.LoadJSON(file, &tests)
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  	return tests
   228  }
   229  
   230  func loadKeyStoreTestV1(file string, t *testing.T) map[string]KeyStoreTestV1 {
   231  	tests := make(map[string]KeyStoreTestV1)
   232  	err := common.LoadJSON(file, &tests)
   233  	if err != nil {
   234  		t.Fatal(err)
   235  	}
   236  	return tests
   237  }
   238  
   239  func TestKeyForDirectICAP(t *testing.T) {
   240  	t.Parallel()
   241  	key := NewKeyForDirectICAP(rand.Reader)
   242  	if !strings.HasPrefix(key.Address.Hex(), "0x00") {
   243  		t.Errorf("Expected first address byte to be zero, have: %s", key.Address.Hex())
   244  	}
   245  }
   246  
   247  func TestV3_31_Byte_Key(t *testing.T) {
   248  	t.Parallel()
   249  	tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t)
   250  	testDecryptV3(tests["31_byte_key"], t)
   251  }
   252  
   253  func TestV3_30_Byte_Key(t *testing.T) {
   254  	t.Parallel()
   255  	tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t)
   256  	testDecryptV3(tests["30_byte_key"], t)
   257  }