c++gnupgopenpgpgpgme

Why does GPGME / GnuPG use pinentry for password input?


GPGME uses a passphrase_cb method to fetch the password from the user for operations, which require access to private keys. This callback can only be overwritten for symmetric encryption, in all other cases the default pinentry is used.

All this effort seems to be pretty uncomfortable, especially because GPGME is an API which shall be used for programming C/C++/... applications. It might be easier (for a programmer who would like to use GPGME) in some cases if the passphrase could be passed to encrypt/sign functions directly. I also saw that other implementations of OpenPGP (to be more precise NetPGP) use a callback.

So I wonder if there is any security specific reason to do so?


Solution

  • GnuPG starting with 2.1 removed the most critical private key functionality into the gpg-agent, to reduce the attack surface on the most intimate secrets -- the private keys.

    Such a callback would not only expose the passphrase to the application you're writing (which probably means an even larger attack surface than GnuPG would be), but also GnuPG gets aware of the passphrase.

    If you really need to control entry of the passphrase from your application, you have several choices.

    Implementing Pinentry

    The information flow would then be: your application calls GnuPG through GPGME, GnuPG requests some private key operation from gpg-agent, which again asks your application for the passphrase. Be aware this will only work if you also started the gpg-agent with appropriate pinentry configuration (you might have to start another instance, separate from the one already running on your system).

    gpg-preset-passphrase

    The most important use case of passing the passphrase directly is in headless daemons, where no humans waits for entering the passphrase. GnuPG also brings a small utility gpg-preset-passphrase (on Debian and derivatives, it is installed as /usr/lib/gnupg2/gpg-preset-passphrase), which also can be used to precache the passphrase (so it is not queried for a configurable time).

    Pinentry Loopback

    With GnuPG 2.1, another option was added: in gpg-agent, you can allow pinentry loopback with the allow-loopback-pinentry option. An additional parameter pinentry-mode set to loopback in GnuPG/GPGME should allow you to handle passphrase interaction using passphrase_cb again.

    But: consider this exposes the passphrase not both your application and GnuPG, and might prove to be a (possibly minor but existing and maybe unnecessary) security risk. Also, GnuPG 2.1 is not yet widely spread, which might be a problem if you do not control the environment.