GPG2 (GnuGP 2) Guide

The guide describes how to generate GPG2 (GnuPG 2) key pair, sign and verify commits on Linux and MacOS platforms using Git.

Prerequisites

  1. Install GnuPG 2.

    For Debian based systems:

    sudo apt-get install gnupg2 -y
    

    For rpm based systems:

    sudo dnf install gnupg2 -y
    

    For MacOS systems install homebrew <http://brew.sh>_ and install GPG2

    brew install gpg2
    
  2. If you are using a GPG smartcard refer to Protecting code integrity with PGP

Generate the GPG keys

  1. Generate your GPG key.

    1. Pick option 1 for “RSA and RSA”

    2. Enter 4096 bit key size (recommended)

    3. Set the key expiry to 2 years, use ‘2y’ for 2 years

    4. Enter ‘y’ to confirm the expiry time

    5. Pick ‘O’ or ‘Q’ to accept your name/email/comment

    6. Enter a pass phrase twice.

    gpg2 --gen-key
    

    Note

    The default key ring path on Linux is /home/$USER/.gnupg/pubring.kbx and MacOS is /Users/$USER/.gnupg/pubring.kbx. This path can be overridden by setting the environment variable $GNUPGHOME to point to a different directory.

  2. View the key fingerprint.

    $ gpg2 --fingerprint --keyid-format long
    /home/abelur/.gnupg/pubring.kbx
    -------------------------------
    pub   rsa4096/0xA46800C5D9A8855E 2016-06-28 [SC]
          Key fingerprint = DBE2 4D9E 8ECC 5B29 5F33  FF61 A468 00C5 D9A8 855E
    uid                   [ unknown] Anil Belur <abelur@linux.com>
    sub   rsa2048/0x0FAA11C1B55BFA62 2016-06-28 [S] [expires: 2022-08-24]
          Key fingerprint = 3E59 553C 2748 4079 C1A1  5DC8 0FAA 11C1 B55B FA62
    sub   rsa2048/0xDC40225E6664848E 2016-06-28 [E] [expires: 2022-08-24]
          Key fingerprint = 5415 64A8 4449 4AE8 1A8D  0877 DC40 225E 6664 848E
    sub   rsa2048/0x9515A6A0C2B6EDC9 2016-06-28 [A]
          Key fingerprint = 0E46 C7F1 A2A7 F3C3 9849  A56A 9515 A6A0 C2B6 EDC9
    

    Note

    In the above example, the users long key id is ‘0xA46800C5D9A8855E’. Use the long key-id from your keys and replace with ‘<KEYID-FINGERPRINT>` in rest of the document. It’s recommended to use long key-id, since 32-bit short key-id’s are subject to collision attacks.

  3. Setup Git to sign commits and push signatures. This step updates the file ‘~/.gitconfig’ to sign commits (with your GPG2 keys) by adding the default user key fingerprint and setting the commit.gpgsign option as true. Also add push.gpgsign as true sign all pushes.

    git config --global user.signingkey <KEYID-FINGERPRINT>
    git config --global commit.gpgsign true
    git config --global push.gpgsign true
    
  4. Set GPG2 the default program.

    git config --global gpg.program $(which gpg2)
    
  5. Upload your public key to key servers.

    gpg2 --send-keys <KEYID-FINGERPRINT>
    ...
    gpg: sending key <KEYID-FINGERPRINT> to hkp server keys.gnupg.net
    

    Note

    In the above example, the $KEY_ID would be A46800C5D9A8855E

  6. Export the GPG2 public key and add it to Gerrit.

    1. Run the following at the CLI:

      gpg --export -a <KEYID-FINGERPRINT>
      
    2. Open the project’s Gerrit and go to project settings and gpg-keys.

    3. Click the Add Key button.

    4. Copy the output from the above command, paste it into the box, and click ‘Add’.

Setup gpg-agent

  1. Install gpg-agent and pinentry-mac using brew:

    brew install gpg-agent pinentry-mac
    
  2. Edit ~/.gnupg/gpg.conf contain the line:

    echo "use-agent" > ~/.gnupg/gpg.conf
    
  3. Edit ~/.gnupg/gpg-agent.conf and add the below line:

    cat > ~/.gnupg/gpg-agent.conf << EOF
    use-standard-socket
    enable-ssh-support
    default-cache-ttl 600
    max-cache-ttl 7200
    pinentry-program /usr/local/bin/pinentry-mac
    EOF
    
  4. Update ~/.bash_profile with the following:

    [ -f ~/.gpg-agent-info ] && source ~/.gpg-agent-info
    if [ -S "${GPG_AGENT_INFO%%:*}" ]; then
       export GPG_AGENT_INFO
    else
       eval $( gpg-agent --daemon --write-env-file ~/.gpg-agent-info )
    fi
    
  5. Kill any stray gpg-agent daemons running:

    sudo killall gpg-agent
    
  6. Restart the terminal (or log in and out) to reload the your ~/.bash_profile.

  7. The next time a Git operation makes a call to gpg, it should use your gpg-agent to run a GUI window to ask for your passphrase and give you an option to save your passphrase in the keychain.

    For Linux:

    _images/passphrase-linux.png

    For MacOS:

    _images/passphrase-mac.png

Sign your commit

  1. Commit and push a change

    1. Change a file and save it with your favorite editor.

    2. Add the file and sign the commit with your GPG private key.

      git add <path/to/file>
      git commit --gpg-sign --signoff -m 'commit message'
      

      Note

      The option –gpg-sign (-S) uses GPG for signing commits. The option –signoff (-s) adds the Signed-off-by line in the commit message footer.

    3. Push patch to Gerrit.

      git review
      

      Note

      • This should result in Git asking you for your pass phrase, if the ssh keys are password protected.

      • The presence of a GPG signature or pushing of a gpg signature isn’t recognized as a “change” by Gerrit, so if you forget to do either, you need to change something about the commit to get Gerrit to accept the patch again. Tweaking the commit message is a good way.

      • This assumes you have git review -s set up and push.gpgsign set to true. Otherwise:

      git push --signed gerrit HEAD:refs/for/master
      
      • This assumes you have your gerrit remote set up like the below, where repo is something like releng-docs:

      ssh://<user-id>@git.linuxfoundation.org:29418/<repo>.git
      
  2. Verify the signature of the signed commit locally.

    git log --show-signature -1
    commit ea26afb7d635a615547490e05a7aef2d9bcda265
    gpg: Signature made Tue 28 Nov 2017 11:15:12 AM AEST
    gpg:                using RSA key 0FAA11C1B55BFA62
    gpg: Good signature from "Anil Belur <abelur@linux.com>" [unknown]
    Primary key fingerprint: DBE2 4D9E 8ECC 5B29 5F33  FF61 A468 00C5 D9A8 855E
         Subkey fingerprint: 3E59 553C 2748 4079 C1A1  5DC8 0FAA 11C1 B55B FA62
    Author: Anil Belur <abelur@linux.com>
    Date:   Tue Nov 28 10:45:29 2017 +1000
    
  3. A green check next to the users name on the Gerrit change should suggest a valid commit signature.

    _images/gerrit-signed-commit.png