pipe passphrase to unlock key

Ciprian Dorin Craciun ciprian.craciun at gmail.com
Mon Jul 30 21:15:55 CEST 2012


On Wed, Jun 27, 2012 at 8:42 PM, Face <falazemi at gmail.com> wrote:
> Hell all,
>
> I am trying  to pipe my passphrase to unlock the key. my problem is
> like this, when I use git
> to sign a tag gnupg ask for the passphrase and i need to pipe the passphrase.
>
> I try
> echo "my long passphrase" | git tag -s 1.0.0.42 -m 'version 1.0.0.1'
>
> however it did not work.
>
>
> is there is any workaround for my problem ?
>
>
> Any help would be much appreciated.
>
> Sincerely,
> falazemi
>
> note: using pinentry-curses


    Hope my feedback is not too late... But either way I don't think
it would help too much as neither solution is straight-forward...

    So the only workaround -- that I know of, but I'm not a GnuPG
developer -- is to either:
    * implement your own "fake" `gpg-agent` which I have no ideea what
actually implies;
    * implement your own "fake" `pinentry` which would be much simpler
as it only has to implement the assuan protocol; but you'll have to
start a separate instance of `gpg-agent` just for this situation,
which unfortunately will background and you'll have to "hunt it down"
once your done, or you could use that to start your command as a child
of `gpg-agent` which is a horrible hack;
    * (preferably) implement a fake `gpg` which does the following:
opens a pipe as you have done in your example, writes the password and
then calls the real `gpg` with an additional argument
`--passphrase-fd`; (this works only as long as Git uses the `gpg` tool
and not the library... fortunately this is true today and I guess it's
unlikely to change...)

    Related to this last option, and assuming you are on Linux and are
using a recent BASH version (mine is 4.x), you could do what you want
as bellow (code not tested):
~~~~
password=...

env \
    GPG_PASSPHRASE_FD=<( printf -- "${password}" ) \
    PATH="a-folder-where-your-gpg-wrapper-is:${PATH}" \
    git ...
~~~~

    Notes:
    * the syntax <( ... ) replaces the token with the path of a pipe
ready to read from the sub-command in the parenthesis; (see the Bash
manual);
    * as you can't send arguments to `gpg` via Git you use environment
variables;
    * the password is not visible in the environment of the `git` or
its children, but could be read from that descriptor;
    * depending on Bash it could actually be stored on the file system
thus maybe leaked to permanent storage...

    Where your `gpg` wrapper would be (not tested but adapted from
another script of mine):
~~~~
#!/bin/bash

# see Bash manual for the magic in the following line... :)
set -e -E -u -o pipefail || exit 1

_self_path="$( readlink -e "${0}" )"
_self_name="$( basename "${0}" )"

# this would contain each resolved file in the path
# if we are a wrapper then the first is the wrapper
# and the second must be the real one
_paths="$( which -a -- "${_self_name}" )"

_next=
while read _path
do
        _path="$( readlink -e "${_path}" )"
        test "${_path}" != "${_self_path}" || continue
        _next="${_path}"
        break
done <<<"${_paths}"

# it will silently fail if we haven't found the real gpg
test -n "${_next}"

# we assume that someone has exported the `GPG_PASSPHRASE_FD`
# and that there we have a path to a pipe to read from

# we also assume that we have at least another argument
exec "${_next}" --passphrase-fd "${GPG_PASSPHRASE_FD}" "${@}"

exit 1
~~~~


    Hope this helps you (one moth later) although it is a crude hack... :(


    But the real problems is still open and should be solved by
extending both Git and GnuPG...

    Ciprian.

    P.S.: If you don't like the Bash script I have an neat idea on how
to simply implement it in C, in a similar fashion, which would
guarantee you zero file system exposure.



More information about the Gnupg-users mailing list