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
|
in = f
|
||||||
} else {
|
} else {
|
||||||
stdinInUse = true
|
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 != "-" {
|
if name := outFlag; name != "" && name != "-" {
|
||||||
f := newLazyOpener(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
|
[windows] skip # no pty support
|
||||||
|
|
||||||
@@ -48,6 +49,16 @@ pty terminal
|
|||||||
! age -d -i key_rsa_other rsa_other.age
|
! age -d -i key_rsa_other rsa_other.age
|
||||||
stderr 'mismatched private and public SSH key'
|
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 --
|
-- input --
|
||||||
test
|
test
|
||||||
-- terminal --
|
-- 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
|
age -d test.age
|
||||||
cmp stdout input
|
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 --
|
-- input --
|
||||||
test
|
test
|
||||||
-- terminal --
|
-- terminal --
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ package main
|
|||||||
// No capitalized initials and no periods at the end.
|
// No capitalized initials and no periods at the end.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -21,6 +22,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"filippo.io/age/armor"
|
||||||
"filippo.io/age/internal/plugin"
|
"filippo.io/age/internal/plugin"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
@@ -205,3 +207,20 @@ var pluginTerminalUI = &plugin.ClientUI{
|
|||||||
printf("waiting on %s plugin...", name)
|
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