Skip to content
Trey Griffith edited this page Jun 12, 2013 · 2 revisions

HTTP Authoritative Keyserver Protocol

This document defines HTTP Authoritative Keyserver Protocol (HAKP). The IETF draft of this HTTP Keyserver Protocol is the basis for much of the HAKP, and it was itself based on earlier implementations of Keyservers, such as Marc Horowitz's Public Key Server.

Although the above draft was never approved, HKP is the de facto standard for keyservers. HAKP is based on HKP, but uses a substantially different API, as its use case is very different.

HAKP places an emphasis on REST principles, and the usage of a Keyserver as an Authoritative Key Server. As such, it does not implement all of the same methods as HKP, and the methods it does implement are done so in a substantially different way. HAKP should be considered incompatible with HKP.

However, due to the many benefits of HKP, including the use of existing technologies such as SKS, the protocol is designed such that a server may use both HAKP and HKP, similar to the way in which a Domain Name Server and an Authoritative Domain Name server may be the same server.

SRV Records

A Keyserver is designated as "Authoritative" for a domain by adding a Service (SRV) Record to the DNS records for the domain. This means that all users of that domain that have PGP Keys will have the official version (up-to-date, valid, etc) located on the designated Authoritative Keyserver.

The symbolic name for the Authoritative Keyserver is hakp, and the underlying protocol is tcp.

An SRV Record might appear as follows:

_hakp._tcp.example.com 86400 IN SRV 0 5 80 keys.example.com.

In this example, keys.example.com is the Authoritative Keyserver for example.com, and it is available on port 80.

Authoritative Keyservers are available over HTTP or HTTPS, so the most common ports will be 80 and 443. However, the traditional HKP port of 11371 is also a likely choice.

If the Keyserver acts as both a HKP Keyserver as well as a HAKP Keyserver, both services should be designated separately within the DNS records.

Public API

Retrieving all the users on a keyserver

HKP defined the index of the keys as all of the individual keyid's. While technically true, for use as an authoritative supplier of keys for users it is more helpful to have an index of users with keys, regardless of whether or not some of those users (again defined by unique email addresses) have the same key.

HAKP uses this more practical definition of an index, which is retrieved by sending a GET request to /users/. The response is a JSON object, which has two properties: version and keys. version defines the version of the HAKP protocol in use, in our case it is always 1. keys are an array of key objects, corresponding to all the unique users who have keys on this server. Each key object has a single property defined, path, which defines the relative path (not the absolute path) to the user's Public Key Block.

GET http://keys.example.com/users/

could return:

{
	"version": 1,
	"keys": [
		{
			"path": "example.com/alice"
		},
		{
			"path": "example.com/bob"
		}
	]
}

HKP defined a parameter (mr) to designate whether a response should be machine-readable or human-readable. Since encryption is generally something better undertaken by machines than humans, HAKP assumes all requests to be machine-readable, but the responses are in formats (JSON) that are also easily read by humans.

Each key object can optionally contain additional properties describing the key, including the keyid, algorithm, etc., but the protocol only requires the path property.

Retrieving all the users for a domain on a keyserver

As might be expected from the paths returned from index, it is possible to retrieve all the users for a particular domain by using the domain as a the endpoint. The JSON object returned is the same as for the index route, but the paths do not include the domain as they are relative to the current endpoint.

GET http://keys.example.com/users/example.com/

could return:

{
	"version": 1,
	"keys": [
		{
			"path": "alice"
		},
		{
			"path": "bob"
		}
	]
}

Retrieving a user's public key

HKP relied on string searching to find the key id for a particular user, and then GETing that key id to retrieve the Public Key Block. HAKP, by contrast does not support string searching, and instead returns the Public Key Block for a user (as defined by a unique email address) when sending a GET request to /users/:domain/:user. For example, to retrieve the public key block for [email protected], this request:

GET http://keys.example.com/users/example.com/alice

could return:

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.1 (GNU/Linux)
Comment: For info see http://www.gnupg.org
	
mQGiBDkHP3URBACkWGsYh43pkXU9wj/X1G67K8/DSrl85r7dNtHNfLL/ewil10k2
q8saWJn26QZPsDVqdUJMOdHfJ6kQTAt9NzQbgcVrxLYNfgeBsvkHF/POtnYcZRgL
tZ6syBBWs8JB4xt5V09iJSGAMPUQE8Jpdn2aRXPApdoDw179LM8Rq6r+gwCg5ZZa
pGNlkgFu24WM5wC1zg4QTbMD/3MJCSxfL99Ek5HXcB3yhj+o0LmIrGAVBgoWdrRd
BIGjQQFhV1NSwC8YhN/4nGHWpaTxgEtnb4CI1wI/G3DK9olYMyRJinkGJ6XYfP3b
cCQmqATDF5ugIAmdditnw7deXqn/eavaMxRXJM/RQSgJJyVpbAO2OqKe6L6Inb5H
kjcZA/9obTm499dDMRQ/CNR92fA5pr0zriy/ziLUow+cqI59nt+bEb9nY1mfmUN6
SW0jCH+pIQH5lerV+EookyOyq3ocUdjeRYF/d2jl9xmeSyL2H3tDvnuE6vgqFU/N
sdvby4B2Iku7S/h06W6GPQAe+pzdyX9vS+Pnf8osu7W3j60WprQkUGF1bCBHYWxs
YWdoZXIgPHBhdWxnYWxsQHJlZGhhdC5jb20+iFYEExECABYFAjkHP3UECwoEAwMV
AwIDFgIBAheAAAoJEJECmvGCPSWpMjQAoNF2zvRgdR/8or9pBhu95zeSnkb7AKCm
/uXVS0a5KoN7J61/1vEwx11poLkBQdQ5Bz+MEAQA8ztcWRJjW8cHCgLaE402jyqQ
37gDT/n4VS66nU+YItzDFScVmgMuFRzhibLblfO9TpZzxEbSF3T6p9hLLnHCQ1bD
HRsKfh0eJYMMqB3+HyUpNeqCMEEd9AnWD9P4rQtO7Pes38sV0lX0OSvsTyMG9wEB
vSNZk+Rl+phA55r1s8cAAwUEAJjqazvk0bgFrw1OPG9m7fEeDlvPSV6HSA0fvz4w
c7ckfpuxg/URQNf3TJA00Acprk8Gg8J2CtebAyR/sP5IsrK5l1luGdk+l0M85FpT
/cen2OdJtToAF/6fGnIkeCeP1O5aWTbDgdAUHBRykpdWU3GJ7NS6923fVg5khQWg
uwrAiEYEGBECAAYFAjkHP4wACgkQkQKa8YI9JamliwCfXox/HjlorMKnQRJkeBcZ
iLyPH1QAoI33Ft/0HBqLtqdtP4vWYQRbibjW
=BMEc
-----END PGP PUBLIC KEY BLOCK-----

Spam Concerns

There are legitimate concerns that exposing all the users on a keyserver with a simple GET request, or all the users of a particular domain can lead to users who are published in this way to be targeted by spammers. Some Public Key Servers, such as the PGP Global Directory, have attempted to combat spam by requiring users to solve a CAPTCHA before they are granted access to the API. However, since the philosophy of HAKP is that machines, not humans, should be handling encryption, a CAPTCHA is decidely the wrong mechanism.

HAKP makes requests for all the users of a keyserver easier, but fundamentally presents the same opportunity for spammers. To combat this, individual implementations can choose to not make the Index methods accessible. The only method that is required for HAKP is retrieving the public key for a single user. In AKS's implementation, the option useIndex can be set to false to disable these methods. In addition to disabling index methods, implemenations may choose to use rate limits, API keys, or other methods to attempt to stop spammers from accessing the keyserver.

Multiple Users for a Single Key

Multiple unique email addresses can be associated with a single PGP key. HKP approached the key as the fundamental unit, and listed all of the users for which the key was applicable. Since there are very few applications for which it would be useful to know all the users of a particular key, instead of the key for a particular user, HAKP takes a fundamentally different approach.

However, one of the instances in which it would be useful to know all the users for a single key would be communicating with a large group that all shared a single PGP key. This scenario is one in which the members of the group corresponded about the shared group key ahead of time, and as a result, a Keyserver is not a necessity.

If this scenario (or others like it) do turn out to be an important use for HAKP Keyservers, the protocol can be expanded, perhaps through a /groups endpoint.