mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-28 20:21:47 +00:00
Expose new and list via cli
This commit is contained in:
3
Makefile
3
Makefile
@ -1,2 +1,5 @@
|
|||||||
test:
|
test:
|
||||||
go test ./...
|
go test ./...
|
||||||
|
|
||||||
|
install:
|
||||||
|
go install ./cmd/keys
|
||||||
|
21
cmd/list.go
21
cmd/list.go
@ -18,7 +18,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// listCmd represents the list command
|
// listCmd represents the list command
|
||||||
@ -28,22 +27,16 @@ var listCmd = &cobra.Command{
|
|||||||
Long: `Return a list of all public keys stored by this key manager
|
Long: `Return a list of all public keys stored by this key manager
|
||||||
along with their associated name and address.`,
|
along with their associated name and address.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// TODO: Work your own magic here
|
infos, err := manager.List()
|
||||||
fmt.Println("list called")
|
if err != nil {
|
||||||
fmt.Println(viper.Get("format"))
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
printInfos(infos)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RootCmd.AddCommand(listCmd)
|
RootCmd.AddCommand(listCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
|
||||||
|
|
||||||
// Cobra supports Persistent Flags which will work for this command
|
|
||||||
// and all subcommands, e.g.:
|
|
||||||
// listCmd.PersistentFlags().String("foo", "", "A help for foo")
|
|
||||||
|
|
||||||
// Cobra supports local flags which will only run when this command
|
|
||||||
// is called directly, e.g.:
|
|
||||||
listCmd.Flags().StringP("format", "f", "text", "Format to display (text|json)")
|
|
||||||
}
|
}
|
||||||
|
50
cmd/new.go
50
cmd/new.go
@ -22,28 +22,46 @@ import (
|
|||||||
|
|
||||||
// newCmd represents the new command
|
// newCmd represents the new command
|
||||||
var newCmd = &cobra.Command{
|
var newCmd = &cobra.Command{
|
||||||
Use: "new",
|
Use: "new <name>",
|
||||||
Short: "Create a new public/private key pair",
|
Short: "Create a new public/private key pair",
|
||||||
Long: `Add a public/private key pair to the key store.
|
Long: `Add a public/private key pair to the key store.
|
||||||
The password muts be entered in the terminal and not
|
The password muts be entered in the terminal and not
|
||||||
passed as a command line argument for security.`,
|
passed as a command line argument for security.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: newPassword,
|
||||||
// TODO: Work your own magic here
|
|
||||||
fmt.Println("new called")
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RootCmd.AddCommand(newCmd)
|
RootCmd.AddCommand(newCmd)
|
||||||
|
}
|
||||||
// Here you will define your flags and configuration settings.
|
|
||||||
|
func newPassword(cmd *cobra.Command, args []string) {
|
||||||
// Cobra supports Persistent Flags which will work for this command
|
if len(args) != 1 || len(args[0]) == 0 {
|
||||||
// and all subcommands, e.g.:
|
fmt.Print("You must provide a name for the key")
|
||||||
// newCmd.PersistentFlags().String("foo", "", "A help for foo")
|
return
|
||||||
|
}
|
||||||
// Cobra supports local flags which will only run when this command
|
name := args[0]
|
||||||
// is called directly, e.g.:
|
|
||||||
// newCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
// TODO: own function???
|
||||||
|
pass, err := getPassword("Enter a passphrase:")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pass2, err := getPassword("Repeat the passphrase:")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if pass != pass2 {
|
||||||
|
fmt.Println("Passphrases don't match")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := manager.Create(name, pass)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
printInfo(info)
|
||||||
}
|
}
|
||||||
|
33
cmd/root.go
33
cmd/root.go
@ -17,16 +17,22 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
keys "github.com/tendermint/go-keys"
|
||||||
|
"github.com/tendermint/go-keys/cryptostore"
|
||||||
|
"github.com/tendermint/go-keys/storage/filestorage"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rootDir string
|
rootDir string
|
||||||
format string
|
output string
|
||||||
|
keyDir string
|
||||||
|
manager keys.Manager
|
||||||
)
|
)
|
||||||
|
|
||||||
// RootCmd represents the base command when called without any subcommands
|
// RootCmd represents the base command when called without any subcommands
|
||||||
@ -53,7 +59,8 @@ func Execute() {
|
|||||||
func init() {
|
func init() {
|
||||||
cobra.OnInitialize(initEnv)
|
cobra.OnInitialize(initEnv)
|
||||||
RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data (default is TM_ROOT or $HOME/.tlc)")
|
RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data (default is TM_ROOT or $HOME/.tlc)")
|
||||||
RootCmd.PersistentFlags().StringP("format", "f", "text", "Output format (text|json)")
|
RootCmd.PersistentFlags().StringP("output", "o", "text", "Output format (text|json)")
|
||||||
|
RootCmd.PersistentFlags().StringP("keydir", "", "keys", "Directory to store private keys (subdir of root)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// initEnv sets to use ENV variables if set.
|
// initEnv sets to use ENV variables if set.
|
||||||
@ -85,11 +92,25 @@ func bindFlags(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
// validateFlags asserts all RootCmd flags are valid
|
// validateFlags asserts all RootCmd flags are valid
|
||||||
func validateFlags(cmd *cobra.Command) error {
|
func validateFlags(cmd *cobra.Command) error {
|
||||||
format = viper.GetString("format")
|
// validate output format
|
||||||
switch format {
|
output = viper.GetString("output")
|
||||||
|
switch output {
|
||||||
case "text", "json":
|
case "text", "json":
|
||||||
return nil
|
|
||||||
default:
|
default:
|
||||||
return errors.Errorf("Unsupported format: %s", format)
|
return errors.Errorf("Unsupported output format: %s", output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store the keys directory
|
||||||
|
keyDir = viper.GetString("keydir")
|
||||||
|
if !filepath.IsAbs(keyDir) {
|
||||||
|
keyDir = filepath.Join(rootDir, keyDir)
|
||||||
|
}
|
||||||
|
// and construct the key manager
|
||||||
|
manager = cryptostore.New(
|
||||||
|
cryptostore.GenEd25519, // TODO - cli switch???
|
||||||
|
cryptostore.SecretBox,
|
||||||
|
filestorage.New(keyDir),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
56
cmd/utils.go
Normal file
56
cmd/utils.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/bgentry/speakeasy"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
data "github.com/tendermint/go-data"
|
||||||
|
keys "github.com/tendermint/go-keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
const PassLength = 10
|
||||||
|
|
||||||
|
func getPassword(prompt string) (string, error) {
|
||||||
|
pass, err := speakeasy.Ask(prompt)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(pass) < PassLength {
|
||||||
|
return "", errors.Errorf("Password must be at least %d characters", PassLength)
|
||||||
|
}
|
||||||
|
return pass, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printInfo(info keys.Info) {
|
||||||
|
switch output {
|
||||||
|
case "text":
|
||||||
|
key, err := data.ToText(info.PubKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // really shouldn't happen...
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\t%s\n", info.Name, key)
|
||||||
|
case "json":
|
||||||
|
json, err := data.ToJSON(info)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // really shouldn't happen...
|
||||||
|
}
|
||||||
|
fmt.Println(string(json))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printInfos(infos keys.Infos) {
|
||||||
|
switch output {
|
||||||
|
case "text":
|
||||||
|
fmt.Println("All keys:")
|
||||||
|
for _, i := range infos {
|
||||||
|
printInfo(i)
|
||||||
|
}
|
||||||
|
case "json":
|
||||||
|
json, err := data.ToJSON(infos)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // really shouldn't happen...
|
||||||
|
}
|
||||||
|
fmt.Println(string(json))
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,7 @@ func (es encryptedStorage) Put(name, pass string, key crypto.PrivKey) error {
|
|||||||
return es.store.Put(name, secret, ki)
|
return es.store.Put(name, secret, ki)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.KeyInfo, error) {
|
func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.Info, error) {
|
||||||
secret, info, err := es.store.Get(name)
|
secret, info, err := es.store.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, info, err
|
return nil, info, err
|
||||||
@ -30,7 +30,7 @@ func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.KeyInfo,
|
|||||||
return key, info, err
|
return key, info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es encryptedStorage) List() ([]keys.KeyInfo, error) {
|
func (es encryptedStorage) List() (keys.Infos, error) {
|
||||||
return es.store.List()
|
return es.store.List()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,8 +39,8 @@ func (es encryptedStorage) Delete(name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// info hardcodes the encoding of keys
|
// info hardcodes the encoding of keys
|
||||||
func info(name string, key crypto.PrivKey) keys.KeyInfo {
|
func info(name string, key crypto.PrivKey) keys.Info {
|
||||||
return keys.KeyInfo{
|
return keys.Info{
|
||||||
Name: name,
|
Name: name,
|
||||||
PubKey: crypto.PubKeyS{key.PubKey()},
|
PubKey: crypto.PubKeyS{key.PubKey()},
|
||||||
}
|
}
|
||||||
|
@ -24,28 +24,28 @@ func (s Manager) assertSigner() keys.Signer {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// exists just to make sure we fulfill the KeyManager interface
|
// exists just to make sure we fulfill the Manager interface
|
||||||
func (s Manager) assertKeyManager() keys.KeyManager {
|
func (s Manager) assertKeyManager() keys.Manager {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create adds a new key to the storage engine, returning error if
|
// Create adds a new key to the storage engine, returning error if
|
||||||
// another key already stored under this name
|
// another key already stored under this name
|
||||||
func (s Manager) Create(name, passphrase string) error {
|
func (s Manager) Create(name, passphrase string) (keys.Info, error) {
|
||||||
key := s.gen.Generate()
|
key := s.gen.Generate()
|
||||||
return s.es.Put(name, passphrase, key)
|
err := s.es.Put(name, passphrase, key)
|
||||||
|
return info(name, key), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// List loads the keys from the storage and enforces alphabetical order
|
// List loads the keys from the storage and enforces alphabetical order
|
||||||
func (s Manager) List() (keys.KeyInfos, error) {
|
func (s Manager) List() (keys.Infos, error) {
|
||||||
k, err := s.es.List()
|
res, err := s.es.List()
|
||||||
res := keys.KeyInfos(k)
|
|
||||||
res.Sort()
|
res.Sort()
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the public information about one key
|
// Get returns the public information about one key
|
||||||
func (s Manager) Get(name string) (keys.KeyInfo, error) {
|
func (s Manager) Get(name string) (keys.Info, error) {
|
||||||
_, info, err := s.es.store.Get(name)
|
_, info, err := s.es.store.Get(name)
|
||||||
return info, err
|
return info, err
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,10 @@ func TestKeyManagement(t *testing.T) {
|
|||||||
// create some keys
|
// create some keys
|
||||||
_, err = cstore.Get(n1)
|
_, err = cstore.Get(n1)
|
||||||
assert.NotNil(err)
|
assert.NotNil(err)
|
||||||
err = cstore.Create(n1, p1)
|
i, err := cstore.Create(n1, p1)
|
||||||
|
require.Equal(n1, i.Name)
|
||||||
require.Nil(err)
|
require.Nil(err)
|
||||||
err = cstore.Create(n2, p2)
|
_, err = cstore.Create(n2, p2)
|
||||||
require.Nil(err)
|
require.Nil(err)
|
||||||
|
|
||||||
// we can get these keys
|
// we can get these keys
|
||||||
@ -159,7 +160,7 @@ func TestAdvancedKeyManagement(t *testing.T) {
|
|||||||
p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$"
|
p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$"
|
||||||
|
|
||||||
// make sure key works with initial password
|
// make sure key works with initial password
|
||||||
err := cstore.Create(n1, p1)
|
_, err := cstore.Create(n1, p1)
|
||||||
require.Nil(err, "%+v", err)
|
require.Nil(err, "%+v", err)
|
||||||
assertPassword(assert, cstore, n1, p1, p2)
|
assertPassword(assert, cstore, n1, p1, p2)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ func TestSortKeys(t *testing.T) {
|
|||||||
|
|
||||||
// alphabetical order is n3, n1, n2
|
// alphabetical order is n3, n1, n2
|
||||||
n1, n2, n3 := "john", "mike", "alice"
|
n1, n2, n3 := "john", "mike", "alice"
|
||||||
infos := keys.KeyInfos{
|
infos := keys.Infos{
|
||||||
info(n1, gen()),
|
info(n1, gen()),
|
||||||
info(n2, gen()),
|
info(n2, gen()),
|
||||||
info(n3, gen()),
|
info(n3, gen()),
|
||||||
|
@ -3,8 +3,8 @@ package keys
|
|||||||
// Storage has many implementation, based on security and sharing requirements
|
// Storage has many implementation, based on security and sharing requirements
|
||||||
// like disk-backed, mem-backed, vault, db, etc.
|
// like disk-backed, mem-backed, vault, db, etc.
|
||||||
type Storage interface {
|
type Storage interface {
|
||||||
Put(name string, key []byte, info KeyInfo) error
|
Put(name string, key []byte, info Info) error
|
||||||
Get(name string) ([]byte, KeyInfo, error)
|
Get(name string) ([]byte, Info, error)
|
||||||
List() ([]KeyInfo, error)
|
List() (Infos, error)
|
||||||
Delete(name string) error
|
Delete(name string) error
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func (s FileStore) assertStorage() keys.Storage {
|
|||||||
|
|
||||||
// Put creates two files, one with the public info as json, the other
|
// Put creates two files, one with the public info as json, the other
|
||||||
// with the (encoded) private key as gpg ascii-armor style
|
// with the (encoded) private key as gpg ascii-armor style
|
||||||
func (s FileStore) Put(name string, key []byte, info keys.KeyInfo) error {
|
func (s FileStore) Put(name string, key []byte, info keys.Info) error {
|
||||||
pub, priv := s.nameToPaths(name)
|
pub, priv := s.nameToPaths(name)
|
||||||
|
|
||||||
// write public info
|
// write public info
|
||||||
@ -62,10 +62,10 @@ func (s FileStore) Put(name string, key []byte, info keys.KeyInfo) error {
|
|||||||
return write(priv, name, key)
|
return write(priv, name, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get loads the keyinfo and (encoded) private key from the directory
|
// Get loads the info and (encoded) private key from the directory
|
||||||
// It uses `name` to generate the filename, and returns an error if the
|
// It uses `name` to generate the filename, and returns an error if the
|
||||||
// files don't exist or are in the incorrect format
|
// files don't exist or are in the incorrect format
|
||||||
func (s FileStore) Get(name string) ([]byte, keys.KeyInfo, error) {
|
func (s FileStore) Get(name string) ([]byte, keys.Info, error) {
|
||||||
pub, priv := s.nameToPaths(name)
|
pub, priv := s.nameToPaths(name)
|
||||||
|
|
||||||
info, err := readInfo(pub)
|
info, err := readInfo(pub)
|
||||||
@ -78,8 +78,8 @@ func (s FileStore) Get(name string) ([]byte, keys.KeyInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List parses the key directory for public info and returns a list of
|
// List parses the key directory for public info and returns a list of
|
||||||
// KeyInfo for all keys located in this directory.
|
// Info for all keys located in this directory.
|
||||||
func (s FileStore) List() ([]keys.KeyInfo, error) {
|
func (s FileStore) List() (keys.Infos, error) {
|
||||||
dir, err := os.Open(s.keyDir)
|
dir, err := os.Open(s.keyDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "List Keys")
|
return nil, errors.Wrap(err, "List Keys")
|
||||||
@ -91,7 +91,7 @@ func (s FileStore) List() ([]keys.KeyInfo, error) {
|
|||||||
|
|
||||||
// filter names for .pub ending and load them one by one
|
// filter names for .pub ending and load them one by one
|
||||||
// half the files is a good guess for pre-allocating the slice
|
// half the files is a good guess for pre-allocating the slice
|
||||||
infos := make([]keys.KeyInfo, 0, len(names)/2)
|
infos := make([]keys.Info, 0, len(names)/2)
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
if strings.HasSuffix(name, PubExt) {
|
if strings.HasSuffix(name, PubExt) {
|
||||||
p := path.Join(s.keyDir, name)
|
p := path.Join(s.keyDir, name)
|
||||||
@ -124,11 +124,11 @@ func (s FileStore) nameToPaths(name string) (pub, priv string) {
|
|||||||
return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName)
|
return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeInfo(path string, info keys.KeyInfo) error {
|
func writeInfo(path string, info keys.Info) error {
|
||||||
return write(path, info.Name, info.PubKey.Bytes())
|
return write(path, info.Name, info.PubKey.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
func readInfo(path string) (info keys.KeyInfo, err error) {
|
func readInfo(path string) (info keys.Info, err error) {
|
||||||
var data []byte
|
var data []byte
|
||||||
data, info.Name, err = read(path)
|
data, info.Name, err = read(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -23,7 +23,7 @@ func TestBasicCRUD(t *testing.T) {
|
|||||||
name := "bar"
|
name := "bar"
|
||||||
key := []byte("secret-key-here")
|
key := []byte("secret-key-here")
|
||||||
pubkey := crypto.GenPrivKeyEd25519().PubKey()
|
pubkey := crypto.GenPrivKeyEd25519().PubKey()
|
||||||
info := keys.KeyInfo{
|
info := keys.Info{
|
||||||
Name: name,
|
Name: name,
|
||||||
PubKey: crypto.PubKeyS{pubkey},
|
PubKey: crypto.PubKeyS{pubkey},
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type data struct {
|
type data struct {
|
||||||
info keys.KeyInfo
|
info keys.Info
|
||||||
key []byte
|
key []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ func (s MemStore) assertStorage() keys.Storage {
|
|||||||
|
|
||||||
// Put adds the given key, returns an error if it another key
|
// Put adds the given key, returns an error if it another key
|
||||||
// is already stored under this name
|
// is already stored under this name
|
||||||
func (s MemStore) Put(name string, key []byte, info keys.KeyInfo) error {
|
func (s MemStore) Put(name string, key []byte, info keys.Info) error {
|
||||||
if _, ok := s[name]; ok {
|
if _, ok := s[name]; ok {
|
||||||
return errors.Errorf("Key named '%s' already exists", name)
|
return errors.Errorf("Key named '%s' already exists", name)
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ func (s MemStore) Put(name string, key []byte, info keys.KeyInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the key stored under the name, or returns an error if not present
|
// Get returns the key stored under the name, or returns an error if not present
|
||||||
func (s MemStore) Get(name string) ([]byte, keys.KeyInfo, error) {
|
func (s MemStore) Get(name string) ([]byte, keys.Info, error) {
|
||||||
var err error
|
var err error
|
||||||
d, ok := s[name]
|
d, ok := s[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -48,8 +48,8 @@ func (s MemStore) Get(name string) ([]byte, keys.KeyInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List returns the public info of all keys in the MemStore in unsorted order
|
// List returns the public info of all keys in the MemStore in unsorted order
|
||||||
func (s MemStore) List() ([]keys.KeyInfo, error) {
|
func (s MemStore) List() (keys.Infos, error) {
|
||||||
res := make([]keys.KeyInfo, len(s))
|
res := make([]keys.Info, len(s))
|
||||||
i := 0
|
i := 0
|
||||||
for _, d := range s {
|
for _, d := range s {
|
||||||
res[i] = d.info
|
res[i] = d.info
|
||||||
|
@ -15,7 +15,7 @@ func TestBasicCRUD(t *testing.T) {
|
|||||||
name := "foo"
|
name := "foo"
|
||||||
key := []byte("secret-key-here")
|
key := []byte("secret-key-here")
|
||||||
pubkey := crypto.GenPrivKeyEd25519().PubKey()
|
pubkey := crypto.GenPrivKeyEd25519().PubKey()
|
||||||
info := keys.KeyInfo{
|
info := keys.Info{
|
||||||
Name: name,
|
Name: name,
|
||||||
PubKey: crypto.PubKeyS{pubkey},
|
PubKey: crypto.PubKeyS{pubkey},
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,19 @@ import (
|
|||||||
crypto "github.com/tendermint/go-crypto"
|
crypto "github.com/tendermint/go-crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyInfo is the public information about a key
|
// Info is the public information about a key
|
||||||
type KeyInfo struct {
|
type Info struct {
|
||||||
Name string
|
Name string
|
||||||
PubKey crypto.PubKeyS
|
PubKey crypto.PubKeyS
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyInfos is a wrapper to allows alphabetical sorting of the keys
|
// Infos is a wrapper to allows alphabetical sorting of the keys
|
||||||
type KeyInfos []KeyInfo
|
type Infos []Info
|
||||||
|
|
||||||
func (k KeyInfos) Len() int { return len(k) }
|
func (k Infos) Len() int { return len(k) }
|
||||||
func (k KeyInfos) Less(i, j int) bool { return k[i].Name < k[j].Name }
|
func (k Infos) Less(i, j int) bool { return k[i].Name < k[j].Name }
|
||||||
func (k KeyInfos) Swap(i, j int) { k[i], k[j] = k[j], k[i] }
|
func (k Infos) Swap(i, j int) { k[i], k[j] = k[j], k[i] }
|
||||||
func (k KeyInfos) Sort() {
|
func (k Infos) Sort() {
|
||||||
if k != nil {
|
if k != nil {
|
||||||
sort.Sort(k)
|
sort.Sort(k)
|
||||||
}
|
}
|
||||||
@ -51,11 +51,11 @@ type Signer interface {
|
|||||||
Sign(name, passphrase string, tx Signable) error
|
Sign(name, passphrase string, tx Signable) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyManager allows simple CRUD on a keystore, as an aid to signing
|
// Manager allows simple CRUD on a keystore, as an aid to signing
|
||||||
type KeyManager interface {
|
type Manager interface {
|
||||||
Create(name, passphrase string) error
|
Create(name, passphrase string) (Info, error)
|
||||||
List() (KeyInfos, error)
|
List() (Infos, error)
|
||||||
Get(name string) (KeyInfo, error)
|
Get(name string) (Info, error)
|
||||||
Update(name, oldpass, newpass string) error
|
Update(name, oldpass, newpass string) error
|
||||||
Delete(name, passphrase string) error
|
Delete(name, passphrase string) error
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user