Sign your commits with a gpg key

Posted on March 15, 2021 by Adrian Wyssmann ‐ 4 min read

Often open source projects require you to sign your git commits in order to verify they are coming from you. I made a quick tutorial on what is needed.

How to sign your commits with a gpg key

GPG or GNU Privacy Guard is a …

.. complete and free implementation of the OpenPGP standard as defined by RFC4880 (also known as PGP). 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. A wealth of frontend applications and libraries are available. GnuPG also provides support for S/MIME and Secure Shell (ssh).

Beside of encrypting it is also used for signing commits and tags which is often required by open source project, so it can be verified that the commits came from you. I usually do this also with my personal projects by default.

How to create a key

First you need a private/public key-pair which you can create with gpg -gen-key or gpg --full-gen-key. The first one uses default values for key type, key size and does not limit the certificate experience, whereas the latter asks you for more details:

gpg --full-gen-key
gpg (GnuPG) 2.2.27; Copyright (C) 2021 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)
  (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) 1y
Key expires at Di 15 Mär 2022 09:43:25 CET
Is this correct? (y/N) y

Some things to notice:

  • key types: see RSA, DSA
  • key size: usually higher is better
  • expiring: making keys expired forces you to replace them regularly, which is a good practice

As a next step, you have to provide proper identification to your key

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

Real name: Papanito
Email address: [email protected]
Comment: test
You selected this USER-ID:
    "Papanito (test) <[email protected]>"

Next you will be asked to enter passphrase and confirm it. You can skip however to creation of a passphrase and leave the key unprotected. This means if somebody gets your private key, he can sign things with your key and even encrypt and decrypt stuff which is only meant for your eyes.

At last, there will be the following dialog:

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.

Once you have enough entropy the key is generated:

gpg: key 363F2D1ABB00CF0E marked as ultimately trusted
gpg: revocation certificate stored as '/home/aedu/.gnupg/openpgp-revocs.d/4628049F4CFFD495056E0AEC8363F2D1ABB00CF0E.rev'
public and secret key created and signed.

pub   rsa4096 2021-03-15 [SC] [expires: 2022-03-15]
uid                      Papanito (test) <[email protected]>
sub   rsa4096 2021-03-15 [E] [expires: 2022-03-15]

It’s very important that you store the .rev key somewhere safe - together with your passphrase cause your key is stolen, you can revoke it from the Public Key Infrastructure (PKI).

How to sign your commits

However this is not really relevant for signing your commits, as it does not rely on public PKI, but requires you having your public key stored in your remote git account:

Once you have the public key stored in your git account, you have to enable signing of the commits. First you have to tell git which key to use. Thus, to use the recently created key 4628049F4CFFD495056E0AEC8363F2D1ABB00CF0E you would execute

git config user.signingkey 4628049F4CFFD495056E0AEC8363F2D1ABB00CF0E

And then you can go on to sign commits using -S

git commit -a -S -m 'Signed commit'

or even tags

git tag -s v1.5 -m 'my signed 1.5 tag'

I usually sign all by default, thus avoiding typing -S every time, I configure signing to be enabled by default:

git config --global commit.gpgsign true

So now your commits will be shown with a green label Verified

Example of a signed git commit
The apperance of a verified git commit in Gitlab