Using SSH to sign Git tags and commits

Ángel Ortega

Use case: you use Git as your version control system and you want to sign your tags and/or commits using a SSH key because it sounds very cool and probably enhances security somewhat.

Read here about how to do the same thing, but with GPG.

If you already have a SSH key (that you are already using to push your commits into Codeberg or Github), skip next section.

Type the following:

ssh-keygen -t ed25519

This will prompt for a file name to store the key, suggesting one, probably with a path into your .ssh directory. Change it to something meaningful, like /home/you/.ssh/my-git-signing-key or similar. You may use a passphrase to protect it. If you do, this passphrase will be requested whenever you sign a commit or tag. SSH keys are stored in two different files: one for the secret key, and another for the public one. This one has the .pub extension.

Move to the working directory of your git project and type:

git config gpg.format ssh

and then

git config user.signingkey /home/you/.ssh/my-git-signing-key.pub

or whatever the file name of your key is. That's all.

This is exactly the same as you do with GPG signing.

You have to do it this way from now on:

git tag 0.01 -s -m "New development release 0.01 (codename Potato Head)"

Note the -s argument. Also, signed tags must have a message. If you don't provide one, a $EDITOR will be spawned for you to do it.

You can also sign individual commits. You must add the -S (capital S) argument to your git commit line, because using -s like you did in git tag would be too easy to remember.

So:

git commit -S -a -m "Incredible commit"

If you dislike or forget typing the -S over and over, you can configure Git to always sign automatically with the following command:

git config commit.gpgsign true

If you try verifying a tag with the -v option or your commit log with the --show-signature option, you'll see that Git complains with the following message:

error: gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification

For this to work, you must create the file mentioned there. This file can contain references to many signing keys, so I think it's better to have only one and configure it globally.

Move to your ~/.ssh directory and type:

echo "your@email namespaces=\"git\" $(cat my-git-signing-key.pub)" >> git-allowed-signers

This file, git-allowed-signers, is the one you must configure Git to use; do it with the following command:

git config --global gpg.ssh.allowedSignersFile /home/you/.ssh/git-allowed-signers

From now on, verified tags and commits will be prefixed with the following message:

Good "git" signature for your@email with ED25519 key SHA256:xxxxxxxxxxxxx

Software forges like Codeberg and others allow you to setup your key for commit validation. This way, people can confirm that you were the real commiter when they browse your code from the web UI. This is cool. Read their documentation on how to do it.

Creating a signed commit:

git commit -S -a -m "Commit message"

Creating a signed tag:

git tag -s 1.23 -m "Tag description"

Verifying a signed tag:

git tag -v 1.23

Showing signature information in logs:

git log --show-signature

Some people prefer SSH keys to GPG ones (they are surely easier to manage). Very intelligent security experts recommend not using GPG for anything. Listen to them. Probably.

Also, don't write singing instead of signing everytime, like I do.

If you found this post useful, you may buy Ángel a coffee.