Add new command: `imgmod key show`
show - Displays JSON describing one or more keys
Usage:
imgmod key show <key-file> [key-files...] [flags]
diff --git a/cli/key_cmds.go b/cli/key_cmds.go
new file mode 100644
index 0000000..4f6cf7a
--- /dev/null
+++ b/cli/key_cmds.go
@@ -0,0 +1,98 @@
+package cli
+
+import (
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+
+ "github.com/apache/mynewt-artifact/errors"
+ "github.com/spf13/cobra"
+
+ "mynewt.apache.org/imgmod/ikey"
+)
+
+func keyDescToJson(path string, body []byte, desc ikey.Desc) (string, error) {
+ type Key struct {
+ Path string `json:"path"`
+ Type string `json:"type"`
+ Algorithm string `json:"algorithm"`
+ Hash string `json:"hash"`
+ FileSha256 string `json:"file_sha256"`
+ }
+
+ var typ string
+ if desc.Private {
+ typ = "private"
+ } else {
+ typ = "public"
+ }
+
+ h := sha256.Sum256(body)
+ fileHash := h[:]
+
+ k := Key{
+ Path: path,
+ Type: typ,
+ Algorithm: desc.Algorithm,
+ Hash: hex.EncodeToString(desc.Hash),
+ FileSha256: hex.EncodeToString(fileHash),
+ }
+
+ j, err := json.MarshalIndent(k, "", " ")
+ if err != nil {
+ return "", errors.Wrapf(err,
+ "internal error: failed to marshal key description")
+ }
+
+ return string(j), nil
+}
+
+func runKeyShowCmd(cmd *cobra.Command, args []string) {
+ if len(args) < 1 {
+ ImgmodUsage(cmd, nil)
+ }
+
+ for i, arg := range args {
+ bin, err := ioutil.ReadFile(arg)
+ if err != nil {
+ ImgmodUsage(nil, err)
+ }
+
+ desc, err := ikey.KeyBytesToDesc(bin)
+ if err != nil {
+ ImgmodUsage(nil, errors.Wrapf(err, "file: \"%s\"", arg))
+ }
+
+ j, err := keyDescToJson(arg, bin, desc)
+ if err != nil {
+ ImgmodUsage(nil, err)
+ }
+
+ fmt.Printf("%s", j)
+ if i < len(args)-1 {
+ fmt.Printf(",")
+ }
+ fmt.Printf("\n")
+ }
+}
+
+func AddKeyCommands(cmd *cobra.Command) {
+ keyCmd := &cobra.Command{
+ Use: "key",
+ Short: "Manipulates image keys",
+ Run: func(cmd *cobra.Command, args []string) {
+ cmd.Usage()
+ },
+ }
+ cmd.AddCommand(keyCmd)
+
+ showCmd := &cobra.Command{
+ Use: "show <key-file> [key-files...]",
+ Short: "Displays JSON describing one or more keys",
+ Run: runKeyShowCmd,
+ }
+
+ keyCmd.AddCommand(showCmd)
+}
diff --git a/ikey/ikey.go b/ikey/ikey.go
new file mode 100644
index 0000000..043d097
--- /dev/null
+++ b/ikey/ikey.go
@@ -0,0 +1,52 @@
+package ikey
+
+import (
+ "fmt"
+
+ "github.com/apache/mynewt-artifact/sec"
+ "github.com/pkg/errors"
+)
+
+type Desc struct {
+ Private bool
+ Algorithm string
+ PubBytes []byte
+ Hash []byte
+}
+
+func signKeyToDesc(key sec.PubSignKey, private bool) (Desc, error) {
+ var alg string
+ if key.Rsa != nil {
+ alg = fmt.Sprintf("RSA-%d", key.Rsa.Size()*8)
+ } else if key.Ec != nil {
+ alg = fmt.Sprintf("ECDSA-%d", key.Ec.X.BitLen())
+ } else {
+ alg = "ED25519"
+ }
+
+ pubBytes, err := key.Bytes()
+ if err != nil {
+ return Desc{}, err
+ }
+
+ return Desc{
+ Private: private,
+ Algorithm: alg,
+ PubBytes: pubBytes,
+ Hash: sec.RawKeyHash(pubBytes),
+ }, nil
+}
+
+func KeyBytesToDesc(keyBytes []byte) (Desc, error) {
+ pubsk, err := sec.ParsePubSignKey(keyBytes)
+ if err == nil {
+ return signKeyToDesc(pubsk, false)
+ }
+
+ privsk, err := sec.ParsePrivSignKey(keyBytes)
+ if err == nil {
+ return signKeyToDesc(privsk.PubKey(), true)
+ }
+
+ return Desc{}, errors.Errorf("unrecognized key type")
+}
diff --git a/imgmod.go b/imgmod.go
index 14f3692..b3e2bb0 100644
--- a/imgmod.go
+++ b/imgmod.go
@@ -75,6 +75,7 @@
cli.AddImageCommands(imgmodCmd)
cli.AddMfgCommands(imgmodCmd)
+ cli.AddKeyCommands(imgmodCmd)
imgmodCmd.Execute()
}