DEV Community

Benjamin Black
Benjamin Black

Posted on • Updated on

Signing Git commits with GPG keys that use modern encryption

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Choose option (1) Curve 25519 for the next prompt:

Please select which elliptic curve you want:
   (1) Curve 25519
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Complete the rest of the steps, and then use the save command at the CLI prompt to save and exit.

gpg> save
$
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

Finally, just tell Git to sign everything with this signing key (step 4 in the Github documentation).

$ git config --global user.signingkey 599D272D
Enter fullscreen mode Exit fullscreen mode

And now our Git commits will be signed with a signing-only GPG subkey that uses Ed25519 encryption.

Top comments (2)

Collapse
 
energeticpixels profile image
Anthony Jackman

@benjaminblack I love the article. Sounds too simple. If I happen to use the same computer (same computer user) to work with two separate github accounts, is there a way to sign commits with two separate signatures? I have a personal github account and a work (day job) account that I need to properly sign commits for.

Collapse
 
benjaminblack profile image
Benjamin Black • Edited

What you want is nominally separate global .gitconfig configurations depending on the project. Then you can set up separate signing keys for each configuration.

See this SO question:

stackoverflow.com/questions/422041...