pipe passphrase to unlock key

Ciprian Dorin Craciun ciprian.craciun at gmail.com
Tue Jul 31 12:54:08 CEST 2012


On Tue, Jul 31, 2012 at 12:32 PM, Werner Koch <wk at gnupg.org> wrote:
> On Mon, 30 Jul 2012 21:15, ciprian.craciun at gmail.com said:
>>     * (preferably) implement a fake `gpg` which does the following:
>> opens a pipe as you have done in your example, writes the password and
>
> Not a good idea, because GnuPG 2.1 requires the gpg-agent and won't see
> any private key stuff.

    Not necessarily if you use the `--batch`, `--no-use-agent`, or
`--no-tty` (or a mix of the I'm not sure right now, but the manual
is.)

>> password=...
>>
>> env \
>>     GPG_PASSPHRASE_FD=<( printf -- "${password}" ) \
>>     PATH="a-folder-where-your-gpg-wrapper-is:${PATH}" \
>>     git ...
>
> This is a bad advise.  If you store the passphrase in a file, you are
> usually better off not to use a passphrase at all.

    I completely agree with you on this. But the above didn't imply
saving the password in the script... `password=...` was just a
suggestion that you need to somehow obtain the password, and then use
it with the Bash `<( ... )` feature. (Although I've suggested it might
bee leaked to the file system.)

    But on the other side, not always you have the option of running a
`gpg-agent` (for example on server side of a background job, etc.),
thus I guess this method has its uses.

    Although I once more agree with you that if you need to automate
password handling maybe it's better not to use it. The only exception
I could think of is if you hold the password entirely into memory of a
daemon process that delegates signatures, but you feed it manually at
boot-up, this way at least if someone steals your device it will have
a harder time getting your actual key. (I completely ignore the "warm"
boot attacks, root-kits or the like... As in these cases your done
fore regardless...)

    To complete my response, this is what I've replied privately to
the original poster, about the solution not involving Bash.

    Ciprian.

~~~~~~~~~~~~~~~~

    [How to give the password to `gpg` while not controlling its invocation.]

    The solution is quite simple and I think it is also portable. But
it still uses the customized `gpg` wrapper, it only solves the
potential password leaking to the file system.

    I'll just highlight the solution, the details being quite simple:
    * use the `pipe2` syscall (and use the `O_NONBLOCK` flag just to be sure);
    * write the password to the pipe, then close the write end; (the
read end is still open;)
    * (maybe be sure that the descriptor value is above or equal to 3;)
    * export an environment variable holding the file descriptor value;
    * `exec` your `git` process which will inherit the open end of the pipe;
    * (in turn your `gpg` wrapper will inherit the descriptor and the
environment variable;)

    What it gains you:
    * first of all the password is now stored only inside the pipe and
can't be recovered from the arguments or environment of the processes
(via `/proc/$pid/cmdline` or `.../environ`);
    * the password can be read exactly once by at most one process
(see below for the caveat);
    * you have no other extra process running (as would happen in the
`<( ... )` Bash solution);
    * if `gpg` would have accepted a `GPG_PASSPHRASE_FD` environment
variable you wouldn't have needed a wrapper script for `gpg`; (this
works for some other programs;)

    What it doesn't grant:
    * complete password secrecy, as anyone with proper rights (usually
any of your processes) could still quickly open `/proc/$pid/fd/$num`
and read the password;

    If you need the password multiple times, this still can still be
done but you'll have to complicate the wrapper too, by:
    * exporting both the read and write ends;
    * the wrapper executes exactly one `read` operation, it writes it
again to the write end; (it doesn't close either ends;)
    * it then creates another pipe and applies the trick as initially
described which is passed to `gpg`;
    * (this works because POSIX mandates that a write less than a page
(4kb on Linux) must match exactly a read operation, thus maintaining
data boundry;)



More information about the Gnupg-users mailing list