GPG (GNU Privacy Guard) is a free, open-source software tool for secure communication and data protection. It implements the OpenPGP standard, allowing users to encrypt and sign their data and communications. GPG uses public-key cryptography, enabling users to exchange messages securely without sharing secret keys beforehand. It’s widely used for securing email, verifying software distributions, and authenticating digital signatures. GPG provides strong privacy and authentication for data communication, making it a crucial tool for individuals, businesses, and organizations concerned with maintaining confidentiality and data integrity in the digital world.
Why should you care as a software developer?
As a developer, using GPG to sign your commits enhances the security and integrity of your codebase by verifying your identity, ensuring the authenticity of your contributions, and protecting against impersonation or unauthorized code changes.
Installation
To install the latest GPG app and utilities suite, follow the up-to-date procedures you find on your preffered search engine. There are solutions for MacOS, Linux/Ubuntu and Windows.
Creating a GPG key
To create a new GPG key with the current default parameters (recommended) run:
gpg --gen-key
As of the time of writing, the default algorithm is ed25519
. You will be prompted for a password, which is recommended to be added, to protect your private key.
If you prefer a personalized way of setting up your GPG key, use:
gpg --full-gen-key
To list your keys use the following:
# list public keys
gpg -k
gpg --list-keys
# list secret keys
gpg -K
gpg --list-secret-keys
Store the secret file in Bitwarden
I prefer to keep the GPG keys in a secure vault, like Bitwarden. My approach is to have everything I need inside a note, so I can easily import the key in any other machine where I use Bitwarden.
For this
- I export the secret key using the
--armor
option, so the output will be in ASCII format, in plain text (no output to file) - I copy the resulting output and put it in the following block
echo '<secret key>' | gpg --batch --import -
And I add the command in my Bitwarden secure note, where I store the corresponding password as well (I know, I’m lazy).
Publish the keys
Now, if you want to use the key so you signed messages are verified (of course you want to), the public key of your secret GPG key should be published to an open key server:
- keyserver.ubuntu.com
- keys.openpgp.org
- pgp.mit.edu
# send to a default key server, e.g. keyserver.ubuntu.com
gpg --send-keys KEY_ID
# send to a specific key server
gpg --keyserver hkp://keys.gnupg.net --send-keys KEY_ID
Full example below
# create a new GPG key
> gpg --gen-key
gpg (GnuPG) 2.4.5; Copyright (C) 2024 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.
Note: Use "gpg --full-generate-key" for a full featured key generation dialog.
GnuPG needs to construct a user ID to identify your key.
Real name: Alexandru Busuioc
Email address: busuioc.alexandru+gpg-test@gmail.com
You selected this USER-ID:
"Alexandru Busuioc <busuioc.alexandru+gpg-test@gmail.com>"
Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
<THE PASSWORD IS ASKED FOR>
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: revocation certificate stored as '/Users/alexandru.busuioc/.gnupg/openpgp-revocs.d/841D7C49F6DADD8EA24B39FC23C265EE32418B55.rev'
public and secret key created and signed.
pub ed25519 2024-07-30 [SC] [expires: 2027-07-30]
841D7C49F6DADD8EA24B39FC23C265EE32418B55
uid Alexandru Busuioc <busuioc.alexandru+gpg-test@gmail.com>
sub cv25519 2024-07-30 [E] [expires: 2027-07-30]
# send keys to a key server
> gpg --send-keys 841D7C49F6DADD8EA24B39FC23C265EE32418B55
gpg: sending key 23C265EE32418B55 to hkps://keyserver.ubuntu.com
# export the secret key (password protected)
> gpg --armor --export-secret-keys 841D7C49F6DADD8EA24B39FC23C265EE32418B55
<THE PASSWORD IS ASKED>
-----BEGIN PGP PRIVATE KEY BLOCK-----
lFgEZqjX1hYJKwYBBAHaRw8BAQdAmm9GLd89k300ikTwJP2IgFHQGNIxDG3j+yK2
FkwWE6MAAP9d8CLVAke+RJ2gwGKZ2GQfY09UfgZrx9IXlFv/5PTWFhE4tDhBbGV4
YW5kcnUgQnVzdWlvYyA8YnVzdWlvYy5hbGV4YW5kcnUrZ3BnLXRlc3RAZ21haWwu
Y29tPoiZBBMWCgBBFiEEhB18Sfba3Y6iSzn8I8Jl7jJBi1UFAmao19YCGwMFCQWj
moAFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQI8Jl7jJBi1VOqQD/bc3O
6gukU1CTyJC875Y0BO8UznuD5HyelDMOWVKOjJQBAOmJE3lkp54+5GEIPVS8INLx
8FIr/jbmT+Gzd9iL86oInIsEZqjX1hIKKwYBBAGXVQEFAQEHQJo87+B2cPYZC/GA
we9T3zyhOBOHmKsPA2qTE2UWJgQ5AwEIB/4HAwIZCnDiEsxKIv8NTbSQs2JmPMoB
teUMHGMc6wedfrD0a/PIBCQ0dAbfoWwtYub3boCQlo7U+Ruh+oyITYl86n0LEOE+
R0SbQdkC5PaAabr0iH4EGBYKACYWIQSEHXxJ9trdjqJLOfwjwmXuMkGLVQUCZqjX
1gIbDAUJBaOagAAKCRAjwmXuMkGLVYQEAQD6WBPROBTp8+mZ6C09xlwqtNMup0he
Lj8hf9neXHhoigD/aTBqnkBtj0QIOBl9d6K/Fq9CYgX9h5rzq8Gud0hjogc=
=zZQt
-----END PGP PRIVATE KEY BLOCK-----
What I put in Bitwarden secure note:
echo '-----BEGIN PGP PRIVATE KEY BLOCK-----
lFgEZqjX1hYJKwYBBAHaRw8BAQdAmm9GLd89k300ikTwJP2IgFHQGNIxDG3j+yK2
FkwWE6MAAP9d8CLVAke+RJ2gwGKZ2GQfY09UfgZrx9IXlFv/5PTWFhE4tDhBbGV4
YW5kcnUgQnVzdWlvYyA8YnVzdWlvYy5hbGV4YW5kcnUrZ3BnLXRlc3RAZ21haWwu
Y29tPoiZBBMWCgBBFiEEhB18Sfba3Y6iSzn8I8Jl7jJBi1UFAmao19YCGwMFCQWj
moAFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQI8Jl7jJBi1VOqQD/bc3O
6gukU1CTyJC875Y0BO8UznuD5HyelDMOWVKOjJQBAOmJE3lkp54+5GEIPVS8INLx
8FIr/jbmT+Gzd9iL86oInIsEZqjX1hIKKwYBBAGXVQEFAQEHQJo87+B2cPYZC/GA
we9T3zyhOBOHmKsPA2qTE2UWJgQ5AwEIB/4HAwIZCnDiEsxKIv8NTbSQs2JmPMoB
teUMHGMc6wedfrD0a/PIBCQ0dAbfoWwtYub3boCQlo7U+Ruh+oyITYl86n0LEOE+
R0SbQdkC5PaAabr0iH4EGBYKACYWIQSEHXxJ9trdjqJLOfwjwmXuMkGLVQUCZqjX
1gIbDAUJBaOagAAKCRAjwmXuMkGLVYQEAQD6WBPROBTp8+mZ6C09xlwqtNMup0he
Lj8hf9neXHhoigD/aTBqnkBtj0QIOBl9d6K/Fq9CYgX9h5rzq8Gud0hjogc=
=zZQt
-----END PGP PRIVATE KEY BLOCK-----' | gpg --batch --import -
This is the script I run to import the secret key to another machine where I want to sign.
In conclusion
Using GPG for commit signing is a valuable practice for developers concerned with security and code integrity. By creating, managing, and securely storing your GPG keys – whether using Bitwarden as suggested or another secure method – you can easily implement this extra layer of verification across different development environments. Remember to publish your public key to well-known key servers to enable others to verify your signatures. With these steps, you’re not just writing code; you’re actively contributing to a more secure and trustworthy development ecosystem. As the digital landscape continues to evolve, adopting tools like GPG becomes increasingly important in maintaining the integrity and authenticity of our work as developers.