Skip to content

Commit

Permalink
cmd/age-keygen: add -y mode to convert identity file to recipients
Browse files Browse the repository at this point in the history
Copied -y from ssh-keygen. Copied the INPUT as only optional argument
from cmd/age.

Fixes #122
Closes #146
  • Loading branch information
FiloSottile committed Mar 10, 2021
1 parent a81357c commit f3fdc33
Showing 1 changed file with 51 additions and 6 deletions.
57 changes: 51 additions & 6 deletions cmd/age-keygen/keygen.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"runtime/debug"
Expand All @@ -20,16 +21,22 @@ 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.
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
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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) {
Expand All @@ -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())
}
}

0 comments on commit f3fdc33

Please sign in to comment.