mirror of
https://github.com/FiloSottile/age.git
synced 2026-01-03 10:55:14 +00:00
cmd/age: support "-R -" if stdin is not in use
This commit is contained in:
committed by
Filippo Valsorda
parent
dc8716d8fc
commit
4147b86ac8
12
README.md
12
README.md
@@ -69,6 +69,8 @@ age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg
|
||||
$ age -R recipients.txt example.jpg > example.jpg.age
|
||||
```
|
||||
|
||||
If the argument to `-R` (or `-i`) is `-`, the file is read from standard input.
|
||||
|
||||
### Passphrases
|
||||
|
||||
Files can be encrypted with a passphrase by using `-p/--passphrase`. By default age will automatically generate a secure passphrase. Passphrase protected files are automatically detected at decrypt time.
|
||||
@@ -92,6 +94,16 @@ $ age -d -i ~/.ssh/id_ed25519 example.jpg.age > example.jpg
|
||||
|
||||
Note that SSH key support employs more complex cryptography, and embeds a public key tag in the encrypted file, making it possible to track files that are encrypted to a specific public key.
|
||||
|
||||
#### Encrypting to a GitHub user
|
||||
|
||||
Combining SSH key support and `-R`, you can easily encrypt a file to the SSH keys listed on a GitHub profile.
|
||||
|
||||
```
|
||||
$ curl https://github.com/benjojo.keys | age -R - example.jpg > example.jpg.age
|
||||
```
|
||||
|
||||
Keep in mind that people might not protect SSH keys long-term, since they are revokable when used only for authentication, and that SSH keys held on YubiKeys can't be used to decrypt files.
|
||||
|
||||
## Installation
|
||||
|
||||
On macOS or Linux, you can use Homebrew:
|
||||
|
||||
@@ -241,14 +241,7 @@ func encryptKeys(keys, files []string, in io.Reader, out io.Writer, armor bool)
|
||||
recipients = append(recipients, r)
|
||||
}
|
||||
for _, name := range files {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
logFatalf("Error: failed to open recipient file: %v", err)
|
||||
}
|
||||
recs, err := parseRecipients(f, func(format string, a ...interface{}) {
|
||||
a = append([]interface{}{name}, a...)
|
||||
_log.Printf("Warning: recipients file %q: "+format, a...)
|
||||
})
|
||||
recs, err := parseRecipientsFile(name)
|
||||
if err != nil {
|
||||
logFatalf("Error: failed to parse recipient file %q: %v", name, err)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -32,7 +33,23 @@ func parseRecipient(arg string) (age.Recipient, error) {
|
||||
return nil, fmt.Errorf("unknown recipient type: %q", arg)
|
||||
}
|
||||
|
||||
func parseRecipients(f io.Reader, warnf func(string, ...interface{})) ([]age.Recipient, error) {
|
||||
func parseRecipientsFile(name string) ([]age.Recipient, error) {
|
||||
var f *os.File
|
||||
if name == "-" {
|
||||
if stdinInUse {
|
||||
return nil, fmt.Errorf("standard input is used for multiple purposes")
|
||||
}
|
||||
stdinInUse = true
|
||||
f = os.Stdin
|
||||
} else {
|
||||
var err error
|
||||
f, err = os.Open(name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open recipient file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
|
||||
const recipientFileSizeLimit = 16 << 20 // 16 MiB
|
||||
const lineLengthLimit = 8 << 10 // 8 KiB, same as sshd(8)
|
||||
var recs []age.Recipient
|
||||
@@ -45,26 +62,26 @@ func parseRecipients(f io.Reader, warnf func(string, ...interface{})) ([]age.Rec
|
||||
continue
|
||||
}
|
||||
if len(line) > lineLengthLimit {
|
||||
return nil, fmt.Errorf("line %d is too long", n)
|
||||
return nil, fmt.Errorf("%q: line %d is too long", name, n)
|
||||
}
|
||||
r, err := parseRecipient(line)
|
||||
if err != nil {
|
||||
if t, ok := sshKeyType(line); ok {
|
||||
// Skip unsupported but valid SSH public keys with a warning.
|
||||
warnf("ignoring unsupported SSH key of type %q at line %d", t, n)
|
||||
log.Printf("Warning: recipients file %q: ignoring unsupported SSH key of type %q at line %d", name, t, n)
|
||||
continue
|
||||
}
|
||||
// Hide the error since it might unintentionally leak the contents
|
||||
// of confidential files.
|
||||
return nil, fmt.Errorf("malformed recipient at line %d", n)
|
||||
return nil, fmt.Errorf("%q: malformed recipient at line %d", name, n)
|
||||
}
|
||||
recs = append(recs, r)
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to read recipients file: %v", err)
|
||||
return nil, fmt.Errorf("%q: failed to read recipients file: %v", name, err)
|
||||
}
|
||||
if len(recs) == 0 {
|
||||
return nil, fmt.Errorf("no recipients found")
|
||||
return nil, fmt.Errorf("%q: no recipients found", name)
|
||||
}
|
||||
return recs, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user