Setting Up GPG Keys

Why does one need a gpg key?

GPG keys have a bunch of good uses, what I use them for most is digitally signing data (in my case git commits) which allows people to verify that a commit was authored by me. If you look at my commits to a repo, you should see a Green Verified badge next to each one.

GitHub GPG Signed Commits

This proves that I signed and pushed this commit. By default Git allows you to set the name and email for the author of a commit to whatever you want, so this is a good built-in way to authenticate that the committer is who they say they are.

Install gpg(2)

The first thing you need is to make sure you have gpg installed, and that gpg --version is at least 2.x. You can get gpg through your package manager if it's not already on your system.

If your gpg --version returns 1.x, then see if you have a gpg2. If gpg2 returns 2.x, then you're fine, just use gpg2 wherever I used gpg.

Generate your key

First work out what you want your name and email address to be. I recommend keeping them the same as your Git name and email address.

So first check what Git thinks your name/email is with:

git config --global user.name
git config --global user.email

Then generate a key:

# Use `gpg2 --gen-key` if `gpg` is version 1.
gpg --gen-key

Once this is done you should have a new key in your keyring. Check it with:

$  gpg --list-keys
/Users/gib/.gnupg/pubring.gpg
-----------------------------
pub   4096R/821C587A 2016-10-07
uid       [ultimate] Gibson Fahnestock <gibfahn@gmail.com>
sub   4096R/2C482931 2016-10-07

Telling Github/Github Enterprise/Gitlab about your key

In the same way you'd add an ssh key, you can add a gpg key in your settings. Go to your key settings and click on New GPG key.

Github New GPG Key

To print your public key do:

# If you chose a different email, use it instead of the $().
gpg --armor --export $(git config --global user.email)

then paste that key into the Github/lab entry box.

Telling git to sign commits:

You can tell git to sign all commits by default with:

git config --global commit.gpgsign true

However I've removed this from my dotfiles, as it caused problems with some test suites (e.g. the npm test suite), and also caused problems on older machines that don't support the gpg option (or that I haven't set up my gpg keys on). Instead I just add -S to all my git commit aliases, which also means that if I don't want to sign something I can just type out the full command.

Remembering your password:

Having to type out your gpg password every time is a massive pain, so you probably want your OS to store your password in your login keychain when you're logged in, so you only have to enter it once. With gpg2 on Linux or macOS this is easy.

Linux

I currently use Ubuntu with bspwm, so if it works for me it'll probably work for you. Let me know if it doesn't!

If your default gpg is gpg2, you can either tell git to use gpg2 rather than gpg, or you can make gpg point to gpg2. See this commit for my reasoning (short answer is because I want my git config to work everywhere).

Option 1: tell git to use gpg2:

git config --global gpg.program gpg2

Option 2: change your default gpg (more info here):

sudo mv /usr/bin/gpg /usr/bin/gpg1
sudo update-alternatives --verbose --install /usr/bin/gpg gnupg /usr/bin/gpg2 50

macOS

You need to configure gpg to use pinentry-mac to read your gpg password from the macOS keychain. For more information see gpg pinentry SO.

First, install gpg and pinentry-mac:

brew install gnupg pinentry-mac

Second, configure gpg to use pinentry-mac to get the password.

# Set GNUPGHOME in your rc file so gpg reads it.
mkdir -p "${GNUPGHOME:="${XDG_DATA_HOME:-~/.local/share}"/gnupg}"
echo "pinentry-program /usr/local/bin/pinentry-mac" >> "$GNUPGHOME"/gpg-agent.conf

Make sure it works:

If you try a commit (git commit -m "DeleteMe" -S, make sure you're in a git repo) you should get a password prompt, and if you do another (git commit --amend --no-edit -S) it should have remembered your password.

If you push to GitHub or GitLab, you should see the green checkmark.

Troubleshoooting:

If it fails you can check whether gpg is working properly by setting:

export GPG_TTY=`tty`

This tells gpg to use your terminal to prompt for your password. If gpg only works when you set this then your gpg agent is probably configured wrong.

If this doesn't work, git is probably confused about which key to use. You can set the default in ~/.gnupg/gpg.conf, or just tell git about your key with:

gpg --list-keys
# I get the following output:
#     /home/gib/.gnupg/pubring.gpg
#     ----------------------------
#     pub   rsa4096/821C587A 2016-10-07 [SC]
#     uid         [ultimate] Gibson Fahnestock <gibfahn@gmail.com>
#     sub   rsa4096/2C482931 2016-10-07 [E]
# Copy the key ID, in my case 821C587A:
git config --global user.signingkey 821C587A # Use the ID from above.