diff --git a/core/commands/keystore.go b/core/commands/keystore.go index efa33d5d7c8..75eff41208e 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -1,11 +1,14 @@ package commands import ( + "bytes" "crypto/rand" + "errors" "fmt" "io" "sort" "strings" + "text/tabwriter" cmds "github.com/ipfs/go-ipfs/commands" @@ -28,6 +31,10 @@ type KeyOutput struct { Id string } +type KeyOutputList struct { + Keys []KeyOutput +} + var KeyGenCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Create a new keypair", @@ -125,7 +132,7 @@ var KeyGenCmd = &cmds.Command{ return nil, fmt.Errorf("expected a KeyOutput as command result") } - return strings.NewReader(k.Id), nil + return strings.NewReader(k.Id + "\n"), nil }, }, Type: KeyOutput{}, @@ -135,6 +142,9 @@ var KeyListCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List all local keypairs", }, + Options: []cmds.Option{ + cmds.BoolOption("l", "Show extra information about keys."), + }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() if err != nil { @@ -149,10 +159,52 @@ var KeyListCmd = &cmds.Command{ } sort.Strings(keys) - res.SetOutput(&stringList{keys}) + + list := make([]KeyOutput, 0, len(keys)) + + for _, key := range keys { + privKey, err := n.Repo.Keystore().Get(key) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + pubKey := privKey.GetPublic() + + pid, err := peer.IDFromPublicKey(pubKey) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + list = append(list, KeyOutput{Name: key, Id: pid.Pretty()}) + } + + res.SetOutput(&KeyOutputList{list}) }, Marshalers: cmds.MarshalerMap{ - cmds.Text: stringListMarshaler, + cmds.Text: keyOutputListMarshaler, }, - Type: stringList{}, + Type: KeyOutputList{}, +} + +func keyOutputListMarshaler(res cmds.Response) (io.Reader, error) { + withId, _, _ := res.Request().Option("l").Bool() + + list, ok := res.Output().(*KeyOutputList) + if !ok { + return nil, errors.New("failed to cast []KeyOutput") + } + + buf := new(bytes.Buffer) + w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0) + for _, s := range list.Keys { + if withId { + fmt.Fprintf(w, "%s\t%s\t\n", s.Id, s.Name) + } else { + fmt.Fprintf(w, "%s\n", s.Name) + } + } + w.Flush() + return buf, nil } diff --git a/test/sharness/t0165-keystore.sh b/test/sharness/t0165-keystore.sh new file mode 100755 index 00000000000..1d94d4f4643 --- /dev/null +++ b/test/sharness/t0165-keystore.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# Copyright (c) 2017 Jeromy Johnson +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test keystore commands" + +. lib/test-lib.sh + +test_init_ipfs + +test_key_cmd() { + test_expect_success "create a new rsa key" ' + rsahash=$(ipfs key gen foobarsa --type=rsa --size=2048) + ' + + test_expect_success "create a new ed25519 key" ' + edhash=$(ipfs key gen bazed --type=ed25519) + ' + + test_expect_success "both keys show up in list output" ' + echo bazed > list_exp && + echo foobarsa >> list_exp && + ipfs key list | sort > list_out && + test_cmp list_exp list_out + ' + + test_expect_success "key hashes show up in long list output" ' + ipfs key list -l | grep $edhash > /dev/null && + ipfs key list -l | grep $rsahash > /dev/null + ' +} + +test_key_cmd + +test_done