Commit 1b5fbb09 authored by Łukasz Magiera's avatar Łukasz Magiera

coreapi: Keystore API proposal

License: MIT
Signed-off-by: default avatarŁukasz Magiera <magik6k@gmail.com>
parent 027f498b
......@@ -33,6 +33,10 @@ func (api *CoreAPI) Name() coreiface.NameAPI {
return (*NameAPI)(api)
}
func (api *CoreAPI) Key() coreiface.KeyAPI {
return (*KeyAPI)(api)
}
func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (coreiface.Node, error) {
p, err := api.ResolvePath(ctx, p)
if err != nil {
......
......@@ -44,6 +44,7 @@ type CoreAPI interface {
Unixfs() UnixfsAPI
Dag() DagAPI
Name() NameAPI
Key() KeyAPI
// ResolvePath resolves the path using Unixfs resolver
ResolvePath(context.Context, Path) (Path, error)
......@@ -102,11 +103,11 @@ type NameAPI interface {
Resolve(ctx context.Context, name string, recursive bool, local bool, nocache bool) (Path, error)
}
type KeyApi interface {
Generate(ctx context.Context, name string, algorithm string, size int) error
type KeyAPI interface {
Generate(ctx context.Context, name string, algorithm string, size int) (string, error)
List(ctx context.Context) (map[string]string, error) //TODO: better key type?
Rename(ctx context.Context, oldName string, newName string) error
Remove(ctx context.Context, name string) error
Rename(ctx context.Context, oldName string, newName string, force bool) (string, bool, error)
Remove(ctx context.Context, name string) (string, error)
}
// type ObjectAPI interface {
......
package coreapi
import (
"context"
"crypto/rand"
"fmt"
"sort"
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
crypto "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
)
type KeyAPI CoreAPI
func (api *KeyAPI) Generate(ctx context.Context, name string, algorithm string, size int) (string, error) {
var sk crypto.PrivKey
var pk crypto.PubKey
switch algorithm {
case "rsa":
if size == 0 {
return "", fmt.Errorf("please specify a key size with --size")
}
priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.RSA, size, rand.Reader)
if err != nil {
return "", err
}
sk = priv
pk = pub
case "ed25519":
priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
if err != nil {
return "", err
}
sk = priv
pk = pub
default:
return "", fmt.Errorf("unrecognized key type: %s", algorithm)
}
err := api.node.Repo.Keystore().Put(name, sk)
if err != nil {
return "", err
}
pid, err := peer.IDFromPublicKey(pk)
if err != nil {
return "", err
}
return pid.String(), nil
}
func (api *KeyAPI) List(ctx context.Context) (map[string]string, error) {
keys, err := api.node.Repo.Keystore().List()
if err != nil {
return nil, err
}
sort.Strings(keys)
out := make(map[string]string, len(keys)+1)
out["self"] = api.node.Identity.Pretty()
for _, key := range keys {
privKey, err := api.node.Repo.Keystore().Get(key)
if err != nil {
return nil, err
}
pubKey := privKey.GetPublic()
pid, err := peer.IDFromPublicKey(pubKey)
if err != nil {
return nil, err
}
out[key] = pid.Pretty()
}
return out, nil
}
func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, force bool) (string, bool, error) {
ks := api.node.Repo.Keystore()
if oldName == "self" {
return "", false, fmt.Errorf("cannot rename key with name 'self'")
}
if newName == "self" {
return "", false, fmt.Errorf("cannot overwrite key with name 'self'")
}
oldKey, err := ks.Get(oldName)
if err != nil {
return "", false, fmt.Errorf("no key named %s was found", oldName)
}
pubKey := oldKey.GetPublic()
pid, err := peer.IDFromPublicKey(pubKey)
if err != nil {
return "", false, err
}
overwrite := false
if force {
exist, err := ks.Has(newName)
if err != nil {
return "", false, err
}
if exist {
overwrite = true
err := ks.Delete(newName)
if err != nil {
return "", false, err
}
}
}
err = ks.Put(newName, oldKey)
if err != nil {
return "", false, err
}
return pid.Pretty(), overwrite, ks.Delete(oldName)
}
func (api *KeyAPI) Remove(ctx context.Context, name string) (string, error) {
ks := api.node.Repo.Keystore()
if name == "self" {
return "", fmt.Errorf("cannot remove key with name 'self'")
}
removed, err := ks.Get(name)
if err != nil {
return "", fmt.Errorf("no key named %s was found", name)
}
pubKey := removed.GetPublic()
pid, err := peer.IDFromPublicKey(pubKey)
if err != nil {
return "", err
}
err = ks.Delete(name)
if err != nil {
return "", err
}
return pid.Pretty(), nil
}
func (api *KeyAPI) core() coreiface.CoreAPI {
return (*CoreAPI)(api)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment