mirror of
https://github.com/FiloSottile/age.git
synced 2025-12-23 05:25:14 +00:00
cmd/age: buffer armored ciphertext before prompting
A partial solution, still missing bracketed paste support. Updates #364
This commit is contained in:
@@ -234,6 +234,16 @@ func main() {
|
||||
in = f
|
||||
} else {
|
||||
stdinInUse = true
|
||||
if decryptFlag && term.IsTerminal(int(os.Stdin.Fd())) {
|
||||
// If the input comes from a TTY, assume it's armored, and buffer up
|
||||
// to the END line (or EOF/EOT) so that a password prompt or the
|
||||
// output don't get in the way of typing the input. See Issue 364.
|
||||
buf, err := bufferTerminalInput(in)
|
||||
if err != nil {
|
||||
errorf("failed to buffer terminal input: %v", err)
|
||||
}
|
||||
in = buf
|
||||
}
|
||||
}
|
||||
if name := outFlag; name != "" && name != "-" {
|
||||
f := newLazyOpener(name)
|
||||
|
||||
13
cmd/age/testdata/encrypted_keys.txt
vendored
13
cmd/age/testdata/encrypted_keys.txt
vendored
@@ -1,4 +1,5 @@
|
||||
# TODO: age-encrypted private keys, multiple identities, -i ordering, -e -i
|
||||
# TODO: age-encrypted private keys, multiple identities, -i ordering, -e -i,
|
||||
# age file password prompt during encryption
|
||||
|
||||
[windows] skip # no pty support
|
||||
|
||||
@@ -48,6 +49,16 @@ pty terminal
|
||||
! age -d -i key_rsa_other rsa_other.age
|
||||
stderr 'mismatched private and public SSH key'
|
||||
|
||||
# buffer armored ciphertext before prompting if stdin is the terminal
|
||||
pty terminal
|
||||
age -e -i key_ed25519 -a -o test.age input
|
||||
exec cat test.age terminal # concatenated ciphertext + password
|
||||
pty -stdin stdout
|
||||
age -d -i key_ed25519
|
||||
ptyout 'Enter passphrase'
|
||||
! stderr .
|
||||
cmp stdout input
|
||||
|
||||
-- input --
|
||||
test
|
||||
-- terminal --
|
||||
|
||||
10
cmd/age/testdata/terminal.txt
vendored
10
cmd/age/testdata/terminal.txt
vendored
@@ -37,6 +37,16 @@ pty terminal
|
||||
age -d test.age
|
||||
cmp stdout input
|
||||
|
||||
# buffer armored ciphertext before prompting if stdin is the terminal
|
||||
pty terminal
|
||||
age -p -a -o test.age input
|
||||
exec cat test.age terminal # concatenated ciphertext + password
|
||||
pty -stdin stdout
|
||||
age -d
|
||||
ptyout 'Enter passphrase'
|
||||
! stderr .
|
||||
cmp stdout input
|
||||
|
||||
-- input --
|
||||
test
|
||||
-- terminal --
|
||||
|
||||
@@ -14,6 +14,7 @@ package main
|
||||
// No capitalized initials and no periods at the end.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"filippo.io/age/armor"
|
||||
"filippo.io/age/internal/plugin"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
@@ -205,3 +207,20 @@ var pluginTerminalUI = &plugin.ClientUI{
|
||||
printf("waiting on %s plugin...", name)
|
||||
},
|
||||
}
|
||||
|
||||
func bufferTerminalInput(in io.Reader) (io.Reader, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
if _, err := buf.ReadFrom(ReaderFunc(func(p []byte) (n int, err error) {
|
||||
if bytes.Contains(buf.Bytes(), []byte(armor.Footer+"\n")) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return in.Read(p)
|
||||
})); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
type ReaderFunc func(p []byte) (n int, err error)
|
||||
|
||||
func (f ReaderFunc) Read(p []byte) (n int, err error) { return f(p) }
|
||||
|
||||
Reference in New Issue
Block a user