Skip to content

Commit

Permalink
cmd/age: buffer armored ciphertext before prompting
Browse files Browse the repository at this point in the history
A partial solution, still missing bracketed paste support.

Updates #364
  • Loading branch information
FiloSottile committed Jul 12, 2022
1 parent 8a02f48 commit 36ae567
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 1 deletion.
10 changes: 10 additions & 0 deletions cmd/age/age.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 12 additions & 1 deletion cmd/age/testdata/encrypted_keys.txt
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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 --
Expand Down
10 changes: 10 additions & 0 deletions cmd/age/testdata/terminal.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 --
Expand Down
19 changes: 19 additions & 0 deletions cmd/age/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ package main
// No capitalized initials and no periods at the end.

import (
"bytes"
"errors"
"fmt"
"io"
"log"
"os"
"runtime"

"filippo.io/age/armor"
"filippo.io/age/internal/plugin"
"golang.org/x/term"
)
Expand Down Expand Up @@ -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) }

0 comments on commit 36ae567

Please sign in to comment.