cmd/age-keygen: add -y mode to convert identity file to recipients

Copied -y from ssh-keygen. Copied the INPUT as only optional argument
from cmd/age.

Fixes #122
Closes #146
This commit is contained in:
Filippo Valsorda
2021-03-09 20:42:20 -05:00
committed by Filippo Valsorda
parent a81357c237
commit f3fdc33c9e

View File

@@ -9,6 +9,7 @@ package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"runtime/debug"
@@ -20,9 +21,11 @@ import (
const usage = `Usage:
age-keygen [-o OUTPUT]
age-keygen -y [-o OUTPUT] [INPUT]
Options:
-o, --output OUTPUT Write the key to the file at path OUTPUT.
-o, --output OUTPUT Write the result to the file at path OUTPUT.
-y Convert an identity file to a recipients file.
age-keygen generates a new standard X25519 key pair, and outputs it to
standard output or to the OUTPUT file.
@@ -30,6 +33,10 @@ standard output or to the OUTPUT file.
If an OUTPUT file is specified, the public key is printed to standard error.
If OUTPUT already exists, it is not overwritten.
In -y mode, age-keygen reads an identity file from INPUT or from standard
input and writes the corresponding recipient(s) to OUTPUT or to standard
output, one per line, with no comments.
Examples:
$ age-keygen
@@ -38,7 +45,10 @@ Examples:
AGE-SECRET-KEY-1N9JEPW6DWJ0ZQUDX63F5A03GX8QUW7PXDE39N8UYF82VZ9PC8UFS3M7XA9
$ age-keygen -o key.txt
Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p`
Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
$ age-keygen -y key.txt
age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p`
// Version can be set at link time to override debug.BuildInfo.Main.Version,
// which is "(devel)" when building from within the module. See
@@ -50,17 +60,21 @@ func main() {
flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n", usage) }
var (
versionFlag bool
outFlag string
versionFlag, convertFlag bool
outFlag string
)
flag.BoolVar(&versionFlag, "version", false, "print the version")
flag.BoolVar(&convertFlag, "y", false, "convert identities to recipients")
flag.StringVar(&outFlag, "o", "", "output to `FILE` (default stdout)")
flag.StringVar(&outFlag, "output", "", "output to `FILE` (default stdout)")
flag.Parse()
if len(flag.Args()) != 0 {
if len(flag.Args()) != 0 && !convertFlag {
log.Fatalf("age-keygen takes no arguments")
}
if len(flag.Args()) > 1 && convertFlag {
log.Fatalf("Too many arguments")
}
if versionFlag {
if Version != "" {
fmt.Println(Version)
@@ -90,7 +104,21 @@ func main() {
}
}
generate(out)
in := os.Stdin
if inFile := flag.Arg(0); inFile != "" && inFile != "-" {
f, err := os.Open(inFile)
if err != nil {
log.Fatalf("Failed to open input file %q: %v", inFile, err)
}
defer f.Close()
in = f
}
if convertFlag {
convert(in, out)
} else {
generate(out)
}
}
func generate(out *os.File) {
@@ -107,3 +135,20 @@ func generate(out *os.File) {
fmt.Fprintf(out, "# public key: %s\n", k.Recipient())
fmt.Fprintf(out, "%s\n", k)
}
func convert(in io.Reader, out io.Writer) {
ids, err := age.ParseIdentities(in)
if err != nil {
log.Fatalf("Failed to parse input: %v", err)
}
if len(ids) == 0 {
log.Fatalf("No identities found in the input")
}
for _, id := range ids {
id, ok := id.(*age.X25519Identity)
if !ok {
log.Fatalf("Internal error: unexpected identity type: %T", id)
}
fmt.Fprintf(out, "%s\n", id.Recipient())
}
}