Want to see that sweet :heavy_check_mark: Verified status on your GitHub commit history? This guide walks through how to setup and configure everything needed on a Windows system!

Install GnuPG (GPG)

I’m a big fan of leveraging Chocolatey for package management on Windows. It makes things really easy to find and install software, and keep things up to date.

If you dont have Chocolatey already installed, head over to https://chocolatey.org/install and follow the instructions.

Install GnuPG with Chocolatey by opening an elevated PowerShell prompt and running the following:

choco install gnupg

If you prefer to install GnuPG manually you can download it here: https://www.gnupg.org/download/index.html

Generate a GPG key pair

Run the following command to start the wizard to generate your first GPG key:

gpg --full-generate-key

When prompted for GPG options provide the following:

PromptResponseNote
Please select what kind of key you want:(1) RSA and RSA (default)GitHub supported GPG key algorithms
What keysize do you want:4096GitHub minimum is 4096
Please specify how long the key should be valid:1yNo requirements from GitHub
Real name:your name
Email address:your email addressMust match your verified email address with GitHub
Comment:GitHub Verification

You will be prompted for a passphrase to secure your key. Generate a nice secure password with something like LastPass to use.

You can confirm your key was generated by running:

gpg --list-keys

Configure git to use your signing key

We’ll need to provide git with the id of the GPG key to use for signing commits. The output from gpg --list-keys will contain the id.

gpg-key-id

Configure git to sign all commits using this id:

git config --global user.signingkey 50DB2A62E89EE4CFC5B4B9AE241F81E6BE8BABEB

On Windows I’ve found that I also need to provide git with the filesystem path to the gpg executable. Without this option I’ve received messages from git such as gpg: signing failed: No secret key. Configure git with this option (you may need to adjust your filesystem path to gpg.exe):

git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe"

Add your public key to GitHub

We need to provide GitHub with the public key of the PGP key pair we generated. Run the following command to export the public key:

gpg --armor --export 50DB2A62E89EE4CFC5B4B9AE241F81E6BE8BABEB

Copy all of the text including the BEGIN PGP PUBLIC KEY and END PGP PUBLIC KEY lines.

On GitHub navigate to your account Settings and SSH and GPG keys. Click New GPG Key, paste your public key text in the text box, and click Add GPG key. You should now see the key stored in your GitHub account.

gh-key-ss

Signing commits

You should be all setup to sign commits now. When using git from a shell you need to add the -S option to indicate the commit should be signed with gpg:

git commit -S -m "this commit is signed"

Git can also be configured to automatically sign all commits. With this option configured your commits from VSCode will also be signed.

git config --global commit.gpgsign true

Test out making a new commit and push to a GitHub repo, goto Code and commits and you should see the wonderful, green Verified badge!

gh-verified

Reduce GPG passphrase prompts

The passphrase you provided when generating your gpg is used to lock and unlock access to your private key when git attempts to sign a commit. The first time you instruct git to sign a commit you should be greeted by a passphrase prompt similar to this screenshot:

gpg-passphrase

When you installed GnuPG, it also installed and runs a service named gpg-agent.exe that is responsible for caching this passphrase so you’re not prompted for it on every single commit. The default TTL for a cached passphrase however is 10 minutes. This is quite short for me, I’m not making commits every 10 minutes so it just ended up feeling like I was prompted for this passphrase every time. gpg-agent.exe contains some configuration options so we can adjust this behavior.

List all of gpg-agent.exe current configuration options using the following:

gpgconf --list-options gpg-agent

The options we need to configure are default-cache-ttl and max-cache-ttl. Both of these are configured with the number of seconds to cache the passphrase. The screenshot below shows the default values for both configuration options; default-cache-ttl set to 600, and max-cache-ttl set to 7200.

gpg-cachettl-1

gpg-agent.exe reads its configuration from a file named gpg-agent.conf. This file needs to be in %APPDATA%\gnupg. By default this file does not exist, you will need to create it. You can use the PowerShell oneliner below to create the file and configure both options to 86400 (24 hours).

Set-Content -Path $ENV:APPDATA\gnupg\gpg-agent.conf -Value "default-cache-ttl 86400$([System.Environment]::NewLine)max-cache-ttl 86400"

Run the following to restart gpg-agent.exe, and then verify the configuration options again:

gpgconf --kill gpg-agent

gpgconf --list-options gpg-agent

You should see 86400 as the configured value for both default-cache-ttl and max-cache-ttl

gpg-cachettl-2

NOTE: There is a good bit of guidance that states the gpg-agent.conf file needs to be in %USERPROFILE%\.gnupg, however this would never work for me. If you have trouble getting gpg-agent.exe to pick up the configuration changes try changing the file path and restarting the agent again.