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_danillouzNote
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_danillouzAdd 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_danillouzThen check it was added:
ssh-add -lTip
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.pubAnd 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 trueThe .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 = trueLocal 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_signersWhere 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.pubThen 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 = trueWith this config, signatures can be verified locally. For example with:
git show --show-signature