github.com/aergoio/aergo@v1.3.1/account/key/store.go (about) 1 package key 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "errors" 8 "path" 9 "sync" 10 "time" 11 12 "github.com/aergoio/aergo-lib/db" 13 "github.com/aergoio/aergo/types" 14 "github.com/btcsuite/btcd/btcec" 15 sha256 "github.com/minio/sha256-simd" 16 ) 17 18 type aergokey = btcec.PrivateKey 19 20 type keyPair struct { 21 key *aergokey 22 timer *time.Timer 23 } 24 25 // Store stucture of keystore 26 type Store struct { 27 sync.RWMutex 28 timeout time.Duration 29 unlocked map[string]*keyPair 30 unlockedLock *sync.Mutex 31 storage db.DB 32 } 33 34 // NewStore make new instance of keystore 35 func NewStore(storePath string, unlockTimeout uint) *Store { 36 const dbName = "account" 37 dbPath := path.Join(storePath, dbName) 38 return &Store{ 39 timeout: time.Duration(unlockTimeout) * time.Second, 40 unlocked: map[string]*keyPair{}, 41 unlockedLock: &sync.Mutex{}, 42 storage: db.NewDB(db.LevelImpl, dbPath), 43 } 44 } 45 func (ks *Store) CloseStore() { 46 ks.unlocked = nil 47 ks.storage.Close() 48 } 49 50 // CreateKey make new key in keystore and return it's address 51 func (ks *Store) CreateKey(pass string) (Address, error) { 52 //gen new key 53 privkey, err := btcec.NewPrivateKey(btcec.S256()) 54 if err != nil { 55 return nil, err 56 } 57 return ks.addKey(privkey, pass) 58 } 59 60 //ImportKey is to import encrypted key 61 func (ks *Store) ImportKey(imported []byte, oldpass string, newpass string) (Address, error) { 62 hash := hashBytes([]byte(oldpass), nil) 63 rehash := hashBytes([]byte(oldpass), hash) 64 key, err := decrypt(hash, rehash, imported) 65 if err != nil { 66 return nil, err 67 } 68 privkey, pubkey := btcec.PrivKeyFromBytes(btcec.S256(), key) 69 address := GenerateAddress(pubkey.ToECDSA()) 70 addresses, err := ks.GetAddresses() 71 if err != nil { 72 return nil, err 73 } 74 for _, v := range addresses { 75 if bytes.Equal(address, v) { 76 return nil, errors.New("already exist") 77 } 78 } 79 err = ks.SaveAddress(address) 80 if err != nil { 81 return nil, err 82 } 83 return ks.addKey(privkey, newpass) 84 } 85 86 //ExportKey is to export encrypted key 87 func (ks *Store) ExportKey(addr Address, pass string) ([]byte, error) { 88 key, err := ks.getKey(addr, pass) 89 if key == nil { 90 return nil, err 91 } 92 return EncryptKey(key, pass) 93 } 94 95 // EncryptKey encrypts a key with a given export for exporting 96 func EncryptKey(key []byte, pass string) ([]byte, error) { 97 hash := hashBytes([]byte(pass), nil) 98 rehash := hashBytes([]byte(pass), hash) 99 return encrypt(hash, rehash, key) 100 } 101 102 //Unlock is to unlock account for signing 103 func (ks *Store) Unlock(addr Address, pass string) (Address, error) { 104 key, err := ks.getKey(addr, pass) 105 if key == nil { 106 return nil, err 107 } 108 pk, _ := btcec.PrivKeyFromBytes(btcec.S256(), key) 109 addrKey := types.EncodeAddress(addr) 110 111 ks.unlockedLock.Lock() 112 defer ks.unlockedLock.Unlock() 113 114 unlockedKeyPair, exist := ks.unlocked[addrKey] 115 116 if ks.timeout == 0 { 117 ks.unlocked[addrKey] = &keyPair{key: pk, timer: nil} 118 return addr, nil 119 } 120 121 if exist { 122 unlockedKeyPair.timer.Reset(ks.timeout) 123 } else { 124 lockTimer := time.AfterFunc(ks.timeout, 125 func() { 126 ks.Lock(addr, pass) 127 }, 128 ) 129 ks.unlocked[addrKey] = &keyPair{key: pk, timer: lockTimer} 130 } 131 return addr, nil 132 } 133 134 //Lock is to lock account prevent signing 135 func (ks *Store) Lock(addr Address, pass string) (Address, error) { 136 key, err := ks.getKey(addr, pass) 137 if key == nil { 138 return nil, err 139 } 140 b58addr := types.EncodeAddress(addr) 141 142 ks.unlockedLock.Lock() 143 defer ks.unlockedLock.Unlock() 144 145 if _, exist := ks.unlocked[b58addr]; exist { 146 ks.unlocked[b58addr] = nil 147 delete(ks.unlocked, b58addr) 148 } 149 return addr, nil 150 } 151 152 func (ks *Store) getKey(address []byte, pass string) ([]byte, error) { 153 encryptkey := hashBytes(address, []byte(pass)) 154 key := ks.storage.Get(hashBytes(address, encryptkey)) 155 if cap(key) == 0 { 156 return nil, types.ErrWrongAddressOrPassWord 157 } 158 return decrypt(address, encryptkey, key) 159 } 160 161 func (ks *Store) addKey(key *btcec.PrivateKey, pass string) (Address, error) { 162 //gen new address 163 address := GenerateAddress(&key.PublicKey) 164 //save pass/address/key 165 encryptkey := hashBytes(address, []byte(pass)) 166 encrypted, err := encrypt(address, encryptkey, key.Serialize()) 167 if err != nil { 168 return nil, err 169 } 170 ks.storage.Set(hashBytes(address, encryptkey), encrypted) 171 return address, nil 172 } 173 174 func hashBytes(b1 []byte, b2 []byte) []byte { 175 h := sha256.New() 176 h.Write(b1) 177 h.Write(b2) 178 return h.Sum(nil) 179 } 180 181 func encrypt(base, key, data []byte) ([]byte, error) { 182 block, err := aes.NewCipher(key) 183 if err != nil { 184 return nil, err 185 } 186 // Never use more than 2^32 random nonces with a given key because of the risk of a repeat. 187 if len(base) < 16 { 188 return nil, errors.New("too short address length") 189 } 190 nonce := base[4:16] 191 192 aesgcm, err := cipher.NewGCM(block) 193 if err != nil { 194 return nil, err 195 } 196 197 cipherbytes := aesgcm.Seal(nil, nonce, data, nil) 198 return cipherbytes, nil 199 } 200 201 func decrypt(base, key, data []byte) ([]byte, error) { 202 if len(base) < 16 { 203 return nil, errors.New("too short address length") 204 } 205 nonce := base[4:16] 206 207 block, err := aes.NewCipher(key) 208 if err != nil { 209 return nil, err 210 } 211 212 aesgcm, err := cipher.NewGCM(block) 213 if err != nil { 214 return nil, err 215 } 216 217 plainbytes, err := aesgcm.Open(nil, nonce, data, nil) 218 219 if err != nil { 220 return nil, err 221 } 222 return plainbytes, nil 223 }