How to sign git commits and tags with GPG

In this article, we will learn how to sign git commits and tags to verify that the code actually came from you and that it wasn’t maliciously altered by an attacker while you were transferring it.

GnuPG is a complete and free implementation of the OpenPGP standard. GnuPG allows you to encrypt and sign your data and communications; it features a versatile key management system, along with access modules for all kinds of public key directories. GnuPG, also known as GPG, is a command line tool with features for easy integration with other applications.

It is a common practice in software development to sign software packages to prove their authenticity.  In the same way, it is possible to sign Git commits and tags, usually with GPG, to prove that the code came from you and that it wasn’t maliciously altered by an attacker.

Checkout related posts:

Step 1 – Ensure that you have GPG installed

GPG is a command line tool with features for easy integration with other applications. It is a free encryption software which can be used to encrypt and decrypt files. We will use it to sign our Git commits and tags.  On a UNIX-like operating systems like Ubuntu and MacOS, gpg usually comes pre-installed. For windows, you have to download and install GPG yourself. 

Confirm the installation by checking the version using this command:

➜ gpg --version
gpg (GnuPG) 2.2.35
libgcrypt 1.10.1-unknown
Copyright (C) 2022 g10 Code GmbH
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/citizix/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

 gpg doesn’t work for you, then try writing gpg2 instead and see if that works. If the gpg2 command works for you, you can tell Git to use it for signing commits with the following command:

git config --global gpg.program gpg2

As a matter of fact, Git doesn’t care what program you use for signing your commits as long as it works like GPG.

Step 2: Configuring GPG keys

Once the gpg command is working as expected, we can generate the key pairs – similar to what we do with SSH keys. 

The following command will guide you through the GPG key creation process.

gpg --gen-key

For more options

<em>You can safely use the following settings:</em>
<em># Key type: RSA and RSA.</em>
<em># Size of key: 4096 bits.</em>
<em># Validity of key: zero (unless you want your key to expire).</em>
gpg --full-gen-key

Next, GPG will ask for the following details to establish your identity. Here’s an example of the information GPG will ask for:

➜ gpg --full-gen-key
gpg (GnuPG) 2.2.35; Copyright (C) 2022 g10 Code GmbH
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)
  (14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 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) 
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Eutychus Towett
Email address: etowett@citizix.com
Comment: Main GPG Key
You selected this USER-ID:
    "Eutychus Towett (Main GPG Key) <etowett@citizix.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
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.
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.
gpg: directory '/home/citizix/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/citizix/.gnupg/openpgp-revocs.d/8527AA1318C42445DC08C06ED722AF52CA1CE58C.rev'
public and secret key created and signed.

pub   rsa4096 2022-05-17 [SC]
      8527AA1318C42445DC08C06ED722AF52CA1CE58C
uid                      Eutychus Towett (Main GPG Key) <etowett@citizix.com>
sub   rsa4096 2022-05-17 [E]

If you are planning to use different email addresses on different projects, you’ll have to generate one GPG key for each email address.

GPG will also ask you to create a password for the key – You’ll be prompted for this password whenever you try to use your key. I’d recommend choosing a strong and memorable password.

Important: Make sure you keep your GPG keys safe, especially the private key.

In order to put your GPG keys to use, you will need access to your key ID and the public key. We’ll see how to get those in the sections below.

Listing GPG Keys

Once you have setup a number of GPG keys, you might want to see a list of all your keys. You can do that with the following command:

<em># List all GPG public keys.</em>
$ gpg --list-keys --keyid-format long

<em># List all GPG secret keys.</em>
$ gpg --list-secret-keys --keyid-format long

For our example in this tutorial, we’ll only see the keys for a particular identity. We do this by appending an email address to the end of one of the above commands:

➜ gpg --list-secret-keys etowett@citizix.com

gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
sec   rsa4096 2022-05-17 [SC]
      8527AA1318C42445DC08C06ED722AF52CA1CE58C
uid           [ultimate] Eutychus Towett (Main GPG Key) <etowett@citizix.com>
ssb   rsa4096 2022-05-17 [E]

If you run the command without the email parameter, you will see all your GPG keys.

Getting GPG key ID

To get the ID of your GPG key, use the command above to see a list of keys first. Now, focus on the line that says sec, i.e. rsa4096 2022-05-17 [SC]. The part after the below that is the GPG key ID. For example: 8527AA1318C42445DC08C06ED722AF52CA1CE58C.

Getting GPG public key

To see the public key, you need to have a key ID as mentioned above. Use the following command to see your full public key:

<em># The syntax is: gpg --armor --export KEY-ID</em>
$ gpg --armor --export 8527AA1318C42445DC08C06ED722AF52CA1CE58C

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBF1xnckBEADIeAmeXUAtUJ5EHr/xwpzNU1C/NixbaHnmFhgnMa076OpbJxvP
kpOGciSN9a4xn39soxFY56G3rO3R7ecANBXjsTi+sz4CzKxU6OH2Eu1tJnidLVg2
<em># ...</em>
aPA1Ij+YjJ+2QOcFDU0+fSTYv+SYAmLsmDK9Fqib9yUjTQgTau8hslBS3YhzlAxK
szXI7gyqWSwNWbvkpJtnR/1eLh/CRC5pFX62AvpnJbqnistNY8OpYCV+kzvwjEiL
=gAQS
-----END PGP PUBLIC KEY BLOCK-----

Deleting GPG Keys

If you ever want to remove a public or private key, you need to run one of the following commands depending on your needs:

<em># Deletes GPG public key.</em>
$ gpg --delete-key etowett@citizix.com

<em># Deletes GPG secret key.</em>
$ gpg --delete-secret-key etowett@citizix.com

Step 3 – Configuring Git

Now, we need to tell Git about our GPG keys to be able to sign and verify things.

Add GPG keys to Git repository manager

Most Git repository managers like GitHub, GitLab and BitBucket provide an option to add GPG public keys to your account.  The option to add your GPG public key to your Git repo manager is usually under profile settings.

Run the command gpg --armor --export KEY-ID to get your GPG public key and add it to your repository manager. These keys are then used to generate badges to indicate if your commits are verified. This lets your team members easily check if your commits are signed and hence, authentic.

Add GPG keys to Git command-line tool

Use the following command to tell your command-line tool to use a specific GPG key for signing your commits:

<em># The syntax is git config user.signingkey KEY-ID</em>
git config user.signingkey 8527AA1318C42445DC08C06ED722AF52CA1CE58

You can use git config --global user.signingkey KEY-ID to save this in your global Git settings which will then be used for all projects.

git config --global user.signingkey 8527AA1318C42445DC08C06ED722AF52CA1CE58

Step 4 – Signing

Now that the GPG keys are in place, it’s actually time to sign commits and tags!

Signing Git commits

To create a signed commit, add the additional parameter -S to your git commit command like this:

git commit -S -m "Enough about you, let's talk about me, Johnny Bravo."

Doing this will show you a dialog where you will have to enter your GPG password to sign and make the commit.

Signing Git tags

To create a signed tag, add the additional parameter -s to your git tag command like this:

git tag -s v1.19

Doing this will show you a dialog where you will have to enter your GPG password to sign and make the commit.

Always sign Git commits

If you’ve decided that you always want to sign your commits and tags, then you can update your git configuration accordingly with the following command:

<em># Enable signing for the project.</em>
$ git config commit.gpgsign true

<em># Enable signing globally.</em>
$ git config --global commit.gpgsign true

Conclusion

Signing GPG commits is an extra layer of security that help verify if a commit or a tag was actually made by you. This can be done by generating a key and configuring it with Git. Signed git commits usually have a “verified” badge on Git repository managers like GitHub, GitLab, BitBucket, etc.

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy