github.com/igggame/nebulas-go@v2.1.0+incompatible/crypto/keystore/keystore.go (about) 1 // Copyright (C) 2017 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas 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-nebulas 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-nebulas library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package keystore 20 21 import ( 22 "errors" 23 "sync" 24 "time" 25 ) 26 27 var ( 28 // DefaultKS generate a default keystore 29 DefaultKS = NewKeystore() 30 31 // DefaultUnlockDuration default lock 300s 32 DefaultUnlockDuration = time.Duration(300 * time.Second) 33 34 // YearUnlockDuration lock 1 year time 35 YearUnlockDuration = time.Duration(365 * 24 * 60 * 60 * time.Second) 36 ) 37 38 var ( 39 // ErrUninitialized uninitialized provider error. 40 ErrUninitialized = errors.New("uninitialized the provider") 41 42 // ErrNotUnlocked key not unlocked 43 ErrNotUnlocked = errors.New("key not unlocked") 44 45 // ErrInvalidPassphrase invalid passphrase 46 ErrInvalidPassphrase = errors.New("passphrase is invalid") 47 ) 48 49 // unlock item 50 type unlocked struct { 51 alias string 52 53 key Key 54 55 timer *time.Timer 56 } 57 58 // Keystore class represents a storage facility for cryptographic keys 59 type Keystore struct { 60 61 // keystore provider 62 p Provider 63 64 // unlocked items 65 unlocked map[string]*unlocked 66 67 mu sync.RWMutex 68 } 69 70 // NewKeystore new 71 func NewKeystore() *Keystore { 72 ks := &Keystore{} 73 74 ks.unlocked = make(map[string]*unlocked) 75 ks.p = NewMemoryProvider(1.0, SCRYPT) 76 return ks 77 } 78 79 // Aliases lists all the alias names of this keystore. 80 func (ks *Keystore) Aliases() []string { 81 return ks.p.Aliases() 82 } 83 84 // ContainsAlias checks if the given alias exists in this keystore. 85 func (ks *Keystore) ContainsAlias(a string) (bool, error) { 86 if ks.p == nil { 87 return false, ErrUninitialized 88 } 89 90 return ks.p.ContainsAlias(a) 91 } 92 93 // Unlock unlock key with ProtectionParameter 94 func (ks *Keystore) Unlock(alias string, passphrase []byte, timeout time.Duration) error { 95 ks.mu.Lock() 96 defer ks.mu.Unlock() 97 98 key, err := ks.p.GetKey(alias, passphrase) 99 if err != nil { 100 return err 101 } 102 103 unlockedKey, ok := ks.unlocked[alias] 104 if ok == true { 105 unlockedKey.key = key 106 unlockedKey.timer.Reset(timeout) 107 } else { 108 u := &unlocked{alias, key, time.NewTimer(timeout)} 109 ks.unlocked[alias] = u 110 go ks.expire(alias) 111 } 112 return nil 113 } 114 115 // Lock lock key 116 func (ks *Keystore) Lock(alias string) error { 117 ks.mu.Lock() 118 defer ks.mu.Unlock() 119 120 if u, ok := ks.unlocked[alias]; ok == true { 121 u.timer.Reset(time.Duration(0) * time.Nanosecond) 122 return nil 123 } 124 125 return ErrNotUnlocked 126 } 127 128 func (ks *Keystore) expire(alias string) { 129 if u, ok := ks.unlocked[alias]; ok == true { 130 defer u.timer.Stop() 131 select { 132 case <-u.timer.C: 133 ks.mu.Lock() 134 u.key.Clear() 135 delete(ks.unlocked, alias) 136 ks.mu.Unlock() 137 } 138 } 139 } 140 141 // GetUnlocked returns a unlocked key 142 func (ks *Keystore) GetUnlocked(alias string) (Key, error) { 143 if len(alias) == 0 { 144 return nil, ErrNeedAlias 145 } 146 147 ks.mu.RLock() 148 defer ks.mu.RUnlock() 149 150 key, ok := ks.unlocked[alias] 151 if ok == false { 152 return nil, ErrNotUnlocked 153 } 154 155 return key.key, nil 156 } 157 158 // SetKey assigns the given key to the given alias, protecting it with the given passphrase. 159 func (ks *Keystore) SetKey(a string, k Key, passphrase []byte) error { 160 if ks.p == nil { 161 return ErrUninitialized 162 } 163 164 return ks.p.SetKey(a, k, passphrase) 165 } 166 167 // GetKey returns the key associated with the given alias, using the given 168 // password to recover it. 169 func (ks *Keystore) GetKey(a string, passphrase []byte) (Key, error) { 170 if ks.p == nil { 171 return nil, ErrUninitialized 172 } 173 174 key, err := ks.p.GetKey(a, passphrase) 175 if err != nil { 176 return nil, err 177 } 178 return key, nil 179 } 180 181 // Delete the entry identified by the given alias from this keystore. 182 func (ks *Keystore) Delete(a string, passphrase []byte) error { 183 if ks.p == nil { 184 return ErrUninitialized 185 } 186 187 key, err := ks.p.GetKey(a, passphrase) 188 if err != nil { 189 return err 190 } 191 key.Clear() 192 193 if _, ok := ks.unlocked[a]; ok == true { 194 ks.Lock(a) 195 } 196 197 return ks.p.Delete(a) 198 }