Web Key Directory (WKD) is a distributed protocol for automatically retrieving PGP keys for a given email address.
Why support this? Frankly, I don't use PGP for anything except as an option for logging into sites that use IndieLogin, via the markup on my homepage. One of the reasons for this is that PGP is largely incomprehensible. However, WKD seems to be a fairly useful step in the direction of making it more usable. Since the maintenance overhead of WKD for a single-user site is basically zero, I decided I might as well set it up.
Setting it up
WKD lives in the .well-known/ namespace, and can be implemented as a flat file structure. There is a more complex mechanism called Web Key Service which can be used for more dynamic implementations, but this is overkill for a personal site.
Generating the WKD directory structure can be done with the gpg-wks-server
command in recent versions of gnupg. The wiki page claims you should use gpg-wks-client
, but my installation doesn't have this tool and the server takes the same options. In my case, generating my directory looked like this:
>> mkdir openpgpkey >> gpg --list-options show-only-fpr-mbox -k vil@vil.lv | gpg-wks-server -v --install-key -C openpgpkey gpg-wks-server: gpg: Total number processed: 1 gpg-wks-server: using key with user id 'vilhalmer <vil@vil.lv>' gpg-wks-server: gpg: Total number processed: 1 gpg-wks-server: directory 'openpgpkey/vil.lv' created gpg-wks-server: directory 'openpgpkey/vil.lv/hu' created gpg-wks-server: policy file 'openpgpkey/vil.lv/policy' created gpg-wks-server: key 7CFAF4A3748190EB6EAC778005FA2E1C6481BDF3 published for 'vil@vil.lv'
You'll notice that the directory structure includes the domain. In the case of a personal site, you actually need to remove this layer from the path. From the wiki:
The hu directory has to be published on your server as https://openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/ (or https://example.com/.well-known/openpgpkey/hu/ iff openpgpkey.example.com is not resolvable via DNS).In our case, we didn't add an
openpgpkey
subdomain, so we need to follow the parenthetical rule.
>> cd openpgpkey >> mv vil.lv/* . >> rmdir vil.lv
Now the openpgpkey
directory needs to be published to .well-known/
at the root of your site. This is left as an exercise to the reader. :)
I had to add the execute bit to the hu
subdirectory in order for nginx to be willing to serve the file within. I have other rules in place to prevent directory listings as the wiki specifies you should. This recommendation probably doesn't matter so much on a single-user site anyway, but is instead designed to prevent user enumeration on a shared instance.
Finally, I verified that my key was fetchable. To be explicit you can add --auto-key-locate wkd
, but this has been the preferred mechanism for a while.
>> gpg --locate-external-keys vil@vil.lv gpg: key 05FA2E1C6481BDF3: "vilhalmer <vil@vil.lv>" not changed gpg: Total number processed: 1 gpg: unchanged: 1 pub rsa4096 2016-04-05 [SC] 7CFAF4A3748190EB6EAC778005FA2E1C6481BDF3 uid [ultimate] vilhalmerTada!sub rsa2048 2016-04-05 [E] [expires: 2024-04-03] sub rsa2048 2016-04-05 [SA] [expires: 2024-04-03]
Troubleshooting
If it doesn't work, you'll see something like this instead:
>> gpg --locate-external-keys vil@vil.lv gpg: error retrieving 'vil@vil.lv' via WKD: No data gpg: error reading key: No data
If things aren't in quite the right place on the first try and gpg is unable to find the .well-known/
path when you query for your key, it will cache the belief that the domain does not support WKD. This makes it difficult to test again after you adjust things. You can tell this is happening by running gpg verbosely and looking for the following line:
gpg: Note: WKD uses a cached resultRestarting your
dirmngr
process will clear this internal cache and allow you to query again.