Skip to main content
  1. Posts/
  2. Git/

Git Commit Signing with GPG & YubiKey

··969 words·5 mins·

After learning about how GitHub displays names and profile pictures next to commits, and how this mechanism can be abused rather easily, I decided to enhance the integrity of my public-facing activity on GitHub by attaching digital signatures to my commits.

This document is a summary of all of the online resources I used to set-up my GPG key pair to work seamless across my machines, my YubiKey hardware-based security key and on GitHub. I used my name and email for demo purposes only, which means that if you copy my details and use them in your key pair, it will look goofy in your commit log.

Required Software #

Generate Key Pair #

The key pair first has to be generated on your local machine, such that its metadata is associated to your GitHub account’s public-facing details, and its cryptographic algorithm is suitable to your requirements.

According to GitHub’s GPG keys Guide1:

  1. Generate a key pair.

    $ gpg --full-generate-key
    
  2. Get your key ID:

    $ gpg --list-secret-keys --keyid-format=long
    sec>  rsa4096/4DAFB02B4734FE52 2021-09-01 [SC]
    	________________________4DAFB02B4734FE52
    	# ...
    uid                 [ultimate] Omri Bornstein <omribor@gmail.com>
    ssb>  rsa4096/422B0DEA5FB23439 2021-09-01 [E]
    $ export KEY=________________________4DAFB02B4734FE52
    
  3. Print your public key:

    $ gpg --export --armor $KEY
    -----BEGIN PGP PUBLIC KEY BLOCK-----
    # ...
    -----END PGP PUBLIC KEY BLOCK-----
    
  4. Copy your public key, beginning with -----BEGIN PGP PUBLIC KEY BLOCK----- and ending with -----END PGP PUBLIC KEY BLOCK-----.

  5. Follow GitHub’s guide to add your public key to your account.

Back-up Your Key Pair #

You can export an ASCII text version of your private key in case you wish to have a back-up version available at a secure location.

$ gpg --export-secret-key --armor $KEY
-----BEGIN PGP PRIVATE KEY BLOCK-----
# ...
-----END PGP PRIVATE KEY BLOCK-----

Enable Commit and Tag Signature #

You can enable commit signing by default by editing your ~/.gitconfig file. Your details must match to the details you provided when creating your key pair.

[user]
	name = Omri Bornstein
	email = omribor@gmail.com
[commit]
	gpgSign = true
[tag]
	gpgSign = true

Graphical PIN Entry #

By default, gpg asks for your key’s PIN to be entered to its command-line prompt before the private key is used for signing. In case you want to use GPG from a non-TUI environment, the Arch Linux wiki covers how to enable PIN entry from a graphical interface.

Import Key Pair to YubiKey #

At this point, you can utilise your key pair from your local machine with git perfectly fine in such a way that GitHub will display a verified badge next to your commit messages. In case you have a OpenPGP-capable hardware-based security key, you can optionally move your key pair to it, such that it can be used seamlessly and securely across machines.

Tom Stuart has an awesome video on YouTube2 showing how ot transfer a key pair to a hardware-based security key like a YubiKey. A similar guide can be found in a written form on @drduh’s YubiKey guide[^4].

  1. Connect your YubiKey to your machine.

  2. gpg lists each of the keys in the key pair according to their role. The first-listed key is intended to be used for digital signatures (labeled by [SC]), and the second-listed key is meant to be used for encryption.

    $ gpg --edit-key $KEY
    sec>  rsa4096/4DAFB02B4734FE52 2021-09-01 [SC]
    	________________________4DAFB02B4734FE52
    	# ...
    uid                 [ultimate] Omri Bornstein <omribor@gmail.com>
    ssb>  rsa4096/422B0DEA5FB23439 2021-09-01 [E]
    
  3. Select each key and instruct gpg to move it to the appropriate key slot on the YubiKey.

    gpg> key 0
    gpg> keytocard
    Please select where to store the key:
    (1) Signature key
    (3) Authentication key
    Your selection? 1
    gpg> key 1
    gpg> keytocard
    Please select where to store the key:
    (2) Encryption key
    Your selection? 2
    
  4. Make sure to save the changes and exit the gpg command prompt.

    gpg> quit
    Save changes? (y/N) y
    

Add YubiKey-backed Key Pair to Another Machine #

In case you want to use the same YubiKey across multiple machines, @drduh’s YubiKey guide3 covers how to inform gpg (installed on another machine) of the key pair you already transferred to your YubiKey from a different machine.

From the original machine with your YubiKey plugged-in, you’ll need to make a copy of the public key alongside a list of the trusted GPG keys.

$ gpg --export --armor $KEY > gpg-public-key-$KEY.asc
$ gpg --export-ownertrust > gpg-owner-trust.txt

Copy both files to the second machine (with gpg installed). Then, on the second machine:

  1. Define your KEY. For example:

    $ export KEY=________________________4DAFB02B4734FE52
    
  2. Import your public key:

    $ gpg --import gpg-public-key-$KEY.asc
    
  3. Import the trust settings:

    $ gpg --import-ownertrust < gpg-owner-trust.txt
    
  4. Insert your YubiKey into a USB port.

  5. Import the private key stubs from the YubiKey:

    $ gpg --card-status 
    # ...
    Application type .: OpenPGP
    Version ..........: 2.1
    Manufacturer .....: Yubico
    # ...
    

Now you can use the YubiKey on your multiple machine seamlessly.

Result #

Git will now use the key pair stored on your YubiKey, and attach a digital signature to all future commits issues from your machine. As a result, GitHub will show a verified badge in the commit’s details page, showing your fellow contributors the integrity of the identity shown in relation to the changes you made (like in commit 74f9009 from raker). Similarly, the git verify-commit and git verify-tag commands can be used locally to ensure your digital signature is recognised as valid by Git.

$ git verify-commit 74f9009
gpg: Signature made Sat 30 Dec 2023 20:48:50 AEDT
gpg:                using RSA key ________________________4DAFB02B4734FE52
gpg:                issuer "omribor@gmail.com"
gpg: Good signature from "Omri Bornstein <omribor@gmail.com>" [ultimate]

  1. GitHub. (2016). Generating a new GPG key. GitHub Docs. https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key ↩︎

  2. Stuart, T. (2022). How to set up Git commit signing with GPG and a YubiKey on macOS [YouTube Video]. In YouTube. https://youtu.be/7LuMTyhFA-g ↩︎

  3. drduh/YubiKey-Guide (2023). Guide to using YubiKey for GPG and SSH. (2023). GitHub. https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#multiple-hosts ↩︎