Ssh – How to use tty allocation to run GPG through SSH

gpgsshtty

I am trying to encrypt and sign a local file using a distant GPG installation via SSH:

pv file | ssh -tt [ssh server] gpg -se -r [receipt key] > file.gpg

Using the double t option removes the gpg "cannot open '/dev/tty': No such device or address" error. However, instead of being sent to the input of gpg, the content to be encrypted is printed right after the ssh password prompt. Then the input is closed, and so it hangs on gpg asking the password to unlock the private key for signing (or the ssh connection is closed if the file is too large).

What is the proper way to pass data to the input of an interactive command executed through SSH?

Best Answer

Piping data into ssh (like you did) is the right way of passing input data to a command executed via SSH.

The issue here is that gpg needs two input streams to read from:

  • one (STDIN) to read the data to be encrypted,
  • another one (the interactive terminal /dev/tty) to read the passphrase (which is why you need to pass the -t option to ssh).

If you conflate the two and try to use STDIN for both purposes, then a way to signal EOF is needed to separate the two inputs. However, ssh would read the end-of-file too, and close the forwarded input stream.

The only practical workaround I can imagine is save the data to a file and then encrypt it using gpg (requires two separate ssh invocations)::

pv file | ssh ... '(umask 077; cat > file.unencrypted)'
ssh -t ... 'gpg -se -r ... < file.unecrypted > file.gpg; rm -f file.unencrypted'
Related Question