Signing Git commits with GPG keys that use modern encryption
Benjamin Black
Posted on January 2, 2021
My posts are usually notes and reference materials for myself, which I publish here with the hope that others might find them useful.
Git can be easily configured so that commits are cryptographically signed. The Github documentation is fairly straightforward, but I find the defaults unpalatable, so I will tweak them a bit.
In particular, I prefer to use the strongest available modern encryption, specifically EdDSA using SHA-512 and the 25519 curve, aka Ed25519.
Also, I like to create a signing-only subkey that is exclusively used for signing.
That requires some extra steps.
Creating a Ed25519 master key
First, we make sure that GPG supports EdDSA public key cryptography:
$ gpg --version
...
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
If our version of GnuPG was built without support for EdDSA, we're out of luck.
Next, generating an Ed25519 master key is still considered an 'expert' option, so we invoke gpg
with --expert
, and for the first prompt, select option (9) ECC and ECC
(Elliptic Curve Cryptography) for the type of key:
$ gpg --full-generate-key --expert
...
Please select what kind of key you want:
...
(9) ECC and ECC
Choose option (1) Curve 25519
for the next prompt:
Please select which elliptic curve you want:
(1) Curve 25519
The rest of the prompts to generate the master key are straightforward.
Once it's finished we can confirm the new master key uses Ed25519 with gpg --list-keys
.
$ gpg --list-keys --keyid-format short
...
---------------------------
pub ed25519/4AC7128F 2021-01-02 [SC]
[redacted]
uid [ultimate] Benjamin Black <benjamin.black@example.com>
sub cv25519/885EBFBA 2021-01-02 [E]
Creating a signing-only subkey
Observe that GPG creates the master key for signing (S) and for certificate creation (C) ([SC]
), and automatically creates a subkey for encryption ([E]
).
So we can use the master key for signing, and that is what both the Github and the official Git documentation suggest, but that is not best practice.
Instead, we should create a signing subkey explicitly for signing Git commits. We'll use the GPG CLI create it.
Begin by editing the master key, again passing --expert
:
$ gpg --expert --edit-key 4AC7128F
...
sec ed25519/B1ED9EFC4AC7128F
created: 2021-01-02 expires: never usage: SC
trust: ultimate validity: ultimate
ssb cv25519/78317B8E885EBFBA
created: 2021-01-02 expires: never usage: E
[ultimate] (1). Benjamin Black <benjamin.black@example.com>
gpg>
Then use the GPG CLI command addkey
and select option (10) ECC (sign only)
for the first prompt, and option (1) Curve 25519
for the second prompt.
gpg> addkey
Please select what kind of key you want:
...
(10) ECC (sign only)
...
Your selection? 10
Please select which elliptic curve you want:
(1) Curve 25519
...
Your selection? 1
Complete the rest of the steps, and then use the save
command at the CLI prompt to save and exit.
gpg> save
$
Now if we list keys, we'll see the newly created signing key.
$ gpg --list-keys --keyid-format short
...
sub ed25519/599D272D 2021-01-02 [S]
Finally, just tell Git to sign everything with this signing key (step 4 in the Github documentation).
$ git config --global user.signingkey 599D272D
And now our Git commits will be signed with a signing-only GPG subkey that uses Ed25519 encryption.
Posted on January 2, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.