Technical Blog

Discovering OpenPGP Keys Over HTTP

Posted on

First off, why would one want to do this? Well, cryptographic security is useful in communications medium other than email, and sometimes one may not have an email address for the person one is contacting. Also, a public key got from someone’s profile page is more likely to be their current key than the one got off a keyserver. Finally, if the discovery is done over TLS (or upcoming XRD signing techinques) then one can use the PKI to verify that the public key is, at very least, the one the owner of the URL claims. Which, for pseudonymous communications, may often be enough.

I will here propose three different ways to make this discovery work. Consumers must try all three. Publishers may publish more than one.

Content Negotiation

A public key represents a person. If a URL represents a person (such as on a profile page), then were that page’s data to be represented in the OpenPGP key format, one would get the user’s OpenPGP public key.

Send the header Accept: application/pgp-keys along with an HTTP GET request. If the Content-Type on the response is application/pgp-keys then the body is the user’s OpenPGP public key.


If a GET or HEAD request is performed on the URL and in the headers is a Link header with rel=me and type=application/pgp-keys, then the URL of that link is the user’s OpenPGP public key.

If the Content-Type header of the GET request is text/html or application/xhtml+xml, then look in the page for <a> and <link> tags with rel=me and type=application/pgp-keys. If there is such a tag, then its href attribute is the URL to the user’s OpenPGP key.


If LRDD discovery is performed on an endpoint, leading to the discovery of an XRD document containing a section like the following:


Then the URI is the URI of the user’s OpenPGP key.

Security Considerations

The URLs used in all methods above should be either HTTPS URIs secured using TLS and a certificate issued by a CA known to the client, or data URIs.

Application to Other Crytography Schemes

Everything in this document applies equally well to public keys for any cryptography scheme, as long as the MIME types are changed appropriately.

6 Responses

David Recordon

Doesn’t useful key discovery require that it be done over SSL? No SSL means that there might be a man in the middle and thus the key could be incorrect. Signing the XRDS file means that the key used to sign either needs to chain up to a root via PKI that you trust or that you fetch the key to verify the signature over SSL. And round and round we go. 🙂

Stephen Paul Weber

The post does say that to do the discovery securely will require TLS or XRD signing. The XRD signing is (IIRC) being designed to be basically the same as TLS (with the same PKI) but done in a way that you don’t need configuration access on the webserver to do it.

If you’re just interested in unsecured discovery (ala keyserver) based on a person’s URL this is useful without TLS.

Stephen Paul Weber

It seems that X.509 certs have no registered MIME type, or even a single standard file format. It seems that PEM is just base64-encoded DER (with PGP-armour-style header/footer). And that both PEM and DER are often served using application/x-x509-ca-cert or application/x-x509-user-cert

Will Norris

Of course I like the third option the best. I wouldn’t suggest even attempting the first, given all the problems with that we’ve run in to with XRDS… plus it’s a bit difficult for some people to setup. The second option is fine as well, but of course XRD would be ideal.

As for the relationship value, I’m not sure that “me” is appropriate. It sort of works, but I’m wary of overloading rel=”me”. I think a new rel value would be better, at the very least for XRD (but if you’re going to do it there, you might as well do it in the link header as well).

Will Norris

and just for future reference, XRD’s Rel value must be a URI, so for “me” you would use “”

Stephen Paul Weber

@will I imagined you would be more interested in the third option. I, of course, as historically, prefer the first. While for YADIS the content negotiation was a bit of a hack, and I’ve been recently conviced by Eran’s arguments that it wasn’t a great idea, for this it seems basically to be what content negotiation was designed for. It may be difficult for some people to set up. Anyone comfortable with .htaccess files can do it pretty easily, though 🙂

Why is “me” not appropriate? Is not the semantic of “me”: “that resource also represents the same person as this one”?

Oh, I thought URIs might be necessary but wasn’t sure how to make that work. I’ll update the post.

Leave a Response