2016-03-17 GPG Agent and Emacs

I updated Gmail, Gnus and GPG on a Mac, on Emacs Wiki, with the information I discovered below.

In my Gmail Gnus GPG Guide I don’t mention gpg-agent because I never managed to set it up correctly for OSX.

Well, perhaps things will change. I followed the instructions on this blog post, I think, and it works on the command line. I can encrypt a text to myself, when I decrypt it, I’m asked for my passphrase, and when I decrypt it again, I’m not asked for my passphrase because the agent handles it.

This requires my gpg-agent.conf file to contain the line pinentry-program /usr/local/bin/pinentry which is the equivalent to pinentry-curses.

It used to say pinentry-program /usr/local/bin/pinentry-mac, however!

If I use pinentry-mac:

alex@Megabombus:~$ gpg -d test.txt.gpg 

You need a passphrase to unlock the secret key for
user: "Alex Schroeder <kensanata@keybase.io>"
8192-bit RSA key, ID 4529A45C, created 2015-03-01 (main key ID ACECFEAE)

gpg: problem with the agent: No pinentry
gpg: encrypted with 8192-bit RSA key, ID 4529A45C, created 2015-03-01
      "Alex Schroeder <kensanata@keybase.io>"
gpg: public key decryption failed: Operation cancelled
gpg: decryption failed: No secret key

If I use pinentry-curses:

alex@Megabombus:~$ echo RELOADAGENT | gpg-connect-agent 
alex@Megabombus:~$ gpg -d test.txt.gpg 
   │ Please enter the passphrase to unlock the secret key for the OpenPGP  │
   │ certificate:                                                          │
   │ "Alex Schroeder <kensanata@keybase.io>"                               │
   │ 8192-bit RSA key, ID 4529A45C,                                        │
   │ created 2015-03-01 (main key ID ACECFEAE).                            │
   │                                                                       │
   │                                                                       │
   │ Passphrase __________________________________________________________ │
   │                                                                       │
   │          <OK>                                         <Cancel>        │

Within Emacs

Without the agent running, and with pinentry-mac, it would work from within Emacs (which is what I want to get working). When the agent is running, no matter what the pinentry-program line says, it won’t work.

This is what the *Messages* buffer says:

Decrypting /Users/alex/test.txt.gpg...done
epa-file--find-file-not-found-function: Opening input file: Decryption failed, 

I’m guessing this is a pinentry problem. Not exactly the same string, though. So... Any ideas? What’s wrong? Should I be setting GPG_TTY? The problem appears to be that if I don’t use gpg-agent, Emacs using gpg knows how to call pinentry-mac. If I do use the gpg-agent, then the gpg-agent tries to call pinentry-mac and fails.

Currently the environment for my Emacs session has the following, as determined by running printenv in *eshell*:

GPG_TTY=not a tty

That looks wrong... I’m surprised that GPG_TTY is set in the first place. I’m setting it in my .bashrc file! So starting Emacs uses a shell? I don’t know how Emacs does that.

alex@Megabombus:~$ ps -fx|grep emacs
  502 42011     1   0  7:34am ??         0:02.88 /usr/local/Cellar/emacs-mac/emacs-24.5-z-mac-5.15/Emacs.app/Contents/MacOS/Emacs

My Config

In ~/Library/LaunchAgents/org.gnupg.gpg-agent.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
<plist version="1.0">

In ~/bin/startup-gpg-agent.sh:

1. ${HOME}/.gpg-agent-info is the default filename
if test -f $HOME/.gpg-agent-info && \
	kill -0 `cut -d: -f 2 $HOME/.gpg-agent-info` 2>/dev/null; then
    GPG_AGENT_INFO=`cat $HOME/.gpg-agent-info`
    export GPG_AGENT_INFO
    eval `/usr/local/bin/gpg-agent --daemon --write-env-file`

In ~/.bashrc, which is also sourced from ~/.bash_profile:

1. GPG
if [ -f "${HOME}/.gpg-agent-info" ]; then
    . "${HOME}/.gpg-agent-info"
    export GPG_AGENT_INFO
    export SSH_AUTH_SOCK
export GPG_TTY

In ~/.gnupg/gnu-agent.conf:

pinentry-program /usr/local/bin/pinentry-mac


OK, this is weird.

In a terminal, it works, if I provide --pinentry-program=/usr/local/bin/pinentry-mac as a startup parameter to gpg-agent.

In Emacs, it works, if I use pinentry-program /usr/local/bin/pinentry-mac in my gpg-agent.conf file.

One would think that the two affect the same thing, but not so. I have no idea why that is so. I’ll have to test this.

Log out and log back in. Nope, nothing works. So, at least I know that there is a way to fix this, even if I don’t know what it is!

gpg: problem with the agent: No pinentry

So here’s how I managed to “fix” it again, in a terminal:

  1. use ps aux | grep gpg to determine the process id of gpg-agent
  2. use kill to kill it
  3. run bin/start-gpg-agent.sh again
  4. run source ~/.gpg-agent-info to set the environment variables again
  5. try gpg -d test.txt.gpg to decrypt my test file – and the GUI pinentry opens!

So. What changed? I have no idea.

Within Emacs, I used setenv to set the GPG_AGENT_INFO to the new value, and it worked: I could open my test file, got asked for my passphrase, killed the buffer, reopened it, and was no longer asked for a passphrase.

So now I’m going to revert the addition of --pinentry-program to the start-gpg-agent.sh script, and see whether simply killing and restarting it from a terminal also “fixes” it. And then we’ll start worrying about the difference between all this stuff.

OK, so restarting this Mac apparently “fixed” all the issues I was having.



I recently stumbled over this somewhere: https://github.com/ecraven/pinentry-emacs

Works great for me (especilly when ssh’ing with X-forwarding) - might be worth trying as well.

Adam 2016-03-18 20:08 UTC

Haha, “This is probably totally insecure, and your passphrase may be leaked! Use at your own risk!” Also, what happens when you’re in a terminal and use gpg – does it start Emacs, or the Emacs Client, and thus you need to be running Emacs somewhere?

– Alex Schroeder 2016-03-18 21:32 UTC

There is also an ELPA package called “pinentry”; as the note in the package description says, it works “with GnuPG (2.1.5+) and Pinentry (not yet released, possibly 0.9.5+)”. It works here.

– Sam 2016-03-19 10:21 UTC

Is that the same pinentry-emacs as https://bugs.gnupg.org/gnupg/issue2034 ? I see a pinentry-emacs is installed by pinentry 0.9.7 on my Arch box.

I have the same question about what happens when if using that when outside emacs (would prefer having both possibilities).

– Kevin Unhammer 2016-04-25 07:28 UTC

pinentry.el works for me :) http://unix.stackexchange.com/questions/55638/can-emacs-use-gpg-agent-in-a-terminal-at-all/278875#278875

– Kevin Unhammer 2016-04-25 08:04 UTC

I could not get passphrase entry to work, so I installed MacGPG2 from https://gpgtools.org/ and now I have a graphical prompt on Mac OS X.

– Anonymous 2016-10-25 02:05 UTC

Here are gotchas that can help others (already included in Alex’s instructions)

  1. Uncomment use-agent in ~/.gnupg/gpg.conf
  2. Add enable-ssh-support to ~/.gnupg/gpg-agent.conf
  3. Change your start-script for gpg-agent to gpg-agent --daemon --write-env-file [1] (this will create a ~/.gpg-agent-info file)
  4. Load this file in your emacs init to setenv GPG_AGENT_INFO [2]
  • - Anonymous 2016-12-30 09:37 UTC

Please make sure you contribute only your own work, or work licensed under the GNU Free Documentation License. Note: in order to facilitate peer review and fight vandalism, we will store your IP number for a number of days. See Privacy Policy for more information. See Info for text formatting rules. You can edit the comment page if you need to fix typos. You can subscribe to new comments by email without leaving a comment.

To save this page you must answer this question:

Just say HELLO