How to use a GPG key for SSH authentication on Windows

Return to posts

Post by Ozelot on 13/06/2023 (last updated on 10/08/2026)

Tags: GuideSysops

Intro

You might already know about using public key authentication for SSH. But did you know that you can also use a GNU Privacy Guard (GPG) keypair for SSH authentication? In this tutorial, we'll look at configuring this on a Windows client. This guide assumes you already have a basic understanding of GPG and SSH.

Why bother, if a plain SSH key already works? You end up with one keypair for everything - signing commits, encrypting files and logging into servers - instead of a separate key sitting in ~/.ssh for each purpose. And if your GPG key lives on a hardware token like a YubiKey or Nitrokey, the private key never leaves the device, so it can't be copied off your machine even if the machine is compromised.

Install Gpg4win

Download Gpg4win and install it. Then, create or import your key if you haven't already. Make sure that your key allows authorization or has a subkey that permits it.

Export SSH key and put it on the server

To export the SSH key from your GPG key, open the command line and run:

gpg --export-ssh-key KEY

Where KEY is your GPG key name, email or ID. You can find it with:

gpg --list-keys

The output should look something like this:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDbDzdth1SOQ793iDV1bhSEabDXj52r4Q6bYpGo27a72VSaqzBEaL7mllL2qteIInWe4yHQxX5kwKxEsB4w657GIkWzTAMMu+tCCRf3EgiZawuICXSpCcCjWu4NjQm6i1N2wWu7LHyKHTKkmyz6F48ti0vWIGv3h78am9aCZSgWyXERPyov9VxVAFKZYJMxNpTpgDx4gCoqKYlTbUqEBYabsk5atpxtRxsS27vsEpaB1Ib2KKWmKhFpLdv0EAkKQrSZlJf15gexnt8o7agGKB2c+kdHhYWYkkTTpZPlaIRejDLFpB6JTFppmgaMaKrN65+dH7Q2FXasZp0Shret17IZ9xmPdRUELSPwDb4OceapjtvHBMB3Ot+NXnSMKFT6/mJa/TB+/nZ9h7gv9vy59wE+LLdNONicWxH9EZyCloIMfM9OVXWgDE+7St18dr4Pd9QIX8bNGWSpGnad5LPCFRV5RdHWfQL4Ag4P63X5qfxrqWFynrfzDlHiXV/hnBykO7yihVOy590wnTkSvsgFT6+6wdVztmX2BJfDOp4EnYDoNDXrKxG4muizHJ79CjvE9Fx+5hU9aCC4WwDsLRa1YNtLDfCJByOZWmcyldHfu21MMgZV6JdkmSj8v8ojQf1myx4rMPIEENNeurGK/iQ6ObJtp92pwOIRP6Zsxnm1WChxbQ== openpgp:0x900AF684

Then copy the entire output (including ssh-rsa and the openpgp:0xXXXXXXXX at the end) and add it to the ~/.ssh/authorized_keys file on your server.

Set up client configuration

Make sure OpenSSH Authentication Agent is disabled

Open services.msc, find OpenSSH Authentication Agent and make sure it is turned off, if not then turn it off. If Windows ssh-agent is left running it will conflict with gpg-agent.

Create environmental variable

Run SystemPropertiesAdvanced and go to Environmental variables. Next create new user variable:

Name: SSH_AUTH_SOCK Value: //./pipe/openssh-ssh-agent

Then close both windows to save.

Set up gpg-agent config

Go to %appdata%\gnupg, create file gpg-agent.conf with following content:

enable-ssh-support
enable-putty-support
enable-win32-openssh-support

Set up keygrip

Execute:

gpg --list-keys --with-keygrip

Copy the keygrip for your key, then go to %appdata%\gnupg, create file named sshcontrol and paste your keygrip in it. Leave one blank line at the end.

Prepare for run

Close all your command line/powershell tasks. Go to Task manager and kill app processes from GnuPG and ssh-agent.exe. Then open new terminal and run gpg-connect-agent /bye. Wait for it to turn on.

Next run ssh-add -L. If it returned your key, that means it's working.

Now you can login to your SSH server via ssh user@example.com. Instead of traditionally asking you for your password you will be asked to authenticate with a key (such as pinentry).

Make gpg-agent run automatically

To avoid running gpg-connect-agent /bye after every system startup, add it to the autostart.

Go to C:\Program Files (x86)\GnuPG\bin (or where you have GnuPG installed), find gpg-connect-agent.exe, create a shortcut and move it to %appdata%\Microsoft\Windows\Start Menu\Programs\Startup.

Troubleshooting

ssh-add -L returns nothing

Almost always the sshcontrol file. Check that it contains the keygrip of a subkey with the authentication capability ([A] in gpg --list-keys --with-keygrip), not the signing or encryption one, and that the file ends with a blank line — without it the last entry is ignored.

If the file looks right, the agent is probably still running with the old configuration. Kill it and start again:

gpgconf --kill gpg-agent
gpg-connect-agent /bye

sign_and_send_pubkey: signing failed: agent refused operation

The agent found the key but refused to use it. Usually the subkey has no authentication capability, or the keygrip in sshcontrol belongs to a different subkey. Verify with gpg --list-keys --with-keygrip and look for the line marked [A].

Windows ssh-agent keeps taking over

Two things to check. OpenSSH Authentication Agent in services.msc has to be stopped and set to disabled - otherwise Windows restarts it on the next boot. And SSH_AUTH_SOCK only applies to processes started after the variable was created, so close every terminal (and your IDE) and open a fresh one.

pinentry never appears

The agent was started from a different session than the one you're authenticating from (or isn't running at all). Kill it with gpgconf --kill gpg-agent, then run gpg-connect-agent /bye from the same terminal you use for SSH.

keep calm and stay cute~

What do you think about it?

LoaderLoading comments...