@cryptotaxi247 / kubo / commits / 1b5fbb09b

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 +}