-
Notifications
You must be signed in to change notification settings - Fork 0
/
krab.go
116 lines (106 loc) · 2.83 KB
/
krab.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
package krab
import (
"bytes"
"errors"
"strings"
"github.com/RTradeLtd/crypto/v2"
datastore "github.com/ipfs/go-datastore"
ds "github.com/ipfs/go-datastore"
namespace "github.com/ipfs/go-datastore/namespace"
"github.com/ipfs/go-datastore/query"
kstore "github.com/ipfs/go-ipfs-keystore"
ci "github.com/libp2p/go-libp2p-core/crypto"
)
// compile time check for interface compatability
var _ kstore.Keystore = (*Keystore)(nil)
// Keystore is used to manage an encrypted IPFS keystore
type Keystore struct {
em *crypto.EncryptManager
ds datastore.Batching
}
// NewKeystore is used to create a new krab ipfs keystore manager
func NewKeystore(ds datastore.Batching, passphrase string) (*Keystore, error) {
wrapDS := namespace.Wrap(ds, datastore.NewKey("/krabkeystore"))
return &Keystore{
em: crypto.NewEncryptManager(passphrase),
ds: wrapDS,
}, nil
}
// Has is used to check whether or not the given key name exists
func (km *Keystore) Has(name string) (bool, error) {
if err := validateName(name); err != nil {
return false, err
}
if has, err := km.ds.Has(ds.NewKey(name)); err != nil {
return false, err
} else if !has {
return false, errors.New(ErrNoSuchKey)
}
return true, nil
}
// Put is used to store a key in our keystore
func (km *Keystore) Put(name string, privKey ci.PrivKey) error {
if err := validateName(name); err != nil {
return err
}
if has, err := km.Has(name); err == nil {
return errors.New(ErrKeyExists)
} else if has {
return errors.New(ErrKeyExists)
}
pkBytes, err := privKey.Bytes()
if err != nil {
return err
}
reader := bytes.NewReader(pkBytes)
// encrypt the private key
encryptedPK, err := km.em.Encrypt(reader)
if err != nil {
return err
}
return km.ds.Put(ds.NewKey(name), encryptedPK)
}
// Get is used to retrieve a key from our keystore
func (km *Keystore) Get(name string) (ci.PrivKey, error) {
if err := validateName(name); err != nil {
return nil, err
}
if has, err := km.Has(name); err != nil {
return nil, err
} else if !has {
return nil, errors.New(ErrNoSuchKey)
}
encryptedPKBytes, err := km.ds.Get(ds.NewKey(name))
if err != nil {
return nil, err
}
reader := bytes.NewReader(encryptedPKBytes)
pkBytes, err := km.em.Decrypt(reader)
if err != nil {
return nil, err
}
return ci.UnmarshalPrivateKey(pkBytes)
}
// Delete is used to remove a key from our keystore
func (km *Keystore) Delete(name string) error {
if err := validateName(name); err != nil {
return err
}
return km.ds.Delete(ds.NewKey(name))
}
// List is used to list all key identifiers in our keystore
func (km *Keystore) List() ([]string, error) {
entries, err := km.ds.Query(query.Query{})
if err != nil {
return nil, err
}
keys, err := entries.Rest()
if err != nil {
return nil, err
}
var ids []string
for _, v := range keys {
ids = append(ids, strings.Split(v.Key, "/")[1])
}
return ids, nil
}