From 3c7c7891bc67ccad52a438807f59d99143f76deb Mon Sep 17 00:00:00 2001 From: Finn Date: Fri, 19 Mar 2021 04:13:03 -0700 Subject: [PATCH] Add some tools to manipluate keys --- cmd/signaldctl/cmd/key/list/list-keys.go | 93 +++++++++++++++++ cmd/signaldctl/cmd/key/qr/qr-key.go | 115 ++++++++++++++++++++++ cmd/signaldctl/cmd/key/root.go | 35 +++++++ cmd/signaldctl/cmd/key/trust/trust-key.go | 76 ++++++++++++++ cmd/signaldctl/cmd/root.go | 2 + 5 files changed, 321 insertions(+) create mode 100644 cmd/signaldctl/cmd/key/list/list-keys.go create mode 100644 cmd/signaldctl/cmd/key/qr/qr-key.go create mode 100644 cmd/signaldctl/cmd/key/root.go create mode 100644 cmd/signaldctl/cmd/key/trust/trust-key.go diff --git a/cmd/signaldctl/cmd/key/list/list-keys.go b/cmd/signaldctl/cmd/key/list/list-keys.go new file mode 100644 index 0000000..d77766a --- /dev/null +++ b/cmd/signaldctl/cmd/key/list/list-keys.go @@ -0,0 +1,93 @@ +// Copyright © 2021 Finn Herzfeld +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package list + +import ( + "encoding/json" + "log" + "os" + + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" + + "gitlab.com/signald/signald-go/cmd/signaldctl/common" + "gitlab.com/signald/signald-go/cmd/signaldctl/config" + "gitlab.com/signald/signald-go/signald/client-protocol/v1" +) + +var ( + account string + address v1.JsonAddress + ListKeysCmd = &cobra.Command{ + Use: "list ", + Short: "list all keys for an account", + PreRun: func(cmd *cobra.Command, args []string) { + if account == "" { + account = config.Config.DefaultAccount + } + if account == "" { + common.Must(cmd.Help()) + log.Fatal("No account specified. Please specify with --account or set a default") + } + if len(args) != 1 { + common.Must(cmd.Help()) + log.Fatal("please specify an address") + } + address = common.StringToAddress(args[0]) + }, + Run: func(_ *cobra.Command, _ []string) { + go common.Signald.Listen(nil) + req := v1.GetIdentitiesRequest{Account: account, Address: &address} + resp, err := req.Submit(common.Signald) + if err != nil { + log.Fatal(err, "error communicating with signald") + } + + switch common.OutputFormat { + case common.OutputFormatJSON: + err := json.NewEncoder(os.Stdout).Encode(resp) + if err != nil { + log.Fatal(err, "error encoding response to stdout") + } + case common.OutputFormatYAML: + err := yaml.NewEncoder(os.Stdout).Encode(resp) + if err != nil { + log.Fatal(err, "error encoding response to stdout") + } + case common.OutputFormatCSV, common.OutputFormatTable, common.OutputFormatDefault: + t := table.NewWriter() + t.SetOutputMirror(os.Stdout) + t.AppendHeader(table.Row{"Safety Number", "Trust Level"}) + for _, identity := range resp.Identities { + t.AppendRow(table.Row{identity.SafetyNumber, identity.TrustLevel}) + } + if common.OutputFormat == common.OutputFormatCSV { + t.RenderCSV() + } else { + common.StylizeTable(t) + t.Render() + } + default: + log.Fatal("Unsupported output format") + } + }, + } +) + +func init() { + ListKeysCmd.Flags().StringVarP(&account, "account", "a", "", "the signald account to use") +} diff --git a/cmd/signaldctl/cmd/key/qr/qr-key.go b/cmd/signaldctl/cmd/key/qr/qr-key.go new file mode 100644 index 0000000..205db36 --- /dev/null +++ b/cmd/signaldctl/cmd/key/qr/qr-key.go @@ -0,0 +1,115 @@ +// Copyright © 2021 Finn Herzfeld +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package qr + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "log" + "os" + + "github.com/mdp/qrterminal" + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" + + "gitlab.com/signald/signald-go/cmd/signaldctl/common" + "gitlab.com/signald/signald-go/cmd/signaldctl/config" + "gitlab.com/signald/signald-go/signald/client-protocol/v1" +) + +var ( + account string + address v1.JsonAddress + safetyNumber string + QRKeyCmd = &cobra.Command{ + Use: "qr []", + Short: "show the QR code of another user's safety number that can be scanned. Uses the newest safety number by default, but an older safety number may be optionally requested", + PreRun: func(cmd *cobra.Command, args []string) { + if account == "" { + account = config.Config.DefaultAccount + } + if account == "" { + common.Must(cmd.Help()) + log.Fatal("No account specified. Please specify with --account or set a default") + } + if len(args) == 0 { + common.Must(cmd.Help()) + log.Fatal("please specify an address") + } + address = common.StringToAddress(args[0]) + if len(args) > 1 { + safetyNumber = args[1] + } + }, + Run: func(_ *cobra.Command, _ []string) { + go common.Signald.Listen(nil) + req := v1.GetIdentitiesRequest{Account: account, Address: &address} + resp, err := req.Submit(common.Signald) + if err != nil { + log.Fatal(err, "error communicating with signald") + } + + var identity *v1.IdentityKey + for _, i := range resp.Identities { + if safetyNumber == "" { + if identity == nil || i.Added > identity.Added { + identity = i + } + } else if i.SafetyNumber == safetyNumber { + identity = i + } + } + if identity == nil { + log.Fatal("no matching identity found") + } + + switch common.OutputFormat { + case common.OutputFormatJSON: + err := json.NewEncoder(os.Stdout).Encode(identity.QrCodeData) + if err != nil { + log.Fatal(err, "error encoding response to stdout") + } + case common.OutputFormatYAML: + err := yaml.NewEncoder(os.Stdout).Encode(identity.QrCodeData) + if err != nil { + log.Fatal(err, "error encoding response to stdout") + } + case common.OutputFormatQR, common.OutputFormatDefault: + qrDataBytes, err := base64.StdEncoding.DecodeString(identity.QrCodeData) + if err != nil { + log.Fatal("Error decoding qr code data: ", err) + } + qrterminal.Generate(string(qrDataBytes), qrterminal.L, os.Stdout) + fmt.Println("\nSafety Number: ") + for i, n := range identity.SafetyNumber { + fmt.Printf("%c", n) + if i%30 == 29 { + fmt.Println() + } else if i%5 == 4 { + fmt.Print(" ") + } + } + default: + log.Fatal("Unsupported output format") + } + }, + } +) + +func init() { + QRKeyCmd.Flags().StringVarP(&account, "account", "a", "", "the signald account to use") +} diff --git a/cmd/signaldctl/cmd/key/root.go b/cmd/signaldctl/cmd/key/root.go new file mode 100644 index 0000000..f18109a --- /dev/null +++ b/cmd/signaldctl/cmd/key/root.go @@ -0,0 +1,35 @@ +// Copyright © 2021 Finn Herzfeld +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package key + +import ( + "github.com/spf13/cobra" + + "gitlab.com/signald/signald-go/cmd/signaldctl/cmd/key/list" + "gitlab.com/signald/signald-go/cmd/signaldctl/cmd/key/qr" + "gitlab.com/signald/signald-go/cmd/signaldctl/cmd/key/trust" +) + +var KeyCmd = &cobra.Command{ + Use: "key", + Aliases: []string{"keys"}, +} + +func init() { + KeyCmd.AddCommand(list.ListKeysCmd) + KeyCmd.AddCommand(qr.QRKeyCmd) + KeyCmd.AddCommand(trust.TrustKeyCmd) +} diff --git a/cmd/signaldctl/cmd/key/trust/trust-key.go b/cmd/signaldctl/cmd/key/trust/trust-key.go new file mode 100644 index 0000000..6dd0195 --- /dev/null +++ b/cmd/signaldctl/cmd/key/trust/trust-key.go @@ -0,0 +1,76 @@ +// Copyright © 2021 Finn Herzfeld +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package trust + +import ( + "log" + "strings" + + "github.com/spf13/cobra" + + "gitlab.com/signald/signald-go/cmd/signaldctl/common" + "gitlab.com/signald/signald-go/cmd/signaldctl/config" + "gitlab.com/signald/signald-go/signald/client-protocol/v1" +) + +var ( + account string + address v1.JsonAddress + safetyNumber string + level string + TrustKeyCmd = &cobra.Command{ + Use: "trust [level]", + Short: "set the trust level of another user's safety number (", + PreRun: func(cmd *cobra.Command, args []string) { + if account == "" { + account = config.Config.DefaultAccount + } + if account == "" { + common.Must(cmd.Help()) + log.Fatal("No account specified. Please specify with --account or set a default") + } + if len(args) < 2 { + common.Must(cmd.Help()) + log.Fatal("please specify an address and a safety number") + } + address = common.StringToAddress(args[0]) + safetyNumber = args[1] + if len(args) > 2 { + level = strings.ToUpper(args[2]) + } else { + level = "TRUSTED_VERIFIED" + } + }, + Run: func(_ *cobra.Command, _ []string) { + go common.Signald.Listen(nil) + req := v1.TrustRequest{ + Account: account, + Address: &address, + SafetyNumber: safetyNumber, + TrustLevel: level, + } + err := req.Submit(common.Signald) + if err != nil { + log.Fatal("error from signald: ", err) + } + log.Println("success") + }, + } +) + +func init() { + TrustKeyCmd.Flags().StringVarP(&account, "account", "a", "", "the signald account to use") +} diff --git a/cmd/signaldctl/cmd/root.go b/cmd/signaldctl/cmd/root.go index 9cca471..eb70b74 100644 --- a/cmd/signaldctl/cmd/root.go +++ b/cmd/signaldctl/cmd/root.go @@ -26,6 +26,7 @@ import ( configcmd "gitlab.com/signald/signald-go/cmd/signaldctl/cmd/config" "gitlab.com/signald/signald-go/cmd/signaldctl/cmd/device" "gitlab.com/signald/signald-go/cmd/signaldctl/cmd/group" + "gitlab.com/signald/signald-go/cmd/signaldctl/cmd/key" "gitlab.com/signald/signald-go/cmd/signaldctl/cmd/message" "gitlab.com/signald/signald-go/cmd/signaldctl/common" "gitlab.com/signald/signald-go/cmd/signaldctl/config" @@ -77,6 +78,7 @@ func init() { RootCmd.AddCommand(configcmd.ConfigCmd) RootCmd.AddCommand(device.DeviceCmd) RootCmd.AddCommand(group.GroupCmd) + RootCmd.AddCommand(key.KeyCmd) RootCmd.AddCommand(message.MessageCmd) }