Skip to content

The mystery of gpg-agent returning "sign_and_send_pubkey: signing failed: agent refused operation"

So I have been using gpg-agent as my SSH agent for a couple of years now, primarily because of my need to use a Yubikey as a SSH key.

To add more security on top of my threat model, I have even used AddKeysToAgent confirm in my SSH config that requires a user confirmation on the pinentry program before the key is unlocked and sent to the client; that came out good in the next few months, before I got irritated by the fact that I have to press the Enter key for each operation on Ansible just to authorize the SSH connection.

I tried to change the value of AddKeysToAgent to yes or even deleting the configuration entry; but either of which have worked. I tried to switch to a different pinentry program since I’m on macOS. The confirmation session seemed to last longer so I didn’t have to confirm so frequently as before; but it’s still frusturating that I have to actually sit at my computer to wait on the confirmations or Ansible will not be able to finish headlessly.

Then I added an comment at the end of line of that pinentry-program entry.

After a while, I noticed that all SSH connections fail after a short period, returning sign_and_send_pubkey: signing failed: agent refused operation.

I was very confused, because I have been modifying all SSH config and gpg-agent.conf in the middle of my work. I was absolutely lost in it and it, frankly, took me hours to find out that the comment apparently causes some kind of (syntax) error in gpg-agent (there was no error messages/logs at all, I tried running gpg-agent in foreground). Removing the comment fixed everything. I’m sharing my gpg-agent.conf here:

default-cache-ttl 60
max-cache-ttl 120
pinentry-program /usr/local/bin/pinentry-mac
ignore-cache-for-signing
max-cache-ttl 1; enable-ssh-support

(I recall that enable-ssh-support in the same line of an option was another hack for gpg-agent or something, but couldn’t remember it)

TL;DR: always put a comment in its own, distinct line in a .conf file. Never put it in the end of a statement - syntax highlighting in your code editor can be misleading.