git diff on PGP keys

3 minute read Published: 2022-08-08

Using git diff on PGP keys

Reasoning about changes to PGP keys is a bit difficult. A changed expiration date, revoked user IDs, added certifications, and so, you don't see that when looking at the file. When they're tracked in a git repo, asking git diff is going to be of little to no help. Either they are binary files, and you don't see anything, or they are pem encoded / ASCII armored files, then you might see a bunch of changes that you can't read. But surely, git must have a solution for this?

The solution git provides here is called a "diff driver". You can match files in your repo via .gitattributes, to set the diff attribute to the name of the driver you're going to use for generating a diff. For this to work, you need to have a specific file extension that you're using for PGP keys, so that you can match on that in your .gitattributes file. I'm using .pub for this, resulting in the following line in my .gitattributes file:

*.pub diff=pgp

Next up is getting into diff drivers. We want a textual diff that gives us information about what changed in the binary file, and luckily, git has a ready made way to handle such cases generically. diff.<driver>.textconv allows us to set a command for generating a textual representation of the binary blob we're examinating. Now let's add that to our git config:

[diff "pgp"]
	textconv = <command>

Well.. How do we show all of the data of a PGP key? There's two options here:

I prefer the output of Sequoia over the output of GnuPG, even though the GnuPG output is slightly more detailed than the Sequoia output, because it's a bit easier to grasp and there's less noise around, but that's a highly subjective matter, so if you want to try this, just play around with both and see what works for you.

Last but not least: Are we done here? Not really. The .gitattributes documentation has a whole section about choosing between textconv versus an external diff tool, because those also exist. An external diff tool would get both of the files and generate a diff output completely on it's own. This has benefits, because it allows us to be a bit smarter about what info we might want to display. If a key has a new signature on one UID, textconv based diffing does give us surrounding certifications, which is not really all that interesting information. The drawbacks to an external diff tool are additional complexity, and worse performance, because we need to run the diff tool for each combination of old and new file. When using textconv, you can cache those by setting cachetextconv to true, which does help if you look at git log -p for example and the same file was edited multiple times.