github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/account/keystore/keystore.go (about) 1 // Copyright (C) 2017 go-crystal authors 2 // 3 // This file is part of the go-crystal library. 4 // 5 // the go-crystal library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-crystal library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-crystal library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package account 20 21 import ( 22 "errors" 23 "fmt" 24 "sync" 25 "time" 26 "github.com/sixexorg/magnetic-ring/crypto" 27 ) 28 29 var ( 30 // DefaultKS generate a default keystore 31 DefaultKS = NewKeystore() 32 33 // DefaultUnlockDuration default lock 300s 34 DefaultUnlockDuration = time.Duration(300 * time.Second) 35 36 // YearUnlockDuration lock 1 year time 37 YearUnlockDuration = time.Duration(365 * 24 * 60 * 60 * time.Second) 38 ) 39 40 var ( 41 // ErrUninitialized uninitialized provider error. 42 ErrUninitialized = errors.New("uninitialized the provider") 43 44 // ErrNotUnlocked key not unlocked 45 ErrNotUnlocked = errors.New("key not unlocked") 46 47 // ErrInvalidPassphrase invalid passphrase 48 ErrInvalidPassphrase = errors.New("passphrase is invalid") 49 ) 50 51 // unlock item 52 type unlocked struct { 53 alias string 54 55 key crypto.PrivateKey 56 57 timer *time.Timer 58 } 59 60 // Keystore class represents a storage facility for cryptographic keys 61 type Keystore struct { 62 63 // keystore provider 64 p Provider 65 66 // unlocked items 67 unlocked map[string]*unlocked 68 69 mu sync.RWMutex 70 } 71 72 // NewKeystore new 73 func NewKeystore() *Keystore { 74 ks := &Keystore{} 75 76 ks.unlocked = make(map[string]*unlocked) 77 ks.p = NewMemoryProvider(1.0) 78 return ks 79 } 80 81 // Aliases lists all the alias names of this keystore. 82 func (ks *Keystore) Aliases() []string { 83 return ks.p.Aliases() 84 } 85 86 // ContainsAlias checks if the given alias exists in this keystore. 87 func (ks *Keystore) ContainsAlias(a string) (bool, error) { 88 if ks.p == nil { 89 return false, ErrUninitialized 90 } 91 92 return ks.p.ContainsAlias(a) 93 } 94 95 // Unlock unlock key with ProtectionParameter 96 func (ks *Keystore) Unlock(alias string, passphrase []byte, timeout time.Duration) error { 97 ks.mu.Lock() 98 defer ks.mu.Unlock() 99 100 key, err := ks.p.GetKey(alias, passphrase) 101 if err != nil { 102 return err 103 } 104 105 unlockedKey, ok := ks.unlocked[alias] 106 if ok == true { 107 unlockedKey.key = key 108 unlockedKey.timer.Reset(timeout) 109 } else { 110 u := &unlocked{alias, key, time.NewTimer(timeout)} 111 ks.unlocked[alias] = u 112 go ks.expire(alias) 113 } 114 return nil 115 } 116 117 // Lock lock key 118 func (ks *Keystore) Lock(alias string) error { 119 ks.mu.Lock() 120 defer ks.mu.Unlock() 121 122 if u, ok := ks.unlocked[alias]; ok == true { 123 u.timer.Reset(time.Duration(0) * time.Nanosecond) 124 return nil 125 } 126 127 return ErrNotUnlocked 128 } 129 130 func (ks *Keystore) expire(alias string) { 131 if u, ok := ks.unlocked[alias]; ok == true { 132 defer u.timer.Stop() 133 select { 134 case <-u.timer.C: 135 ks.mu.Lock() 136 //u.key.Clear() 137 delete(ks.unlocked, alias) 138 ks.mu.Unlock() 139 } 140 } 141 } 142 143 // GetUnlocked returns a unlocked key 144 func (ks *Keystore) GetUnlocked(alias string) (crypto.PrivateKey, error) { 145 if len(alias) == 0 { 146 return nil, ErrNeedAlias 147 } 148 149 ks.mu.RLock() 150 defer ks.mu.RUnlock() 151 152 key, ok := ks.unlocked[alias] 153 if ok == false { 154 return nil, ErrNotUnlocked 155 } 156 157 return key.key, nil 158 } 159 160 // SetKey assigns the given key to the given alias, protecting it with the given passphrase. 161 func (ks *Keystore) SetKey(a string, k crypto.PrivateKey, passphrase []byte) error { 162 if ks.p == nil { 163 return ErrUninitialized 164 } 165 166 return ks.p.SetKey(a, k, passphrase) 167 } 168 169 // GetKey returns the key associated with the given alias, using the given 170 // password to recover it. 171 func (ks *Keystore) GetKey(a string, passphrase []byte) (crypto.PrivateKey, error) { 172 if ks.p == nil { 173 fmt.Printf("getkey 001 a=%s\n",a) 174 return nil, ErrUninitialized 175 } 176 177 key, err := ks.p.GetKey(a, passphrase) 178 if err != nil { 179 fmt.Printf("getkey 002 a=%s\n",a) 180 return nil, err 181 } 182 return key, nil 183 } 184 185 // Delete the entry identified by the given alias from this keystore. 186 func (ks *Keystore) Delete(a string, passphrase []byte) error { 187 if ks.p == nil { 188 return ErrUninitialized 189 } 190 191 //key, err := ks.p.GetKey(a, passphrase) 192 //if err != nil { 193 // return err 194 //} 195 //key.Clear() 196 197 if _, ok := ks.unlocked[a]; ok == true { 198 ks.Lock(a) 199 } 200 201 return ks.p.Delete(a) 202 }