Setting Up GPG Keys

Why do I 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, 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.

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).

To tell git to use gpg2:

git config --global gpg.program gpg2

To 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

Easy way is to use gpg-suite, if you're using brew:

brew install gpg

# Make sure you have brew cask:
brew tap caskroom/cask

brew cask install gpg-suite

Now you need to import your key into gpg-suite, first open GPG Keychain (e.g. with Spacegpg keychainEnter). Then in a terminal window run:

# Be careful with this, this is your secret key!
gpg --armor --export --export-secret-keys $(git config --global user.email) | tee ~/privkey | pbcopy

GPG Keychain should start bouncing up and down to tell you that it's detected a key in your clipboard, if so let it import it, if not click Import and navigate to ~/privkey.

GPG Keychain import key

Success looks like this:

GPG Keychain show key

Whatever happens delete ~/privkey ASAP, it shouldn't be left unencrypted on disk.

rm ~/privkey

Then do the same for your public key:

gpg --armor --export $(git config --global user.email) | tee ~/pubkey | pbcopy
# Import `/Users/YourUsername/pubkey`
rm ~/pubkey

Then open System Preferences and open the newly created GPGPreferences. Make sure your private key is listed in Default Key, and tick the Store in OSX Keychain checkbox.

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.

Migrate gpgtools -> gpg-suite

If you have gpgtools installed, check with:

brew cask list | grep gpgtools

then you need to update, as gpgtools was renamed to gpg-suite, see this comment for more info. You can fix it with:

mv /usr/local/Caskroom/gpgtools /usr/local/Caskroom/gpg-suite
brew cask reinstall gpg-suite