github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/identity/keystore_mock.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 "crypto/ecdsa" 22 crand "crypto/rand" 23 "encoding/hex" 24 "sync" 25 26 "github.com/ethereum/go-ethereum/accounts" 27 ethKs "github.com/ethereum/go-ethereum/accounts/keystore" 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/crypto" 30 ) 31 32 type mockKeystore struct { 33 keys map[common.Address]MockKey 34 lock sync.Mutex 35 } 36 37 // MockKeys represents the mocked keys 38 var MockKeys = map[common.Address]MockKey{ 39 common.HexToAddress("53a835143c0ef3bbcbfa796d7eb738ca7dd28f68"): { 40 PkHex: "6f88637b68ee88816e73f663aef709d7009836c98ae91ef31e3dfac7be3a1657", 41 Pass: "", 42 }, 43 } 44 45 // NewMockKeystore returns empty mock keystore 46 func NewMockKeystore() *mockKeystore { 47 return NewMockKeystoreWith(map[common.Address]MockKey{}) 48 } 49 50 // NewMockKeystoreWith returns a new mock keystore with specified keys 51 func NewMockKeystoreWith(keys map[common.Address]MockKey) *mockKeystore { 52 copied := make(map[common.Address]MockKey) 53 for key, value := range keys { 54 copied[key] = value 55 } 56 return &mockKeystore{ 57 keys: copied, 58 } 59 } 60 61 // MockKey represents a mocked key 62 type MockKey struct { 63 PkHex string 64 Pass string 65 pk *ecdsa.PrivateKey 66 isUnlocked bool 67 } 68 69 func (mk *mockKeystore) Accounts() []accounts.Account { 70 mk.lock.Lock() 71 defer mk.lock.Unlock() 72 res := make([]accounts.Account, 0) 73 for k := range mk.keys { 74 res = append(res, accounts.Account{ 75 Address: k, 76 }) 77 } 78 return res 79 } 80 81 func (mk *mockKeystore) SignHash(a accounts.Account, hash []byte) ([]byte, error) { 82 mk.lock.Lock() 83 defer mk.lock.Unlock() 84 85 if v, ok := mk.keys[a.Address]; ok { 86 if !v.isUnlocked { 87 return nil, ethKs.ErrLocked 88 } 89 return crypto.Sign(hash, v.pk) 90 } 91 return nil, ethKs.ErrNoMatch 92 } 93 94 func (mk *mockKeystore) Export(a accounts.Account, passphrase, newPassphrase string) (keyJSON []byte, err error) { 95 mk.lock.Lock() 96 defer mk.lock.Unlock() 97 if v, ok := mk.keys[a.Address]; ok { 98 if v.Pass != passphrase { 99 return nil, ethKs.ErrDecrypt 100 } 101 return common.Hex2Bytes(v.PkHex), nil 102 } 103 return nil, ethKs.ErrNoMatch 104 } 105 106 func (mk *mockKeystore) NewAccount(passphrase string) (accounts.Account, error) { 107 mk.lock.Lock() 108 defer mk.lock.Unlock() 109 110 privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), crand.Reader) 111 if err != nil { 112 return accounts.Account{}, err 113 } 114 115 address := crypto.PubkeyToAddress(privateKeyECDSA.PublicKey) 116 mk.keys[address] = MockKey{ 117 Pass: passphrase, 118 PkHex: hex.EncodeToString(crypto.FromECDSA(privateKeyECDSA)), 119 pk: privateKeyECDSA, 120 isUnlocked: false, 121 } 122 return accounts.Account{ 123 Address: address, 124 }, nil 125 } 126 127 func (mk *mockKeystore) Unlock(a accounts.Account, passphrase string) error { 128 mk.lock.Lock() 129 defer mk.lock.Unlock() 130 131 if v, ok := mk.keys[a.Address]; ok { 132 if v.isUnlocked { 133 return nil 134 } 135 136 if v.Pass != passphrase { 137 return ethKs.ErrDecrypt 138 } 139 140 pk, err := crypto.HexToECDSA(v.PkHex) 141 if err != nil { 142 return err 143 } 144 145 v.isUnlocked = true 146 v.pk = pk 147 mk.keys[a.Address] = v 148 return nil 149 } 150 151 return ethKs.ErrNoMatch 152 } 153 154 func (mk *mockKeystore) Lock(addr common.Address) error { 155 mk.lock.Lock() 156 defer mk.lock.Unlock() 157 158 if v, ok := mk.keys[addr]; ok { 159 v.isUnlocked = false 160 mk.keys[addr] = v 161 } 162 return nil 163 } 164 165 func (mk *mockKeystore) Find(a accounts.Account) (accounts.Account, error) { 166 mk.lock.Lock() 167 defer mk.lock.Unlock() 168 169 if _, ok := mk.keys[a.Address]; ok { 170 return a, nil 171 } 172 return accounts.Account{}, ethKs.ErrNoMatch 173 } 174 175 // MockDecryptFunc represents the mock decrypt func 176 var MockDecryptFunc = func(keyjson []byte, auth string) (*ethKs.Key, error) { 177 pk, err := crypto.HexToECDSA(common.Bytes2Hex(keyjson)) 178 if err != nil { 179 return nil, err 180 } 181 return ðKs.Key{ 182 PrivateKey: pk, 183 }, nil 184 }