Configure OpenPGP Web Key Directory (WKD)
Encrypting emails with OpenPGP has always required having the recipient’s public key. Traditionally, that meant manually exchanging keys or searching public key servers which could be cumbersome and error-prone.
Recently I revisited the use of OpenPGP for my personal email and found that Web Key Directory (WKD) changes that by allowing anyone to securely and automatically fetch your key from your domain over HTTPs. It was proposed back in 2012 and has achieved wide adoption in recent years making it a practical choice. There are alternatives such as DNS-Based Authentication of Named Entities (DANE) however it does not appear to be as widely supported.
To make your public key available to others to discover using WKD, you have two choices. The direct method, or the advanced method. If you have an existing https website at the root of your email domain, then it is trivial to configure the direct method - we will cover how to do this at the end of this article.
Software can validate whether WKD is configured for a given domain by checking that a policy file exists at a defined URI. For example.com
this would be:
- Direct method
https://example.com/.well-known/openpgpkey/policy
- Advanced method
https://openpgpkey.example.com/.well-known/openpgpkey/example.com/policy
The advanced method is attempted first. Therefore to use the direct method you need to ensure that the openpgpkey subdomain does not resolve. Even if you haven’t configured this subdomain, check that you don’t have a wildcard entry.
Software using WKD will then attempt to obtain a binary version of the public key for a given email address. For [email protected]
this would be:
- Direct method
https://example.com/.well-known/openpgpkey/hu/ymokugqfbcxatz54t7pyjapzpc46w4we?l=andrew
- Advanced method
https://openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/ymokugqfbcxatz54t7pyjapzpc46w4we?l=andrew
The hash between the /hu/
and query parameters ?l=...
is a SHA-1 hash of the local part of the email address in lowercase (andrew), which is then encoded using the Z-Base-32 method. This reduces the likelihood of automated harvesting of email addresses.
Configure the direct method.
Generate the hash for a given email address using GnuPG, this example uses GnuPG 2.4.8.
gpg-wks-client print-wkd-hash [email protected]
The response will include a hash that you’ll need for the next step.
ymokugqfbcxatz54t7pyjapzpc46w4we [email protected]
Assuming that you have the ASCII-armored public key file (public-key.asc), use GnuPG to convert your public key to binary format with a filename of the hash generated in the previous step (ymokugqfbcxatz54t7pyjapzpc46w4we).
gpg -o ymokugqfbcxatz54t7pyjapzpc46w4we --dearmor public-key.asc
Now create a blank policy file.
touch policy
Upload the following files to your website at the following locations:
policy
->https://example.com/.well-known/openpgpkey/
ymokugqfbcxatz54t7pyjapzpc46w4we
->https://example.com/.well-known/openpgpkey/hu/
You need to ensure that the public keys served from the /hu/ directory are served with a Content-Header of application/octet-stream
. How this is achieved depends on your own configuration.
Test that WKD works using GnuPG.
gpg-wks-client check -v [email protected]
If it works you will see an output similar to this:
gpg-wks-client: public key for '[email protected]' found via WKD
gpg-wks-client: fingerprint: 80CFF50BD8ABA8D64113CE0CF27D85F21B52FE5D
gpg-wks-client: user-id: [email protected] <[email protected]>
gpg-wks-client: created: Sun 10 August 11:00:00 2025 BST
gpg-wks-client: addr-spec: [email protected]