GPG Signature Verification on Github

Github just announced first-class support for GPG signature verification. This is a great feature that provides a more reliable way to trust code and the people you collaborate with. Plus, it has the nice benefit of being simple to setup. With that said, let's see what I did to get it up and running.

Generating a GPG key

From my Ubuntu 14.04 host, I ran gpg --gen-key selecting the default RSA key type with a size of 4096 bits. I added my name, email, and a comment about the key and set the key to be valid for one year.

Note: It's important to use the same email address as the one registered to your Github account and it must be verified.

➜  tests git:(gpg-keys) ✗ gpg --gen-key           
gpg (GnuPG) 1.4.16; Copyright (C) 2013 Free Software Foundation, Inc.  
This is free software: you are free to change and redistribute it.  
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:  
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 1  
RSA keys may be between 1024 and 4096 bits long.  
What keysize do you want? (2048) 4096  
Requested keysize is 4096 bits  
Please specify how long the key should be valid.  
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 1y  
Key expires at Thu 06 Apr 2017 10:54:33 AM EDT  
Is this correct? (y/N) Y

You need a user ID to identify your key; the software constructs the user ID  
from the Real Name, Comment and Email Address in this form:  
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Justin Valentini  
Email address: justin.valentini@gmail.com  
Comment: Github  
You selected this USER-ID:  
    "Justin Valentini (Github) <justin.valentini@gmail.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O  
You need a Passphrase to protect your secret key.  

Key entropy

After I filled out the required info and set a passphrase, I ran into an issue creating enough entropy to generate the keys. GPG warned me that I need to generate more random bytes.

We need to generate a lot of random bytes. It is a good idea to perform  
some other action (type on the keyboard, move the mouse, utilize the  
disks) during the prime generation; this gives the random number  
generator a better chance to gain enough entropy.

Not enough random bytes available.  Please do some other work to give  
the OS a chance to collect more entropy! (Need 237 more bytes)  

However, no amount of mouse movement / keyboard smashing was enough to successfully generate the key.

Some quick searching revealed a solution. Installing rng-tools was exactly what I needed and it finally generated a key pair.

gpg: key 0839B87E marked as ultimately trusted  
public and secret key created and signed.

gpg: checking the trustdb  
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model  
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u  
gpg: next trustdb check due at 2017-04-06  
pub   4096R/0839B87E 2016-04-06 [expires: 2017-04-06]  
      Key fingerprint = 7C9B 681A 7101 D685 0794  6992 73DF 5097 0839 B87E
uid                  Justin Valentini (Github) <justin.valentini@gmail.com>  
sub   4096R/DFB6A46A 2016-04-06 [expires: 2017-04-06]  

Configuring git

Next I copied my 8-character key ID from the output above, in this case 0839B87E, and added it to my git config with git config --global user.signingkey 0839B87E.

If you need to find the key ID again, run gpg --list-public-keys:

➜  tests git:(gpg-keys) ✗ gpg --list-public-keys 
/home/jvalentini/.gnupg/pubring.gpg
-----------------------------------
pub   4096R/0839B87E 2016-04-06 [expires: 2017-04-06]  
uid                  Justin Valentini (Github) <justin.valentini@gmail.com>  
sub   4096R/DFB6A46A 2016-04-06 [expires: 2017-04-06]  

A quick check reveals things look good from git's perspective:

➜  tests git:(gpg-keys) ✗ git config --global --get user.signingkey   
0839B87E  

In git version 2.0+ you can set a config option to auto-sign commits with git config --global commit.gpgsign true. Unfortunately, the current version of git for Ubuntu 14.04 is only 1.9.1 so I didn't have this option.

Magit (Optional)

Even though my version of git didn't supported auto-signing commits, I was able to configure Magit, an Emacs package for working with git, to auto-sign commits for me. To do so, I set the magit-commit-arguments var to (quote ("--gpg-sign=73DF50970839B87E")).

Now, when I commit from Emacs, Magit will auto-sign my commits exactly as if I had run git commit -S.

Configuring Github

Now that things with git and magit were set up, I had to set up Github. The next step was to export my public key with gpg --armor --export justin.valentini@gmail.com:

➜  tests git:(gpg-keys) ✗ gpg --armor --export justin.valentini@gmail.com
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

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  
=V4jD
-----END PGP PUBLIC KEY BLOCK-----

I copied that entire block, including the BEGIN / END lines, and added it to my Github account.

Verifying it works

The last step was to commit some code and push it up to Github. Since I had modified my global .gitconfig, which I keep in a dotfiles repo, I was able to use those changes as a quick test:

And just like that, GPG signing is complete!