Signing Git Commits with SSH

Published: March 06, 2023 git - ssh - gpg - windows

I’ve been using GPG to sign my Git commits for a while now and have recently discovered that you can now use SSH keys to sign commits. I may be late to join this one but if you are like me, you hate typing in your GPG password to commit. And if you are even more like me, you could never get GPG or Git to cache your password for you. So, I’m going to show you how to use SSH keys to sign your commits.

This is will be focused on Windows but should be similar on other platforms.

Generate an SSH Key

If you already have an SSH key, you can skip this step. If you don’t, you can generate a new one:

ssh-keygen -t ed25519 -C "your_email@example.com"

This will prompt you for a file name and a passphrase. I would recommend using the default file path and a secure passphrase.

Adding SSH Key to SSH Agent

First we will check if the SSH agent is running, if not we will start it.

Get-Service | ?{$_.Name -like '*ssh-agent*'} | select -Property Name, StartType, Status

If the SSH agent is not running or disabled, you will need to enable it.

# Enable the Service if it is disabled (will require powershell to be run as admin):
Set-Service -Name ssh-agent -StartupType Manual
# Start the service if it is not running:
Start-Service ssh-agent

Now add your key to the SSH agent:

ssh-add ~/.ssh/id_ed25519

Adding SSH Key to GitHub

Now we need to add our SSH public key to GitHub. You can do this by going to your GitHub profile settings and clicking on SSH and GPG keys. To add your key to your GitHub account, we are going to need to do a little bit of work. First lets get our SSH public key ready:

$ cat ~/.ssh/id_ed25519.pub | clip
# Copies your public key to your clipboard

Use this easy url to quickly navigate to the SSH and GPG keys page on GitHub. Then click on the “New SSH key” button. You will create two keys for both authentication and signing key. The Authentication key is used for connecting to Github without a username and a token at each visit. The Signing key is used for signing commits.

Now that we have our SSH key added to our GitHub account, let’s finally test our connection to see if everything is working:

ssh -T git@github.com

You may see a warning like this:

Before you can continue, verify that the fingerprint is correct here GitHub’s public key fingerprint. If it is correct, type yes and press enter.

> The authenticity of host 'github.com (IP ADDRESS)' can't be established.
> RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
> Are you sure you want to continue connecting (yes/no)?

If the connection is successful, you will see something like this:

> Hi username! You've successfully authenticated, but GitHub does not provide shell access.

Configuring Git to Use SSH

Now that we have our SSH key added to our GitHub account and ready to go on our local machine, we need to configure Git to use it.

git config --global commit.gpgsign true
git config --global gpg.format ssh

Now let’s tell Git which SSH key to use. I’m going to use the default SSH key path but you can use whichever path your SSH key is located at.

git config --global user.signingkey "~/.ssh/id_ed25519"

Now lets test it out. Before we continue, you will have to navigate to the directory of the repository you want to sign commits for. If you are using a new repository, you will need to initialize it first.

If you do need to start a new repository, you can do so by running the following command:

git init

Now we can create a new commit and sign it with our SSH key:

git commit --allow-empty -S -m "Signed SSH Commit"

You should see something like this: [master 58f39d7] Signed SSH Commit if everything is correct.

To double check that your commit is signed, you can use the following command:

git log --show-signature

You should see something like this:

commit f6e0367385aacd68ec5daa2b77c1092e115d5aa9
Good "git" signature with ED25519 key SHA256:yjwtDJIvOG6qSFo3eDSKnK8YK213Y0ldxDwaTa9QFFc
sig_find_principals: sshsig_find_principal: No such file or directory^M
No principal matched.
Author: Douglas Rocha <79188161+dougrocha@users.noreply.github.com>
Date:   Mon Mar 6 17:52:55 2023 -0700

    Signed SSH Commit

Now you may be wondering why you are seeing No principal matched.. This is because the SSH key gives a valid signature but cannot be found as one of the allowed signers. To fix this we can create a file called ~/.ssh/allowed_signers" and add our SSH key contents to it. When checking the signature now, you should see something like this:

# Create the ~/.ssh/allowed_signers file
New-Item -Path ~/.ssh/allowed_signers

One thing to note is that the ~/.ssh/allowed_signers file contents must all start with an email address. So if you are copying your public SSH key into the file, you will need to add your email address to the beginning of the line.

We also need to add the following to our ~/.gitconfig file:

git config --global gpg.ssh.allowedsignersfile ~/.ssh/allowed_signers

Now when we rerun the git log --show-signature command, we should see something like this:

commit f6e0367385aacd68ec5daa2b77c1092e115d5aa9
Good "git" signature for douglas_junior@icloud.com with ED25519 key SHA256:yjwtDJIvOG6qSFo3eDSKnK8YK213Y0ldxDwaTa9QFFc
Author: Douglas Rocha <79188161+dougrocha@users.noreply.github.com>
Date:   Mon Mar 6 17:52:55 2023 -0700

    Signed SSH Commit

The End

After all this, your ~/.gitconfig file should look something like this:

[user]
    signingkey = ~/.ssh/id_ed25519
[gpg]
    format = ssh
[commit]
    gpgsign = true
[gpg "ssh"]
    allowedSignersFile = ~/.ssh/allowed_signers

You should now be able to sign Git commits with your SSH key. It is a great alternative to GPG and is much easier to setup. I hope this helps you out!