2

I'm seeking to pipe passwords into gpg for symmetric encryption, but it acts as if I did not pipe anything, and still asks me for the password and to re-enter it.

Here is what I'm trying (with 'enter' being the password):

(echo 'enter'; echo 'enter') | gpg -c test.py

Why isn't this working?

I already know you can use --batch --yes --passphrase='enter', but that will show the password in the task in the task manager (and so seems less secure—tell me if I'm wrong).

EDIT: I just realized that echo would still probably show up in the task manager, too (just separately from the gpg command). So, to get around that, I could save the password to a temporary file and use cat myPasswordFile instead of echo myPassword. That way, they'd have to get the password in real-time from the temporary file (while it exists) instead of just logging all the tasks that have run and obtaining the password at their leisure.

1 Answer 1

6

You can use --passphrase-fd 0 to tell gpg to read the password from stdin. That should get along well with pipes. Don't send it twice; that's only required for typo detection when you're doing it interactively.

Normally gpg reads from the tty so you can redirect both input and output and still have the ability to enter a passphrase.

In a normal login session, your shell is connected to the terminal by 3 file descriptors: stdin, stdout, and stderr. Pipes and redirection operators change where those file descriptors point.

If you run a command without any redirection operators, all of its file descriptors are inherited from the shell. When it reads from stdin, it's reading from the tty.

If you run the same command with a < redirection operator, its stdin is connected to the file whose name appears after the <. If you put a command on the right side of a | operator, its stdin is connected to a pipe file descriptor (whose opposite end is connected to the stdout of the command on the left side of the |.)

That's the stuff you probably already knew. What you didn't know is that in addition to file descriptors, there's another thing that links terminals and processes: the controlling terminal. Your shell process has a controlling terminal, and it's inherited by all child processes, including in this case your gpg.

When a program wants to get keyboard input from the user in spite of the fact that stdin is not a terminal, it can access its controlling terminal by opening the special file /dev/tty.

One kind of program that depends heavily on this feature is a pager (e.g. more, less). If you run somecommand | less, what less wants to do is read some input from the pipe on stdin, display the first screenful, and then read from the keyboard to wait for you to press a key to tell it what to do next. stdin can't be both the pipe and the keyboard, so less opens /dev/tty.

The controlling terminal for a process is listed in the TTY column by ps.

2
  • It works! :) e.g. echo enter|gpg --passphrase-fd 0 -c myFile.txt. It tells me this afterward, just for the record: Reading passphrase from file descriptor 0. So, you solved my problem (thank you very much), but I'm still curious what input it's reading from if not the standard input (and why). Feb 17, 2016 at 0:18
  • 1
    you also could do GPG=$(tty) before that to affect same result Feb 17, 2016 at 2:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .