Signing Git commits with SSH
How to sign Git commits with SSH on macOS.
You can sign Git commits with an SSH key.
Info
The following uses the same SSH key for GitHub authentication and signing commits.
Create a new SSH key
Create a new SSH key with a passphrase:
ssh-keygen -t ed25519 -C "<ID>+<USERNAME>@users.noreply.github.com"
Use the following file location and name:
~/.ssh/id_ed25519_github_danillouz
Note
I’m using the GitHub noreply email (which matches the noreply commit email) to keep my email private (my primary email is also marked private on GitHub, so the noreply email is also used for web-based operations).
Update SSH config
Add the following to ~/.ssh/config
:
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519_github_danillouz
Add private key to the SSH agent
Add the private key to the SSH agent, to automatically manage the key, and store the passphrase in the macOS keychain (the default macOS ssh-add
must be used):
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_github_danillouz
Then check it was added:
ssh-add -l
Tip
All previously added SSH key(s) can be deleted with
ssh-add -D
.
Add public SSH key to GitHub
Copy the public key:
pbcopy < ~/.ssh/id_ed25519_github_danillouz.pub
And add it to GitHub.
Note
When using the same SSH key for GitHub authentication and signing commits, the same key must be added twice to GitHub: once with type “authentication” and once with type “signing”.
Test SSH connection
Test the SSH connection to GitHub (authentication):
ssh -T [email protected]
Note
Check that GitHub’s public key fingerprint matches before connecting.
The GitHub username is printed when it works.
Tell Git about the signing key
Update the global Git config to start using the SSH key to sign commits and tags:
git config --global user.signingkey "~/.ssh/id_ed25519_github_danillouz.pub"
git config --global gpg.format ssh
git config --global commit.gpgsign true
git config --global tag.gpgsign true
The .gitconfig
should now look like this:
[user]
name = Daniël Illouz
email = <ID>+<USERNAME>@users.noreply.github.com
signingkey = ~/.ssh/id_ed25519_github_danillouz.pub
[gpg]
format = ssh
[commit]
gpgsign = true
[tag]
gpgsign = true
Local signature verification
SSH has no concept of trust levels like GPG does, but a file can be created that contains trusted SSH (public) keys.
For example:
~/.config/git_allowed_signers
Where each key in the file (each key must be placed on a separate line) has the format:
<EMAIL> <KEY_TYPE> <PUBLIC_KEY>
Where KEY_TYPE
must be ssh-ed25519
.
To get PUBLIC_KEY
use:
pbcopy < ~/.ssh/id_ed25519_github_danillouz.pub
Then update the global Git config to use the allowed signers file:
git config --global gpg.ssh.allowedSignersFile "~/.config/git_allowed_signers"
The .gitconfig
should now look like this:
[user]
name = Daniël Illouz
email = <ID>+<USERNAME>@users.noreply.github.com
signingkey = ~/.ssh/id_ed25519_github_danillouz.pub
[gpg]
format = ssh
[gpg "ssh"]
allowedSignersFile = ~/.config/git_allowed_signers
[commit]
gpgsign = true
[tag]
gpgsign = true
With this config, signatures can be verified locally. For example with:
git show --show-signature