-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathkeybase.go
225 lines (196 loc) · 6.67 KB
/
keybase.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
package cosmos
import (
"crypto/sha256"
"sync"
clientkey "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
"github.com/cosmos/cosmos-sdk/types"
bip39 "github.com/cosmos/go-bip39"
"github.com/tendermint/tendermint/crypto"
)
const (
mnemonicEntropySize = 256
)
// Keybase is a standard cosmos keybase.
type Keybase struct {
kb keys.Keybase
mx sync.Mutex
privKeysCache map[[sha256.Size]byte]crypto.PrivKey
}
// NewKeybase initializes a filesystem keybase at a particular dir.
func NewKeybase(dir string) (*Keybase, error) {
kb, err := clientkey.NewKeyBaseFromDir(dir)
if err != nil {
return nil, err
}
return &Keybase{
kb: kb,
privKeysCache: make(map[[sha256.Size]byte]crypto.PrivKey),
}, nil
}
// NewInMemoryKeybase initializes a in memory keybase.
func NewInMemoryKeybase() *Keybase {
return &Keybase{
kb: clientkey.NewInMemoryKeyBase(),
privKeysCache: make(map[[sha256.Size]byte]crypto.PrivKey),
}
}
// NewMnemonic returns a new mnemonic phrase.
func (kb *Keybase) NewMnemonic() (string, error) {
// read entropy seed straight from crypto.Rand and convert to mnemonic
entropySeed, err := bip39.NewEntropy(mnemonicEntropySize)
if err != nil {
return "", err
}
return bip39.NewMnemonic(entropySeed)
}
// Exist checks if the account exists.
func (kb *Keybase) Exist(name string) (bool, error) {
_, err := kb.Get(name)
if keyerror.IsErrKeyNotFound(err) {
return false, nil
}
if err != nil {
return false, err
}
return true, nil
}
// List is a lock protected version of keys.List
func (kb *Keybase) List() ([]keys.Info, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.List()
}
// Get is a lock protected version of keys.Get
func (kb *Keybase) Get(name string) (keys.Info, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.Get(name)
}
// GetByAddress is a lock protected version of keys.GetByAddress
func (kb *Keybase) GetByAddress(address types.AccAddress) (keys.Info, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.GetByAddress(address)
}
// Delete is a lock protected version of keys.Delete
func (kb *Keybase) Delete(name, passphrase string, skipPass bool) error {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.Delete(name, passphrase, skipPass)
}
// Sign is a lock protected version of keys.Sign
// it also keeps the last private key used in memory for the time set in `keepPrivTime` for performance improvement.
func (kb *Keybase) Sign(name, passphrase string, msg []byte) ([]byte, crypto.PubKey, error) {
hash := sha256.Sum256([]byte(name + ":" + passphrase))
kb.mx.Lock()
priv, ok := kb.privKeysCache[hash]
if !ok {
var err error
if priv, err = kb.kb.ExportPrivateKeyObject(name, passphrase); err != nil {
kb.mx.Unlock()
return nil, nil, err
}
kb.privKeysCache[hash] = priv
}
kb.mx.Unlock()
sig, err := priv.Sign(msg)
return sig, priv.PubKey(), err
}
// CreateMnemonic is a lock protected version of keys.CreateMnemonic
func (kb *Keybase) CreateMnemonic(name string, language keys.Language, passwd string, algo keys.SigningAlgo) (keys.Info, string, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.CreateMnemonic(name, language, passwd, algo)
}
// CreateAccount is a lock protected version of keys.CreateAccount
func (kb *Keybase) CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo keys.SigningAlgo) (keys.Info, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, hdPath, algo)
}
// CreateLedger is a lock protected version of keys.CreateLedger
func (kb *Keybase) CreateLedger(name string, algo keys.SigningAlgo, hrp string, account, index uint32) (keys.Info, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.CreateLedger(name, algo, hrp, account, index)
}
// CreateOffline is a lock protected version of keys.CreateOffline
func (kb *Keybase) CreateOffline(name string, pubkey crypto.PubKey, algo keys.SigningAlgo) (keys.Info, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.CreateOffline(name, pubkey, algo)
}
// CreateMulti is a lock protected version of keys.CreateMulti
func (kb *Keybase) CreateMulti(name string, pubkey crypto.PubKey) (keys.Info, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.CreateMulti(name, pubkey)
}
// Update is a lock protected version of keys.Update
func (kb *Keybase) Update(name, oldpass string, getNewpass func() (string, error)) error {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.Update(name, oldpass, getNewpass)
}
// Import is a lock protected version of keys.Import
func (kb *Keybase) Import(name, armor string) error {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.Import(name, armor)
}
// ImportPrivKey is a lock protected version of keys.ImportPrivKey
func (kb *Keybase) ImportPrivKey(name, armor, passphrase string) error {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.ImportPrivKey(name, armor, passphrase)
}
// ImportPubKey is a lock protected version of keys.ImportPubKey
func (kb *Keybase) ImportPubKey(name, armor string) (err error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.ImportPubKey(name, armor)
}
// Export is a lock protected version of keys.Export
func (kb *Keybase) Export(name string) (armor string, err error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.Export(name)
}
// ExportPubKey is a lock protected version of keys.ExportPubKey
func (kb *Keybase) ExportPubKey(name string) (armor string, err error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.ExportPubKey(name)
}
// ExportPrivKey is a lock protected version of keys.ExportPrivKey
func (kb *Keybase) ExportPrivKey(name, decryptPassphrase, encryptPassphrase string) (armor string, err error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.ExportPrivKey(name, decryptPassphrase, encryptPassphrase)
}
// ExportPrivateKeyObject is a lock protected version of keys.ExportPrivateKeyObject
func (kb *Keybase) ExportPrivateKeyObject(name string, passphrase string) (crypto.PrivKey, error) {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.ExportPrivateKeyObject(name, passphrase)
}
// SupportedAlgos returns a list of signing algorithms supported by the keybase
func (kb *Keybase) SupportedAlgos() []keys.SigningAlgo {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.SupportedAlgos()
}
// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration
func (kb *Keybase) SupportedAlgosLedger() []keys.SigningAlgo {
kb.mx.Lock()
defer kb.mx.Unlock()
return kb.kb.SupportedAlgosLedger()
}
// CloseDB is a lock protected version of keys.CloseDB
func (kb *Keybase) CloseDB() {
kb.mx.Lock()
defer kb.mx.Unlock()
kb.kb.CloseDB()
}