Relentless Coding

A Developer’s Blog

Make passmenu Show GUI Pinentry When Using Pinentry Curses by Default

Let’s take a look at how to use a GUI pinentry for one program, and curses for everything else.

I’m on Arch Linux using i3wm as a window manager and pass as my password manager. pass comes with a handy script, passmenu, that allows you to find your password from within the status bar, dmenu. This way you won’t have to open a terminal every time you want to copy a password.

However, I had instructed gpg-agent to use /usr/bin/pinentry-curses. This meant that every time I invoked passmenu and my PGP password was not already cached, nothing appeared to happen. (In fact, it would open the pinentry-curses in a terminal not accessible to me and time out.)

So here is how to use a different pinentry for passmenu and pass.

  1. First, create a wrapper script for pinentry (~/bin/pinentry-wrapper):

    #!/usr/bin/env bash
    #
    # Defaults to Qt, with a choice of curses for selected programs
    # PINENTRY_USER_DATA is a GnuPG defined variable (see man gpg)
    
    case "$PINENTRY_USER_DATA" in
        gtk)
            exec /usr/bin/pinentry "$@"
            ;;
        *)
            exec /usr/bin/pinentry-curses "$@"
            ;
    esac
    
  2. Make this script executable:

    $ chmod u+x ~/bin/pinentry-wrapper
    
  3. Instruct GnuGP to use your version of pinentry (~/.gnupg/gpg-agent.conf):

    pinentry-program /home/neftas/bin/pinentry-wrapper
    
  4. Restart the gpg-agent:

    $ pkill -HUP gpg-agent
    
  5. Create a wrapper script for passmenu (~/bin/passmenu):

    #!/usr/bin/env bash
    
    PINENTRY_USER_DATA=gtk /usr/bin/passmenu "$@"
    
  6. Make it executable:

    $ chmod u+x ~/bin/passmenu
    
  7. Make sure ~/bin is searched first in your PATH (put this in your .bashrc):

    $ export PATH="~/bin:$PATH"
    
  8. Check your work:

    $ command -v passmenu
    /home/neftas/bin/passmenu
    

I’ve also posted this as an answer to a related question on the Unix & Linux StackExchange page.

Why PINENTRY_USER_DATA and not MY_OWN_VAR? man pgp tells us that:

PINENTRY_USER_DATA
    This value is passed via gpg-agent to pinentry. It is useful to convey extra
    information to a custom pinentry.