Skip to content

Instantly share code, notes, and snippets.

@mxmauro
Created March 9, 2022 11:48
Show Gist options
  • Save mxmauro/0c95fdc7e9bbebdd127a6bb8ed495c42 to your computer and use it in GitHub Desktop.
Save mxmauro/0c95fdc7e9bbebdd127a6bb8ed495c42 to your computer and use it in GitHub Desktop.
How to sign git tags and commits

How to sign git tags and commits

The following step-by-step guide will assist you to start pushing signed commits and create signed tags. This is a quick-start guide. For more details, you can visit here and here.

There some topics to take into account on why we decided to follow a specific approach on certificate management:

  • GitHub does not handle master certificates revocation but the community seems to not care about this because the purpose of these certificates is to demostrate to others that you are you and not other person impersonating you. If your certificate expires or is stolen, you simply create a new one and upload it to GitHub. Because GitHub also verifies the email address, a thief must also gain to your account in order to be able to use it.
  • Using subkeys is preferable but updating them and GitHub periodically can become a pain. Also the whole public certificate chain becomes too big.
  • You can use hardware devices like YubiKey, but take into account the private keys are moved to them. There are some hacks that allows you to store the same private key in more than one key (for e.g., for backup) but it is a lot easier to handle multiple keys, one on each hardware device.
  • If you want to use multiple hardware devices, repeat the instructions below for each one.

Before starting.

Install GnuGP on your operating system. Usually it is preinstalled on most Linux distributions but if you use another OS or the application is not present, please visit https://gnupg.org/download/ and follow the download and installation instructions. If you already have it, ensure it is up-to-date with the latest available version.

Generating the master certificate.

  1. Run gpg --expert --full-generate-key
  2. Select ECC (sign and encrypt) default. On some GPG versions, it is listed as ECC and ECC.
  3. Select Curve 25519 default.
  4. This step is up to you. You can choose 0 = key never expires or type something like 2y if you want the certificate to be valid for 2 years.
  5. Enter your full name, your email and, optionally, a comment.
  6. Confirm changes.
  7. Enter a strong password to protect the private key being generated.

Retrieval of the key ID.

  1. Run gpg --list-secret-keys --keyid-format=long.
  2. Locate a line similar to this: sec ed25519/####### yyyy-mm-dd [SC] (with current date) where ####### is an hexadecimal value located after the slash.
  3. Take note of this value and let's call it KEY_ID. On future references when {KEY_ID} appears, replace it with the extracted id.

Exporting the secret key (optional and for backup purposes).

  1. Run gpg --export-secret-key --armor {KEY_ID}
  2. GPG will ask for the private key's password.
  3. Save the output in a safe place.

Adding they keys into your GitHub account.

  1. Run gpg --armor --export {KEY_ID}
  2. Copy the content of the output to a temporary location.
  3. Navigate to your personal GitHub account settings https://github.com/settings/profile.
  4. Go to SSH and GPG keys panel.
  5. Click on new GPG key.
  6. Paste the content copied on step 2 in the box.
  7. Save the changes.

Preparing a repository to only accept signed commits.

  1. Navigate to the repository's configuration settings by going to https://github.com/{organization-or-account}/{repository-name}/settings
  2. Go to the Branches panel.
  3. Create a new rule (or edit the existing) to protected the master or main branch.
  4. Enable Require signed commits and set up the other options as convenience.
  5. Save the changes.
  6. Optionally, add similar rules referencing to other branches you would like to protect.

Preparing a local repository to use signed commits.

  1. Go to a repository's root directory.
  2. Run git config commit.gpgsign true to allow GIT to use a GPG key to sign yours commits.
  3. Run git config user.signingkey {SIGNING_SUBKEY_ID} to specify which signature to use.
  4. If you are NOT a Microsoft Windows user, skip the next step.
  5. Run git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe" so git apps can locate GPG. WARNING: The name and/or location may be different depending on the version of GnuPG installed. I recommend to use GPG4WIN.

NOTE: You can, optionally, add the --global flag to both git config commands if you wish to use the same signature in all of your commits of all repositories. This is recommended method if you only use GitHub or, if the majority of projects reside on GitHub. For e.g., if you use a different account for a few repositories, you can override the global setting by running git config commit.gpgsign false in the local repository.

Signing your commits.

At this point you should be able to create signed commits and tags using the same procedure you were using before. When a commit is created, GPG should ask to enter the private key's password.


Yubico's YubiKey users.

Some notes.

  • As said before, when you move a key to a YubiKey, GPG moves the actual key data to the device and then replaces the local data with some sort of pointer so GPG knows the private key is stored on an external device.
  • Use, at least, 6 characters for PIN and, at least, 8 characters for Administrator PIN. For some unknown reason (may be a firmware bug), using less than 6 characters makes git commit to fail with "Bad PIN" error.
  • On Microsoft Windows, installation of the Yubico Minidriver may be needed if your device is not properly recognized by GPG.

Preparing the key(s) for OpenPGP.

  1. Download and install YubiKey Manager CLI from https://developers.yubico.com/yubikey-manager/
  2. Plug the YubiKey.
  3. Run ykman info and check if your device has support for OpenPGP application and if it is enabled. Some devices support both USB and NFC interfaces.
  4. If support is disabled, run ykman config usb --enable OpenPGP.
  5. If your device supports NFC, you can also run ykman config nfc --enable OpenPGP.
  6. Run gpg --card-edit.
  7. Type admin and press enter to enable administrator commands.
  8. Type kdf-setup and press enter. GPG will ask for the administrator PIN. By default, it is 12345678. Take into account these are just GPG pins and unrelated to other application pins the device may have.
  9. Type passwd and press enter. This will allow us to change the OpenPGP PIN and the OpenPGP Administrator PIN.
  10. Type 1 to change the PIN.
  11. Enter the current PIN. By default, it is 123456.
  12. Enter a new PIN and repeat it in the following two prompts to change it. Pins can contain any alphanumeric value.
  13. Now back in the menu, type 3 to change the Administrator PIN.
  14. Enter the current Administrator PIN. Remember by default it is 12345678.
  15. Enter a new Administrator PIN and repeat it in the following two prompts to change it. Pins can contain any alphanumeric value.
  16. Type q to quit from the PIN configuration module.
  17. Now back into the gpg/card> prompt, type quit to exit the application.

Moving the master certificate's private key to YubiKey.

  1. Ensure the YubiKey is still plugged.
  2. Run gpg --expert --edit-key {KEY_ID}. The master-key and subkeys will be listed and a new prompt will appear.
  3. Type keytocard and press enter. It will ask if you really want to move the primary key.
  4. Type 1 to select the signing location as the target.
  5. You will be prompted for the private key's password.
  6. Then you will be prompted for the OpenPGP Administrator PIN. You might be asked for the admin pin more than once.
  7. Type save and press enter to save changes.

To verify a key was successfully moved, run gpg -K. It will list all keys and those residing in a smart card, will have the sbb> signature instead of just sbb.

Signing.

The signing process of commits and tags should remain the same except now you will be asked for the device pin instead of the private key's password. Just ensure you plugged the correct YubiKey in your computer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment