github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/identity/keystore_filesystem_test.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU 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   * This program 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 General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package identity
    19  
    20  import (
    21  	"testing"
    22  
    23  	"github.com/ethereum/go-ethereum/accounts"
    24  	ethKs "github.com/ethereum/go-ethereum/accounts/keystore"
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/crypto"
    27  	"github.com/pkg/errors"
    28  	"github.com/stretchr/testify/assert"
    29  )
    30  
    31  const secretMessage = "I like trains. A LOT. Choo CHOO"
    32  
    33  var (
    34  	encryptionAddress = common.HexToAddress("53a835143c0ef3bbcbfa796d7eb738ca7dd28f68")
    35  	encryptionAccount = accounts.Account{Address: encryptionAddress}
    36  	encryptionKey, _  = crypto.HexToECDSA("6f88637b68ee88816e73f663aef709d7009836c98ae91ef31e3dfac7be3a1657")
    37  )
    38  
    39  func Test_DerivedEncryption(t *testing.T) {
    40  	ks := NewKeystoreFilesystem("", &ethKeystoreMock{account: encryptionAccount})
    41  	ks.loadKey = func(addr common.Address, filename, auth string) (*ethKs.Key, error) {
    42  		return &ethKs.Key{Address: addr, PrivateKey: encryptionKey}, nil
    43  	}
    44  
    45  	t.Run("Fails to decrypt or encrypt if account is locked", func(t *testing.T) {
    46  		encrypted, err := ks.Encrypt(encryptionAddress, []byte(secretMessage))
    47  		assert.Error(t, err)
    48  
    49  		_, err = ks.Decrypt(encryptionAddress, encrypted)
    50  		assert.Error(t, err)
    51  	})
    52  
    53  	err := ks.Unlock(encryptionAccount, "")
    54  	assert.NoError(t, err)
    55  
    56  	t.Run("Encrypts and decrypts messages with the derived key", func(t *testing.T) {
    57  		encrypted, err := ks.Encrypt(encryptionAddress, []byte(secretMessage))
    58  		assert.NoError(t, err)
    59  		assert.NotEqual(t, []byte(secretMessage), encrypted)
    60  
    61  		decrypted, err := ks.Decrypt(encryptionAddress, encrypted)
    62  		assert.NoError(t, err)
    63  
    64  		assert.Equal(t, secretMessage, string(decrypted))
    65  	})
    66  
    67  	t.Run("Errors if message is tampered with", func(t *testing.T) {
    68  		encrypted, err := ks.Encrypt(encryptionAddress, []byte(secretMessage))
    69  		assert.NoError(t, err)
    70  		assert.NotEqual(t, []byte(secretMessage), encrypted)
    71  
    72  		encrypted[1] = 0x1
    73  		_, err = ks.Decrypt(encryptionAddress, encrypted)
    74  		assert.Error(t, err)
    75  	})
    76  }
    77  
    78  var result []byte
    79  
    80  func Benchmark_DerivedEncryption(b *testing.B) {
    81  	ks := NewKeystoreFilesystem("", &ethKeystoreMock{account: encryptionAccount})
    82  	ks.loadKey = func(addr common.Address, filename, auth string) (*ethKs.Key, error) {
    83  		return &ethKs.Key{}, nil
    84  	}
    85  	_ = ks.Unlock(encryptionAccount, "")
    86  
    87  	var r []byte
    88  	for n := 0; n < b.N; n++ {
    89  		encrypted, _ := ks.Encrypt(encryptionAddress, []byte(secretMessage))
    90  		r = encrypted
    91  	}
    92  
    93  	result = r
    94  }
    95  
    96  func Benchmark_DerivedDecryption(b *testing.B) {
    97  	ks := NewKeystoreFilesystem("", &ethKeystoreMock{account: encryptionAccount})
    98  	ks.loadKey = func(addr common.Address, filename, auth string) (*ethKs.Key, error) {
    99  		return &ethKs.Key{}, nil
   100  	}
   101  	_ = ks.Unlock(encryptionAccount, "")
   102  	encrypted, _ := ks.Encrypt(encryptionAddress, []byte(secretMessage))
   103  
   104  	var r []byte
   105  	for n := 0; n < b.N; n++ {
   106  		decrypted, _ := ks.Decrypt(encryptionAddress, encrypted)
   107  		r = decrypted
   108  	}
   109  
   110  	result = r
   111  }
   112  
   113  type ethKeystoreMock struct {
   114  	account  accounts.Account
   115  	unlocked bool
   116  }
   117  
   118  func (ekm *ethKeystoreMock) Unlock(a accounts.Account, passphrase string) error {
   119  	ekm.unlocked = true
   120  	return nil
   121  }
   122  
   123  func (ekm *ethKeystoreMock) Delete(a accounts.Account, passphrase string) error {
   124  	if a.Address == ekm.account.Address {
   125  		ekm.account = accounts.Account{}
   126  	}
   127  
   128  	return nil
   129  }
   130  
   131  func (ekm *ethKeystoreMock) Export(a accounts.Account, passphrase, newPassphrase string) ([]byte, error) {
   132  	return []byte("exported"), nil
   133  }
   134  
   135  func (ekm *ethKeystoreMock) Import(keyJSON []byte, passphrase, newPassphrase string) (accounts.Account, error) {
   136  	return ekm.account, nil
   137  }
   138  
   139  func (ekm *ethKeystoreMock) Accounts() []accounts.Account {
   140  	return []accounts.Account{ekm.account}
   141  }
   142  
   143  func (ekm *ethKeystoreMock) Find(a accounts.Account) (accounts.Account, error) {
   144  	if ekm.account.Address == a.Address {
   145  		return ekm.account, nil
   146  	}
   147  	return accounts.Account{}, errors.New("not found")
   148  }
   149  
   150  func (ekm *ethKeystoreMock) NewAccount(passphrase string) (accounts.Account, error) {
   151  	return accounts.Account{}, errors.New("not implemented yet")
   152  }