PGP Key Discovery Mechanisms Explained

Table of Contents

Okay, final thing on PGP after talking about PGP itself and Signature and trust levels, we have… How you can get someone else’s public key.

There’s a few common ways to do this:

  • Keyservers
  • Web Key Directory
  • DNS
    • CERT record
    • PKA TXT record
    • DANE OPENPGPKEY record

Let’s discuss how they all work.

PGP Keyservers (HKP Protocol)

This is pretty much the most common form of distributing and sharing keys: using a web keyserver, or keyserver pool, like keyserver.ubuntu.com or keys.gnupg.net. The protocol used here is the… HTTP Keyserver Protocol, or HKP (HKPS if over HTTPS). And by “protocol” I mean “very specific HTTP query strings”. For example, if I wanted to ask keys.gnupg.net for the key with this fingerprint:

C1CB 0206 9205 8541 6627  6FD2 998E A222 3673 9B9B

I could use this curl invocation:

curl https://keys.gnupg.net:11371/pks/lookup?op=get&search=0xC1CB02069205854166276FD2998EA22236739B9B&options=mr

Let’s break that down if you don’t see the pattern:

  • We send a HTTP request to, by default, port 11371
  • The path is always /pks/lookup
  • The op parameter specifies the operation, in this case, get to retrieve a specific key. Others might include index to get a list of matching keys, or the like.
  • The search parameter is the search string we’re using, in this case, it’s the entire key fingerprint, prefixed with 0x.
  • The options variable contains mr, meaning the response to this request should be machine readable.

You will rarely need to interact with this directly, since just about any PGP software on the planet will know how to talk to keyservers, and you’re free to send, search, and receive, using their interface as much as you like. Just note that once your key is in a server, usually, it can’t get fully deleted, so don’t publish keys unless you intend to share them with the world.

Keyservers are nice for people who don’t have authoritative control of the domain in their user ID, like users that have keys with gmail.com addresses in them.

Web Key Directory Protocol

Here’s a weird, but cool one. WKD, or Web Key Directory, is another method of fetching keys via HTTP, but this one doesn’t have a reliance on external keyservers. WKD works by placing keys in a “well-known” location on a domain’s webserver, allowing HTTP requests to be made to grab a file containing key data.

For a domain, say, example.com, all requests are to files in https://example.com/.well-known/openpgpkey/hu/, where the file name is a hash of the user-part of the email address. For example, the user-ID, and, thus, email address, [email protected] would translate to looking up:

https://example.com/.well-known/openpgpkey/hu/iffe93qcsgp4c8ncbb378rxjo6cn9q6u

There are a few other requirements though:

  • The Access-Control-Allow-Origin header mush be present for this resource, and have a value of “*”.
  • A policy file at /.well-known/openpgpkey/policy must exist, but, since it has no useful information right now, is just an empty file.
  • The file much contain the binary (not ASCII-armored) representation of the key block

A companion service called WKS exists to automatically manage keys in your WKD, but we won’t cover that right now.

Additionally, there is an “advanced” lookup method, that prepends openpgpkey to the domain name, but otherwise has the same path, meaning that there are two addresses one can fetch a potential key from:

https://example.com/.well-known/openpgpkey/hu/iffe93qcsgp4c8ncbb378rxjo6cn9q6u
https://openpgpkey.example.com/.well-known/openpgpkey/hu/iffe93qcsgp4c8ncbb378rxjo6cn9q6u

Only if you’re a domain owner of service provider would you likely be able to set up WKD, since it requires access to the webserver of the domain name in your user ID.

Fetching Keys from DNS

This one you have to seriously be a domain owner, because you need to modify the DNS records for the domain in your user ID, which is something that, unless you own said domain, you’re likely not ever going to have access to. But since it does exist, I’ll cover it.

Using CERT Records

Cert records might not be recognized in whatever DNS manager you’re using, but they do exist as type 37, which most servers, like BIND, will understand by specifying the record type as TYPE37. Note that… you’re likely not going to write these by hand. A tool called make-dns-cert is all you need, which can take in a key file, and a domain name, and spit out a zone file compatible TYPE37 record which contains…. your entire key. This is nice because it’s one self-contained thing, but the disadvantage is that means that it’s huge. Any client that doesn’t support EDNS or DNS-over-TCP is just not going to be able to retrieve a data block that large, and like I said before, most servers don’t have support for CERT records like that.

There is a short mode for CERT records, which makes them behave more like PKA — If you give make-dns-cert a URL and a fingerprint instead of a key file, it will make a binary CERT record that’s much shorter and behaves almost identically to the PKA records that are discussed below.

Using PKA Records

Honestly, this one is the simplest, for people that can do it. First, you take your email address, say, [email protected]. You use _pka to replace the @, meaning the DNS record will live at test._pka.example.com. The record is comprised of three fields: the version (which is always pka1 ), a fingerprint, and a URI where the key can be fetched. Here’s an example PKA record:

test._pka.example.com    TXT    "v=pka1;fpr=C1CB02069205854166276FD2998EA22236739B9B;uri=https://example.com/keys/test.pub.txt"

All you’d need to do after that is to actually make the file test.pub.txt there contain the ascii-armored (read: PEM encoded) public key block for the key specified by that fingerprint.

The advantage of using PKA records is that they’re small — just a fingerprint and a URI, but the disadvantage is that they’re not self-contained, you still need to actually make the file on the webserver that it points to.

Using OPENPGPKEY Records

These are the weirdest of them all, since there’s almost no documentation, despite being one of two with actual RFCs behind them.

The DNS label for these is weird, where, instead of PKA, which used user._pka.domain, this uses hash._openpgpkey.domain, leading to the record for [email protected] to exist at:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15._openpgpkey.example.com

Yes, that’s the hexadecimal representation of the first 28 bytes of the SHA-256 hash of the user part. I don’t even.

Even better, the OPENPGPKEY format does encode your entire key into binary data in the record, but it doesn’t store everything, the RFC itself defines a lot of fields that should be stripped away to shorten the message size.

Conclusion

if you’re going the DNS route, just use PKA records. They’re just text, human readable, human writable, small, and can be trivially parsed by more than just specific PGP applications. Realistically though, don’t use DNS. Either publish your key to a well-known HKP server, or, if you do own your own mail domain, you can put your key there for WKD, but for 99% of people, keyservers are good enough for everything.