-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
csa.go
182 lines (156 loc) · 3.91 KB
/
csa.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
package keystore
import (
"fmt"
"github.com/pkg/errors"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey"
)
//go:generate mockery --quiet --name CSA --output mocks/ --case=underscore
// ErrCSAKeyExists describes the error when the CSA key already exists
var ErrCSAKeyExists = errors.New("can only have 1 CSA key")
// type CSAKeystoreInterface interface {
type CSA interface {
Get(id string) (csakey.KeyV2, error)
GetAll() ([]csakey.KeyV2, error)
Create() (csakey.KeyV2, error)
Add(key csakey.KeyV2) error
Delete(id string) (csakey.KeyV2, error)
Import(keyJSON []byte, password string) (csakey.KeyV2, error)
Export(id string, password string) ([]byte, error)
EnsureKey() error
GetV1KeysAsV2() ([]csakey.KeyV2, error)
}
type csa struct {
*keyManager
}
var _ CSA = &csa{}
func newCSAKeyStore(km *keyManager) *csa {
return &csa{
km,
}
}
func (ks *csa) Get(id string) (csakey.KeyV2, error) {
ks.lock.RLock()
defer ks.lock.RUnlock()
if ks.isLocked() {
return csakey.KeyV2{}, ErrLocked
}
return ks.getByID(id)
}
func (ks *csa) GetAll() (keys []csakey.KeyV2, _ error) {
ks.lock.RLock()
defer ks.lock.RUnlock()
if ks.isLocked() {
return nil, ErrLocked
}
for _, key := range ks.keyRing.CSA {
keys = append(keys, key)
}
return keys, nil
}
func (ks *csa) Create() (csakey.KeyV2, error) {
ks.lock.Lock()
defer ks.lock.Unlock()
if ks.isLocked() {
return csakey.KeyV2{}, ErrLocked
}
// Ensure you can only have one CSA at a time. This is a temporary
// restriction until we are able to handle multiple CSA keys in the
// communication channel
if len(ks.keyRing.CSA) > 0 {
return csakey.KeyV2{}, ErrCSAKeyExists
}
key, err := csakey.NewV2()
if err != nil {
return csakey.KeyV2{}, err
}
return key, ks.safeAddKey(key)
}
func (ks *csa) Add(key csakey.KeyV2) error {
ks.lock.Lock()
defer ks.lock.Unlock()
if ks.isLocked() {
return ErrLocked
}
if len(ks.keyRing.CSA) > 0 {
return ErrCSAKeyExists
}
return ks.safeAddKey(key)
}
func (ks *csa) Delete(id string) (csakey.KeyV2, error) {
ks.lock.Lock()
defer ks.lock.Unlock()
if ks.isLocked() {
return csakey.KeyV2{}, ErrLocked
}
key, err := ks.getByID(id)
if err != nil {
return csakey.KeyV2{}, err
}
err = ks.safeRemoveKey(key)
return key, err
}
func (ks *csa) Import(keyJSON []byte, password string) (csakey.KeyV2, error) {
ks.lock.Lock()
defer ks.lock.Unlock()
if ks.isLocked() {
return csakey.KeyV2{}, ErrLocked
}
key, err := csakey.FromEncryptedJSON(keyJSON, password)
if err != nil {
return csakey.KeyV2{}, errors.Wrap(err, "CSAKeyStore#ImportKey failed to decrypt key")
}
if _, found := ks.keyRing.CSA[key.ID()]; found {
return csakey.KeyV2{}, fmt.Errorf("key with ID %s already exists", key.ID())
}
return key, ks.keyManager.safeAddKey(key)
}
func (ks *csa) Export(id string, password string) ([]byte, error) {
ks.lock.RLock()
defer ks.lock.RUnlock()
if ks.isLocked() {
return nil, ErrLocked
}
key, err := ks.getByID(id)
if err != nil {
return nil, err
}
return key.ToEncryptedJSON(password, ks.scryptParams)
}
// EnsureKey verifies whether the CSA key has been seeded, if not, it creates it.
func (ks *csa) EnsureKey() error {
ks.lock.Lock()
defer ks.lock.Unlock()
if ks.isLocked() {
return ErrLocked
}
if len(ks.keyRing.CSA) > 0 {
return nil
}
key, err := csakey.NewV2()
if err != nil {
return err
}
ks.logger.Infof("Created CSA key with ID %s", key.ID())
return ks.safeAddKey(key)
}
func (ks *csa) GetV1KeysAsV2() (keys []csakey.KeyV2, _ error) {
v1Keys, err := ks.orm.GetEncryptedV1CSAKeys()
if err != nil {
return keys, err
}
for _, keyV1 := range v1Keys {
err := keyV1.Unlock(ks.password)
if err != nil {
return keys, err
}
keys = append(keys, keyV1.ToV2())
}
return keys, nil
}
func (ks *csa) getByID(id string) (csakey.KeyV2, error) {
key, found := ks.keyRing.CSA[id]
if !found {
return csakey.KeyV2{}, KeyNotFoundError{ID: id, KeyType: "CSA"}
}
return key, nil
}