coreapi: Keystore API proposal
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
Dec 10, 2017 at 23:48 UTC
1b5fbb09b508c979120fe43ac21b274b73542508
3 files changed
+173
-4
core/coreapi/coreapi.go
+4
@@ -33,6 +33,10 @@ func (api *CoreAPI) Name() coreiface.NameAPI {
33
return (*NameAPI)(api)
34
}
35
36
+func (api *CoreAPI) Key() coreiface.KeyAPI {
37
+ return (*KeyAPI)(api)
38
+}
39
+
40
func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (coreiface.Node, error) {
41
p, err := api.ResolvePath(ctx, p)
42
if err != nil {
core/coreapi/interface/interface.go
+5
-4
@@ -44,6 +44,7 @@ type CoreAPI interface {
44
Unixfs() UnixfsAPI
45
Dag() DagAPI
46
Name() NameAPI
47
+ Key() KeyAPI
48
49
// ResolvePath resolves the path using Unixfs resolver
50
ResolvePath(context.Context, Path) (Path, error)
@@ -102,11 +103,11 @@ type NameAPI interface {
103
Resolve(ctx context.Context, name string, recursive bool, local bool, nocache bool) (Path, error)
104
}
105
105
-type KeyApi interface {
106
- Generate(ctx context.Context, name string, algorithm string, size int) error
106
+type KeyAPI interface {
107
+ Generate(ctx context.Context, name string, algorithm string, size int) (string, error)
108
List(ctx context.Context) (map[string]string, error) //TODO: better key type?
108
- Rename(ctx context.Context, oldName string, newName string) error
109
- Remove(ctx context.Context, name string) error
109
+ Rename(ctx context.Context, oldName string, newName string, force bool) (string, bool, error)
110
+ Remove(ctx context.Context, name string) (string, error)
111
}
112
113
// type ObjectAPI interface {
core/coreapi/key.go
new
+164
@@ -0,0 +1,164 @@
1
+package coreapi
2
+
3
+import (
4
+ "context"
5
+ "crypto/rand"
6
+ "fmt"
7
+ "sort"
8
+
9
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
10
+
11
+ peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
12
+ crypto "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
13
+)
14
+
15
+type KeyAPI CoreAPI
16
+
17
+func (api *KeyAPI) Generate(ctx context.Context, name string, algorithm string, size int) (string, error) {
18
+ var sk crypto.PrivKey
19
+ var pk crypto.PubKey
20
+
21
+ switch algorithm {
22
+ case "rsa":
23
+ if size == 0 {
24
+ return "", fmt.Errorf("please specify a key size with --size")
25
+ }
26
+
27
+ priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.RSA, size, rand.Reader)
28
+ if err != nil {
29
+ return "", err
30
+ }
31
+
32
+ sk = priv
33
+ pk = pub
34
+ case "ed25519":
35
+ priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
36
+ if err != nil {
37
+ return "", err
38
+ }
39
+
40
+ sk = priv
41
+ pk = pub
42
+ default:
43
+ return "", fmt.Errorf("unrecognized key type: %s", algorithm)
44
+ }
45
+
46
+ err := api.node.Repo.Keystore().Put(name, sk)
47
+ if err != nil {
48
+ return "", err
49
+ }
50
+
51
+ pid, err := peer.IDFromPublicKey(pk)
52
+ if err != nil {
53
+ return "", err
54
+ }
55
+
56
+ return pid.String(), nil
57
+}
58
+
59
+func (api *KeyAPI) List(ctx context.Context) (map[string]string, error) {
60
+ keys, err := api.node.Repo.Keystore().List()
61
+ if err != nil {
62
+ return nil, err
63
+ }
64
+
65
+ sort.Strings(keys)
66
+
67
+ out := make(map[string]string, len(keys)+1)
68
+ out["self"] = api.node.Identity.Pretty()
69
+
70
+ for _, key := range keys {
71
+ privKey, err := api.node.Repo.Keystore().Get(key)
72
+ if err != nil {
73
+ return nil, err
74
+ }
75
+
76
+ pubKey := privKey.GetPublic()
77
+
78
+ pid, err := peer.IDFromPublicKey(pubKey)
79
+ if err != nil {
80
+ return nil, err
81
+ }
82
+
83
+ out[key] = pid.Pretty()
84
+ }
85
+ return out, nil
86
+}
87
+
88
+func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, force bool) (string, bool, error) {
89
+ ks := api.node.Repo.Keystore()
90
+
91
+ if oldName == "self" {
92
+ return "", false, fmt.Errorf("cannot rename key with name 'self'")
93
+ }
94
+
95
+ if newName == "self" {
96
+ return "", false, fmt.Errorf("cannot overwrite key with name 'self'")
97
+ }
98
+
99
+ oldKey, err := ks.Get(oldName)
100
+ if err != nil {
101
+ return "", false, fmt.Errorf("no key named %s was found", oldName)
102
+ }
103
+
104
+ pubKey := oldKey.GetPublic()
105
+
106
+ pid, err := peer.IDFromPublicKey(pubKey)
107
+ if err != nil {
108
+ return "", false, err
109
+ }
110
+
111
+ overwrite := false
112
+ if force {
113
+ exist, err := ks.Has(newName)
114
+ if err != nil {
115
+ return "", false, err
116
+ }
117
+
118
+ if exist {
119
+ overwrite = true
120
+ err := ks.Delete(newName)
121
+ if err != nil {
122
+ return "", false, err
123
+ }
124
+ }
125
+ }
126
+
127
+ err = ks.Put(newName, oldKey)
128
+ if err != nil {
129
+ return "", false, err
130
+ }
131
+
132
+ return pid.Pretty(), overwrite, ks.Delete(oldName)
133
+}
134
+
135
+func (api *KeyAPI) Remove(ctx context.Context, name string) (string, error) {
136
+ ks := api.node.Repo.Keystore()
137
+
138
+ if name == "self" {
139
+ return "", fmt.Errorf("cannot remove key with name 'self'")
140
+ }
141
+
142
+ removed, err := ks.Get(name)
143
+ if err != nil {
144
+ return "", fmt.Errorf("no key named %s was found", name)
145
+ }
146
+
147
+ pubKey := removed.GetPublic()
148
+
149
+ pid, err := peer.IDFromPublicKey(pubKey)
150
+ if err != nil {
151
+ return "", err
152
+ }
153
+
154
+ err = ks.Delete(name)
155
+ if err != nil {
156
+ return "", err
157
+ }
158
+
159
+ return pid.Pretty(), nil
160
+}
161
+
162
+func (api *KeyAPI) core() coreiface.CoreAPI {
163
+ return (*CoreAPI)(api)
164
+}