Files
x/internal/cli/cbk.go
T

83 lines
2.1 KiB
Go

package cli
import (
"fmt"
"io"
"github.com/spf13/cobra"
"sneak.berlin/go/x/pkg/cbk"
)
// maxMnemonicInputBytes bounds how much of stdin `cbk derive` will read; a
// 24-word mnemonic is well under 300 bytes.
const maxMnemonicInputBytes = 64 << 10
// newCBKCommand returns `sutil cbk`, the parent of the crypto_box
// keypair commands.
func newCBKCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "cbk",
Short: "crypto_box keypairs derived from BIP39 mnemonics",
}
cmd.AddCommand(newCBKDeriveCommand())
return cmd
}
// newCBKDeriveCommand returns `sutil cbk derive`.
func newCBKDeriveCommand() *cobra.Command {
var publicOnly bool
cmd := &cobra.Command{
Use: "derive",
Short: "Derive a crypto_box keypair from a mnemonic read on stdin",
Long: `Reads a BIP39 mnemonic from stdin, in any letter case and with any
whitespace between words, and prints the crypto_box keypair derived from it
as hex. The same mnemonic always yields the same keypair.
The mnemonic is read from stdin rather than taken as an argument so that it
does not end up in shell history or process listings:
sutil generate mnemonic > mnemonic.txt
sutil cbk derive < mnemonic.txt`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
input := io.LimitReader(cmd.InOrStdin(), maxMnemonicInputBytes)
mnemonic, err := io.ReadAll(input)
if err != nil {
return fmt.Errorf("reading mnemonic from stdin: %w", err)
}
keypair, err := cbk.New(cbk.Params{Mnemonic: string(mnemonic)})
if err != nil {
return err
}
return writeKeypair(cmd.OutOrStdout(), keypair, publicOnly)
},
}
cmd.Flags().BoolVar(&publicOnly, "public", false, "print only the public key")
return cmd
}
// writeKeypair prints the keypair as labeled hex lines, or just the bare
// public key when publicOnly is set.
func writeKeypair(w io.Writer, keypair cbk.CryptoBoxKeypair, publicOnly bool) error {
if publicOnly {
_, err := fmt.Fprintln(w, keypair.PublicKeyHex())
return err
}
_, err := fmt.Fprintf(
w, "public: %s\nprivate: %s\n", keypair.PublicKeyHex(), keypair.PrivateKeyHex(),
)
return err
}