Python, Subprocess, GPG and Standard Input
A discussion around having the gpg command tell the passphrase from data when both are expected to be supplied on stdin, and ways to achieve this in Python.
1 Both the Passphrase and Data Through Standard Input
As the gpg
command can take both data and a passphrase from stdin, one might be wondering how to make both available to it. While it turns out writing first the passphrase, then the data to stdin seems to work I've never seen this method advertised. So I decided that only writing data to stdin and providing the passphrase by giving the gpg
command a file descriptor might be more desirable.
2 Using Pipes
But what's a safe way to write a passphrase to file? Even if you use encrypted filesystems, using the tempfile
module to write a temporary file and having it deleted immediately after you're done isn't really satisfying.
Thankfully, there's a better way, still: pipes. A discussion on Stack Overflow entitled Python/POpen/gpg: Supply passphrase and encryption text both through stdin or file descriptor explains how a snippet similar to this one will work like a charm:
rpipe, wpipe = os.pipe()
os.write(wpipe, passphrase)
os.close(wpipe)
tarproc = subprocess.Popen(tarcmd, stdout=subprocess.PIPE)
gpgproc = subprocess.Popen(gpgcmd + [str(rpipe)], stdin=tarproc.stdout)
gpgproc.communicate()
tarproc.communicate()
os.close(rpipe)
I found it interesting to see that str(rpipe)
is usually a relatively low number. You'll also notice in that Stack Overflow discussion referred to below that one example suggests adding a newline at the end of the passphrase: I didn't find that necessary in practice.