Skip to content

Commit c1f611c

Browse files
committed
Basic test working
1 parent a2f2d18 commit c1f611c

File tree

7 files changed

+120
-129
lines changed

7 files changed

+120
-129
lines changed

keystore/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ Design principles:
44
to wrap via a network layer if needed.
55
- Storage abstract. Keystore interfaces can be implemented with memory, file, database, etc. for storage to be useable in a variety of
66
contexts. Use write through caching to maintain synchronization between in memory keys and stored keys.
7-
- Only the Admin interface mutates the keystore, all other interfaces
8-
are read only.
7+
- Only the Admin interface mutates the keystore, all other interfaces are read only. Admin interface
8+
is plural/batched to support atomic batched mutations.
99
- Client side key naming. Keystore itself doesn't impose certain key algorithims/curves be used for specific contexts, it just supports a the minimum viable set of algorithms/curves for chainlink wide use cases. Clients define a name for each key which represents
1010
the context in which they wish to use it.
1111
- Common serialization/encryption for all storage types. Protobuf serialization (compact, versioned) for key material and then key material encrypted before persistence with a passphase.

keystore/admin.go

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,56 +20,37 @@ import (
2020
type CreateKeysRequest struct {
2121
Keys []CreateKeyRequest
2222
}
23-
2423
type CreateKeyRequest struct {
25-
Name string
24+
KeyName string
2625
KeyType KeyType
2726
}
28-
2927
type CreateKeysResponse struct {
3028
Keys []CreateKeyResponse
3129
}
32-
3330
type CreateKeyResponse struct {
3431
KeyInfo KeyInfo
3532
}
36-
3733
type DeleteKeysRequest struct {
38-
Names []string
34+
KeyNames []string
3935
}
4036

4137
type DeleteKeysResponse struct{}
42-
4338
type ImportKeysRequest struct {
4439
Keys []ImportKeyRequest
4540
}
46-
4741
type ImportKeyRequest struct {
48-
Name string
42+
KeyName string
4943
KeyType KeyType
5044
Data []byte
5145
}
5246

53-
type ImportKeysResponse struct {
54-
Keys []ImportKeyResponse
55-
}
56-
57-
type ImportKeyResponse struct {
58-
PublicKey []byte
59-
}
60-
47+
type ImportKeysResponse struct{}
6148
type ExportKeysRequest struct {
62-
Names []string
49+
KeyNames []string
6350
}
64-
6551
type ExportKeysResponse struct {
6652
Keys []ExportKeyResponse
6753
}
68-
69-
type ExportKeyRequest struct {
70-
Name string
71-
}
72-
7354
type ExportKeyResponse struct {
7455
KeyInfo KeyInfo
7556
Data []byte
@@ -78,14 +59,12 @@ type ExportKeyResponse struct {
7859
type SetMetadataRequest struct {
7960
Updates []SetMetadataUpdate
8061
}
81-
8262
type SetMetadataUpdate struct {
8363
KeyName string
8464
Metadata []byte
8565
}
8666

8767
type SetMetadataResponse struct{}
88-
8968
type Admin interface {
9069
CreateKeys(ctx context.Context, req CreateKeysRequest) (CreateKeysResponse, error)
9170
DeleteKeys(ctx context.Context, req DeleteKeysRequest) (DeleteKeysResponse, error)
@@ -110,32 +89,47 @@ func (ks *keystore) CreateKeys(ctx context.Context, req CreateKeysRequest) (Crea
11089
if err != nil {
11190
return CreateKeysResponse{}, fmt.Errorf("failed to generate Ed25519 key: %w", err)
11291
}
113-
ksCopy[keyReq.Name] = key{
92+
publicKey, err := publicKeyFromPrivateKey(internal.NewRaw(privateKey), keyReq.KeyType)
93+
if err != nil {
94+
return CreateKeysResponse{}, fmt.Errorf("failed to get public key from private key: %w", err)
95+
}
96+
ksCopy[keyReq.KeyName] = key{
11497
keyType: keyReq.KeyType,
11598
privateKey: internal.NewRaw(privateKey),
99+
publicKey: publicKey,
116100
createdAt: time.Now(),
117101
metadata: []byte{},
118102
}
119103
case EcdsaSecp256k1:
120-
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
104+
privateKey, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
121105
if err != nil {
122106
return CreateKeysResponse{}, fmt.Errorf("failed to generate EcdsaSecp256k1 key: %w", err)
123107
}
124-
ksCopy[keyReq.Name] = key{
108+
publicKey, err := publicKeyFromPrivateKey(internal.NewRaw(privateKey.D.Bytes()), keyReq.KeyType)
109+
if err != nil {
110+
return CreateKeysResponse{}, fmt.Errorf("failed to get public key from private key: %w", err)
111+
}
112+
ksCopy[keyReq.KeyName] = key{
125113
keyType: keyReq.KeyType,
126-
privateKey: internal.NewRaw(privateKeyECDSA.D.Bytes()),
114+
privateKey: internal.NewRaw(privateKey.D.Bytes()),
115+
publicKey: publicKey,
127116
createdAt: time.Now(),
128117
metadata: []byte{},
129118
}
130119
case X25519:
131-
encryptionKey := [curve25519.ScalarSize]byte{}
132-
_, err := rand.Read(encryptionKey[:])
120+
privateKey := [curve25519.ScalarSize]byte{}
121+
_, err := rand.Read(privateKey[:])
133122
if err != nil {
134123
return CreateKeysResponse{}, fmt.Errorf("failed to generate Curve25519 key: %w", err)
135124
}
136-
ksCopy[keyReq.Name] = key{
125+
publicKey, err := publicKeyFromPrivateKey(internal.NewRaw(privateKey[:]), keyReq.KeyType)
126+
if err != nil {
127+
return CreateKeysResponse{}, fmt.Errorf("failed to get public key from private key: %w", err)
128+
}
129+
ksCopy[keyReq.KeyName] = key{
137130
keyType: keyReq.KeyType,
138-
privateKey: internal.NewRaw(encryptionKey[:]),
131+
privateKey: internal.NewRaw(privateKey[:]),
132+
publicKey: publicKey,
139133
createdAt: time.Now(),
140134
metadata: []byte{},
141135
}
@@ -145,10 +139,10 @@ func (ks *keystore) CreateKeys(ctx context.Context, req CreateKeysRequest) (Crea
145139

146140
responses = append(responses, CreateKeyResponse{
147141
KeyInfo: KeyInfo{
148-
Name: keyReq.Name,
142+
Name: keyReq.KeyName,
149143
KeyType: keyReq.KeyType,
150-
PublicKey: ksCopy[keyReq.Name].publicKey(),
151-
Metadata: ksCopy[keyReq.Name].metadata,
144+
PublicKey: ksCopy[keyReq.KeyName].publicKey,
145+
Metadata: ksCopy[keyReq.KeyName].metadata,
152146
},
153147
})
154148
}
@@ -167,7 +161,7 @@ func (k *keystore) DeleteKeys(ctx context.Context, req DeleteKeysRequest) (Delet
167161
defer k.mu.Unlock()
168162

169163
ksCopy := maps.Clone(k.keystore)
170-
for _, name := range req.Names {
164+
for _, name := range req.KeyNames {
171165
delete(ksCopy, name)
172166
}
173167
if err := save(k.storage, k.password, ksCopy); err != nil {
@@ -184,7 +178,7 @@ func (k *keystore) ImportKeys(ctx context.Context, req ImportKeysRequest) (Impor
184178
func (k *keystore) ExportKeys(ctx context.Context, req ExportKeysRequest) (ExportKeysResponse, error) {
185179
var responses []ExportKeyResponse
186180

187-
for _, name := range req.Names {
181+
for _, name := range req.KeyNames {
188182
key, ok := k.keystore[name]
189183
if !ok {
190184
return ExportKeysResponse{}, fmt.Errorf("key not found: %s", name)
@@ -201,7 +195,7 @@ func (k *keystore) ExportKeys(ctx context.Context, req ExportKeysRequest) (Expor
201195
KeyInfo: KeyInfo{
202196
Name: name,
203197
KeyType: key.keyType,
204-
PublicKey: key.publicKey(),
198+
PublicKey: key.publicKey,
205199
Metadata: key.metadata,
206200
},
207201
Data: exportedKeyData,

keystore/admin_reader_test.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@ func TestKeystore_AdminReader(t *testing.T) {
1414
ks, err := keystore.NewKeystore(storage, "test-password")
1515
require.NoError(t, err)
1616
ctx := context.Background()
17+
var (
18+
testKeyEd25519 = "test-ed25519"
19+
testKeyEcdsaSecp256k1 = "test-ecdsa-secp256k1"
20+
testKeyX25519 = "test-x25519"
21+
)
1722

1823
req := keystore.CreateKeysRequest{
1924
Keys: []keystore.CreateKeyRequest{
20-
{Name: "test-ed25519", KeyType: keystore.Ed25519},
21-
{Name: "test-secp256k1", KeyType: keystore.EcdsaSecp256k1},
22-
{Name: "test-x25519", KeyType: keystore.X25519},
25+
{KeyName: testKeyEd25519, KeyType: keystore.Ed25519},
26+
{KeyName: testKeyEcdsaSecp256k1, KeyType: keystore.EcdsaSecp256k1},
27+
{KeyName: testKeyX25519, KeyType: keystore.X25519},
2328
},
2429
}
2530

@@ -30,12 +35,12 @@ func TestKeystore_AdminReader(t *testing.T) {
3035
expectedTypes := []keystore.KeyType{keystore.Ed25519, keystore.EcdsaSecp256k1, keystore.X25519}
3136
for i, key := range resp.Keys {
3237
require.Equal(t, expectedTypes[i], key.KeyInfo.KeyType)
33-
require.Equal(t, req.Keys[i].Name, key.KeyInfo.Name)
38+
require.Equal(t, req.Keys[i].KeyName, key.KeyInfo.Name)
3439
require.NotEmpty(t, key.KeyInfo.PublicKey, "Expected non-empty public key for %s", key.KeyInfo.Name)
3540
}
3641

3742
getReq := keystore.GetKeysRequest{
38-
Names: []string{"test-ed25519", "test-secp256k1"},
43+
KeyNames: []string{testKeyEd25519, testKeyEcdsaSecp256k1},
3944
}
4045

4146
getResp, err := ks.GetKeys(ctx, getReq)
@@ -48,13 +53,13 @@ func TestKeystore_AdminReader(t *testing.T) {
4853
require.Len(t, allKeysResp.Keys, 3)
4954

5055
deleteReq := keystore.DeleteKeysRequest{
51-
Names: []string{"test-x25519"},
56+
KeyNames: []string{testKeyX25519},
5257
}
5358

5459
_, err = ks.DeleteKeys(ctx, deleteReq)
5560
require.NoError(t, err)
5661

57-
deleteVerifyReq := keystore.GetKeysRequest{Names: []string{"test-x25519"}}
62+
deleteVerifyReq := keystore.GetKeysRequest{KeyNames: []string{testKeyX25519}}
5863
_, err = ks.GetKeys(ctx, deleteVerifyReq)
5964
require.Error(t, err)
6065

keystore/encryptor.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,14 @@ type Encryptor interface {
4343
}
4444

4545
// TODO: Encryptor implementation.
46+
func (k *keystore) Encrypt(ctx context.Context, req EncryptRequest) (EncryptResponse, error) {
47+
return EncryptResponse{}, nil
48+
}
49+
50+
func (k *keystore) Decrypt(ctx context.Context, req DecryptRequest) (DecryptResponse, error) {
51+
return DecryptResponse{}, nil
52+
}
53+
54+
func (k *keystore) DeriveSharedSecret(ctx context.Context, req DeriveSharedSecretRequest) (DeriveSharedSecretResponse, error) {
55+
return DeriveSharedSecretResponse{}, nil
56+
}

0 commit comments

Comments
 (0)