Skip to content

Commit a154305

Browse files
authored
Merge pull request #536 from okp4/feat/cli-keys-did
Feat/cli keys did
2 parents 5b92c7d + 47539aa commit a154305

File tree

18 files changed

+583
-188
lines changed

18 files changed

+583
-188
lines changed

client/keys/did.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package keys
2+
3+
import (
4+
"encoding/base64"
5+
"encoding/hex"
6+
"fmt"
7+
8+
"github.com/spf13/cobra"
9+
10+
errorsmod "cosmossdk.io/errors"
11+
12+
"github.com/cosmos/cosmos-sdk/types/errors"
13+
"github.com/cosmos/cosmos-sdk/version"
14+
15+
"github.com/okp4/okp4d/x/logic/util"
16+
)
17+
18+
var flagPubKeyType = "type"
19+
20+
func DIDCmd() *cobra.Command {
21+
cmd := &cobra.Command{
22+
Use: fmt.Sprintf("did [pubkey] -t [{%s, %s}]", util.KeyAlgEd25519, util.KeyAlgSecp256k1),
23+
Short: fmt.Sprintf("Give the did:key from a %s or %s pubkey (hex, base64)", util.KeyAlgEd25519, util.KeyAlgSecp256k1),
24+
Long: fmt.Sprintf(`Give the did:key from a %s or %s pubkey given as hex or base64 encoded string.
25+
26+
Example:
27+
28+
$ %s keys did "AtD+mbIUqu615Grk1loWI6ldnQzs1X1nP35MmhmsB1K8" -t %s
29+
$ %s keys did 02d0fe99b214aaeeb5e46ae4d65a1623a95d9d0cecd57d673f7e4c9a19ac0752bc -t %s
30+
`, util.KeyAlgEd25519, util.KeyAlgSecp256k1, version.AppName, util.KeyAlgSecp256k1, version.AppName, util.KeyAlgSecp256k1),
31+
Args: cobra.ExactArgs(1),
32+
RunE: func(cmd *cobra.Command, args []string) error {
33+
pubkeyType, err := cmd.Flags().GetString(flagPubKeyType)
34+
if err != nil {
35+
return err
36+
}
37+
pubkeyAlgo, err := util.ParseKeyAlg(pubkeyType)
38+
if err != nil {
39+
return errorsmod.Wrapf(errors.ErrInvalidType,
40+
"invalid pubkey type; expected oneof %+q", []util.KeyAlg{util.KeyAlgSecp256k1, util.KeyAlgEd25519})
41+
}
42+
bs, err := getBytesFromString(args[0])
43+
if err != nil {
44+
return err
45+
}
46+
pubKey, err := util.BytesToPubKey(bs, pubkeyAlgo)
47+
if err != nil {
48+
return errorsmod.Wrapf(errors.ErrInvalidPubKey, "failed to make pubkey from %s; %s", args[0], err)
49+
}
50+
did, err := util.CreateDIDKeyByPubKey(pubKey)
51+
if err != nil {
52+
return errorsmod.Wrapf(errors.ErrInvalidPubKey, "failed to make did:key from %s; %s", args[0], err)
53+
}
54+
55+
cmd.Println(did)
56+
57+
return nil
58+
},
59+
}
60+
cmd.Flags().StringP(flagPubKeyType, "t", util.KeyAlgSecp256k1.String(),
61+
fmt.Sprintf("Pubkey type to decode (oneof %s, %s)", util.KeyAlgEd25519, util.KeyAlgSecp256k1))
62+
return cmd
63+
}
64+
65+
func getBytesFromString(pubKey string) ([]byte, error) {
66+
if bz, err := hex.DecodeString(pubKey); err == nil {
67+
return bz, nil
68+
}
69+
70+
if bz, err := base64.StdEncoding.DecodeString(pubKey); err == nil {
71+
return bz, nil
72+
}
73+
74+
return nil, errorsmod.Wrapf(errors.ErrInvalidPubKey,
75+
"pubkey '%s' invalid; expected hex or base64 encoding of correct size", pubKey)
76+
}

client/keys/list.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package keys
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
8+
"github.com/spf13/cobra"
9+
"sigs.k8s.io/yaml"
10+
11+
"github.com/cosmos/cosmos-sdk/client"
12+
"github.com/cosmos/cosmos-sdk/client/flags"
13+
"github.com/cosmos/cosmos-sdk/client/keys"
14+
cryptokeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
15+
16+
"github.com/okp4/okp4d/x/logic/util"
17+
)
18+
19+
const (
20+
flagListNames = "list-names"
21+
ListCmdName = "list"
22+
)
23+
24+
// KeyOutput is the output format for keys when listing them.
25+
// It is an improved copy of the KeyOutput from the keys module (github.com/cosmos/cosmos-sdk/client/keys/types.go).
26+
type KeyOutput struct {
27+
keys.KeyOutput
28+
DID string `json:"did,omitempty" yaml:"did"`
29+
}
30+
31+
// ListKeysCmd lists all keys in the key store with additional info, such as the did:key equivalent of the public key.
32+
// This is an improved copy of the ListKeysCmd from the keys module.
33+
func ListKeysCmd() *cobra.Command {
34+
cmd := &cobra.Command{
35+
Use: ListCmdName,
36+
Short: "List all keys",
37+
Long: `Return a list of all public keys stored by this key manager
38+
along with their associated name, address and decentralized identifier (for supported public key algorithms)`,
39+
RunE: runListCmd,
40+
}
41+
42+
cmd.Flags().BoolP(flagListNames, "n", false, "List names only")
43+
return cmd
44+
}
45+
46+
func runListCmd(cmd *cobra.Command, _ []string) error {
47+
clientCtx, err := client.GetClientQueryContext(cmd)
48+
if err != nil {
49+
return err
50+
}
51+
52+
records, err := clientCtx.Keyring.List()
53+
if err != nil {
54+
return err
55+
}
56+
57+
if len(records) == 0 && clientCtx.OutputFormat == flags.OutputFormatText {
58+
cmd.Println("No records were found in keyring")
59+
return nil
60+
}
61+
62+
if ok, _ := cmd.Flags().GetBool(flagListNames); !ok {
63+
return printKeyringRecords(cmd.OutOrStdout(), records, clientCtx.OutputFormat)
64+
}
65+
66+
for _, k := range records {
67+
cmd.Println(k.Name)
68+
}
69+
70+
return nil
71+
}
72+
73+
func printKeyringRecords(w io.Writer, records []*cryptokeyring.Record, output string) error {
74+
kos, err := mkKeyOutput(records)
75+
if err != nil {
76+
return err
77+
}
78+
79+
switch output {
80+
case flags.OutputFormatText:
81+
if err := printTextRecords(w, kos); err != nil {
82+
return err
83+
}
84+
85+
case flags.OutputFormatJSON:
86+
out, err := json.Marshal(kos)
87+
if err != nil {
88+
return err
89+
}
90+
91+
if _, err := fmt.Fprintf(w, "%s", out); err != nil {
92+
return err
93+
}
94+
}
95+
96+
return nil
97+
}
98+
99+
func printTextRecords(w io.Writer, kos []KeyOutput) error {
100+
out, err := yaml.Marshal(&kos)
101+
if err != nil {
102+
return err
103+
}
104+
105+
if _, err := fmt.Fprintln(w, string(out)); err != nil {
106+
return err
107+
}
108+
109+
return nil
110+
}
111+
112+
func mkKeyOutput(records []*cryptokeyring.Record) ([]KeyOutput, error) {
113+
kos := make([]KeyOutput, len(records))
114+
115+
for i, r := range records {
116+
kko, err := keys.MkAccKeyOutput(r)
117+
if err != nil {
118+
return nil, err
119+
}
120+
pk, err := r.GetPubKey()
121+
if err != nil {
122+
return nil, err
123+
}
124+
did, _ := util.CreateDIDKeyByPubKey(pk)
125+
126+
kos[i] = KeyOutput{
127+
KeyOutput: kko,
128+
DID: did,
129+
}
130+
}
131+
132+
return kos, nil
133+
}

client/keys/root.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package keys
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
)
6+
7+
// Enhance augment the given command which is assumed to be the root command of the 'list' command.
8+
// It will:
9+
// - add the 'did' command.
10+
// - replace the original 'list' command with our own 'list' command which will list all did:key.
11+
func Enhance(cmd *cobra.Command) *cobra.Command {
12+
cmd.AddCommand(
13+
DIDCmd(),
14+
)
15+
16+
for i, c := range cmd.Commands() {
17+
if c.Name() == ListCmdName {
18+
cmd.RemoveCommand(cmd.Commands()[i])
19+
cmd.AddCommand(ListKeysCmd())
20+
break
21+
}
22+
}
23+
24+
return cmd
25+
}

cmd/okp4d/cmd/root.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242

4343
"github.com/okp4/okp4d/app"
4444
appparams "github.com/okp4/okp4d/app/params"
45+
okp4keys "github.com/okp4/okp4d/client/keys"
4546
)
4647

4748
// NewRootCmd creates a new root command for a Cosmos SDK application.
@@ -180,7 +181,7 @@ func initRootCmd(
180181
genesisCommand(encodingConfig.TxConfig, basicManager),
181182
queryCommand(),
182183
txCommand(),
183-
keys.Commands(),
184+
okp4keys.Enhance(keys.Commands()),
184185
)
185186
}
186187

docs/command/okp4d_keys.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ The pass backend requires GnuPG: [https://gnupg.org/](https://gnupg.org/)
4040
* [okp4d](okp4d.md) - OKP4 Daemon 👹
4141
* [okp4d keys add](okp4d_keys_add.md) - Add an encrypted private key (either newly generated or recovered), encrypt it, and save to <name> file
4242
* [okp4d keys delete](okp4d_keys_delete.md) - Delete the given keys
43+
* [okp4d keys did](okp4d_keys_did.md) - Give the did:key from a ed25519 or secp256k1 pubkey (hex, base64)
4344
* [okp4d keys export](okp4d_keys_export.md) - Export private keys
4445
* [okp4d keys import](okp4d_keys_import.md) - Import private keys into the local keybase
4546
* [okp4d keys import-hex](okp4d_keys_import-hex.md) - Import private keys into the local keybase

docs/command/okp4d_keys_did.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## okp4d keys did
2+
3+
Give the did:key from a ed25519 or secp256k1 pubkey (hex, base64)
4+
5+
### Synopsis
6+
7+
Give the did:key from a ed25519 or secp256k1 pubkey given as hex or base64 encoded string.
8+
9+
Example:
10+
11+
$ okp4d keys did "AtD+mbIUqu615Grk1loWI6ldnQzs1X1nP35MmhmsB1K8" -t secp256k1
12+
$ okp4d keys did 02d0fe99b214aaeeb5e46ae4d65a1623a95d9d0cecd57d673f7e4c9a19ac0752bc -t secp256k1
13+
14+
```
15+
okp4d keys did [pubkey] -t [{ed25519, secp256k1}] [flags]
16+
```
17+
18+
### Options
19+
20+
```
21+
-h, --help help for did
22+
-t, --type string Pubkey type to decode (oneof ed25519, secp256k1) (default "secp256k1")
23+
```
24+
25+
### Options inherited from parent commands
26+
27+
```
28+
--keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "test")
29+
--keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used
30+
--output string Output format (text|json) (default "text")
31+
```
32+
33+
### SEE ALSO
34+
35+
* [okp4d keys](okp4d_keys.md) - Manage your application's keys

docs/command/okp4d_keys_list.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ List all keys
55
### Synopsis
66

77
Return a list of all public keys stored by this key manager
8-
along with their associated name and address.
8+
along with their associated name, address and decentralized identifier (for supported public key algorithms)
99

1010
```
1111
okp4d keys list [flags]

go.mod

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ require (
3232
github.com/golang/protobuf v1.5.3
3333
github.com/grpc-ecosystem/grpc-gateway v1.16.0
3434
github.com/hashicorp/go-metrics v0.5.3
35+
github.com/hyperledger/aries-framework-go v0.3.2
3536
github.com/ichiban/prolog v1.1.3
3637
github.com/ignite/cli v0.27.2
3738
github.com/nuts-foundation/go-did v0.4.0
@@ -86,7 +87,9 @@ require (
8687
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
8788
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
8889
github.com/bits-and-blooms/bitset v1.8.0 // indirect
90+
github.com/btcsuite/btcd v0.22.0-beta // indirect
8991
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
92+
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect
9093
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
9194
github.com/cespare/xxhash v1.1.0 // indirect
9295
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -129,6 +132,7 @@ require (
129132
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
130133
github.com/go-git/go-billy/v5 v5.5.0 // indirect
131134
github.com/go-git/go-git/v5 v5.11.0 // indirect
135+
github.com/go-jose/go-jose/v3 v3.0.1-0.20221117193127-916db76e8214 // indirect
132136
github.com/go-kit/kit v0.12.0 // indirect
133137
github.com/go-kit/log v0.2.1 // indirect
134138
github.com/go-logfmt/logfmt v0.6.0 // indirect
@@ -166,6 +170,11 @@ require (
166170
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
167171
github.com/huandu/skiplist v1.2.0 // indirect
168172
github.com/huandu/xstrings v1.3.3 // indirect
173+
github.com/hyperledger/aries-framework-go/component/kmscrypto v0.0.0-20230427134832-0c9969493bd3 // indirect
174+
github.com/hyperledger/aries-framework-go/component/log v0.0.0-20230427134832-0c9969493bd3 // indirect
175+
github.com/hyperledger/aries-framework-go/component/models v0.0.0-20230501135648-a9a7ad029347 // indirect
176+
github.com/hyperledger/aries-framework-go/component/storageutil v0.0.0-20230901120639-e17eddd3ad3e // indirect
177+
github.com/hyperledger/aries-framework-go/spi v0.0.0-20230427134832-0c9969493bd3 // indirect
169178
github.com/iancoleman/strcase v0.3.0 // indirect
170179
github.com/imdario/mergo v0.3.15 // indirect
171180
github.com/improbable-eng/grpc-web v0.15.0 // indirect
@@ -175,6 +184,7 @@ require (
175184
github.com/jmhodges/levigo v1.0.0 // indirect
176185
github.com/jtolds/gls v4.20.0+incompatible // indirect
177186
github.com/kevinburke/ssh_config v1.2.0 // indirect
187+
github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 // indirect
178188
github.com/klauspost/compress v1.17.4 // indirect
179189
github.com/kr/pretty v0.3.1 // indirect
180190
github.com/kr/text v0.2.0 // indirect
@@ -200,16 +210,22 @@ require (
200210
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
201211
github.com/mitchellh/mapstructure v1.5.0 // indirect
202212
github.com/mitchellh/reflectwalk v1.0.0 // indirect
213+
github.com/mr-tron/base58 v1.2.0 // indirect
203214
github.com/mtibben/percent v0.2.1 // indirect
215+
github.com/multiformats/go-base32 v0.1.0 // indirect
216+
github.com/multiformats/go-base36 v0.1.0 // indirect
217+
github.com/multiformats/go-multibase v0.1.1 // indirect
204218
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
205219
github.com/ockam-network/did v0.1.4-0.20210103172416-02ae01ce06d8 // indirect
206220
github.com/oklog/run v1.1.0 // indirect
207221
github.com/opencontainers/go-digest v1.0.0 // indirect
208222
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
209223
github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect
224+
github.com/piprate/json-gold v0.5.0 // indirect
210225
github.com/pjbgf/sha1cd v0.3.0 // indirect
211226
github.com/pkg/errors v0.9.1 // indirect
212227
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
228+
github.com/pquerna/cachecontrol v0.1.0 // indirect
213229
github.com/princjef/mageutil v1.0.0 // indirect
214230
github.com/prometheus/client_model v0.5.0 // indirect
215231
github.com/prometheus/common v0.45.0 // indirect
@@ -234,10 +250,14 @@ require (
234250
github.com/subosito/gotenv v1.6.0 // indirect
235251
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
236252
github.com/tendermint/go-amino v0.16.0 // indirect
253+
github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 // indirect
237254
github.com/tidwall/btree v1.7.0 // indirect
238255
github.com/ulikunitz/xz v0.5.11 // indirect
239256
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
240257
github.com/xanzy/ssh-agent v0.3.3 // indirect
258+
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
259+
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
260+
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
241261
github.com/zondax/hid v0.9.2 // indirect
242262
github.com/zondax/ledger-go v0.14.3 // indirect
243263
go.etcd.io/bbolt v1.3.8 // indirect

0 commit comments

Comments
 (0)