Table of Contents
Proton mail supports GPG WKD which allows mail clients to lookup GPG keys to use. Only some clients support this but it seems very cool.
I have a custom domain in ProtonMail which will not be automagically setup with this, so I wanted to set it up.
Looking at whats available there is Web Key Directory(WKD) and Web Key Service(WSK), WKS is a service that attempts to make this simpler in the long term, but to me WKD seems much easier for small scale given it seems to just be hosting a web directory and file structure, something that can be hosted in S3 or R2. Given my domain is within Cloudflare I wanted to try keep everything together so went with the WKD option intending to use it on Cloudflare R2.m
WKD
To get started I read some blogs which go through the two methods, one using a subdomain and one using a different file structure.
- https://bacardi55.io/2023/02/05/setting-up-openpgp-web-key-directory-wkd/
- https://www.uriports.com/blog/setting-up-openpgp-web-key-directory/
- https://wiki.gnupg.org/WKD
Both seem pretty straight forward with what is necessary. If I want people to retrieve my public key for [email protected]
I need a subdomain of openpgpkey.mydomain.com
and it needs a directory structure looking like:
/.well-known/openpgpkey/mydomain.com/hu/<"michael" hashed SHA-1 then encoded Z-Base-32>
/.well-known/openpgpkey/mydomain.com/policy
0
The policy file can be an empty file you create, it appears to allow some other options which I briefly looked over in the specification and then decided blank is fine.
I went and downloaded the public key for my email address from ProtonMail and created a .well-known
directory. I imported the key into my keychain:
gpg --import [email protected]
OpenGPG provides a tool gpg-wks-client
which helps setup the directory structure and does the name hashing etc for us using gpg-wks-client -v install-key
where you can pipe the key through to.
mkdir -p .well-known/openpgpkey
cd .well-known
gpg --list-options show-only-fpr-mbox -k [email protected] | gpg-wks-client -v install-key
# gpg-wks-client: using key with user id '[email protected] <[email protected]>'
# gpg-wks-client: directory 'openpgpkey/mydomain.com' created
# gpg-wks-client: directory 'openpgpkey/mydomain.com/hu' created
# gpg-wks-client: policy file 'openpgpkey/mydomain.com/policy' created
# gpg-wks-client: key XXXXXXXX published for '[email protected]'
This sets up the correct directory structure for us, now I just need to host it somewhere.
exa --tree .well-known
# .well-known
# └── openpgpkey
# └── mydomain.com
# ├── hu
# │ └── n6h6dt1ftdd9w3y3sujj5oxwejt8uqob
# └── policy
Cloudflare R2
Cloudflare R2 gives us S3 type functionality, the free tier gives up to 10GB, and to make a bucket public we can just set a subdomain to point to the bucket from Cloudflare.
So I created a bucket called gpg
and then set the subdomain openpgpkey
on my domain (As specified by the WKD documentation) to make it public.
To sync my local directory structure into the bucket, rather that individually uploading, I went to the R2 documentation and was pleasantly surprised to find help for using rclone: https://developers.cloudflare.com/r2/examples/rclone/
rclone
is some cool software that lets you sync files with all manner of backends. I found the Cloudflare guide quite straight forward.
Create a API token (I made mine as restrictive as possible, only object read write, and only for the gpg bucket):
Setup rclone
with this easy config in my ~/.config/rclone/rclone.conf
(Including the no_check_bucket = true
that was told to me by the note proclaiming "If you are using a token with Object-level permissions, you will need to add no_check_bucket = true
to the configuration to avoid errors" ):
[r2gpg]
type = s3
provider = Cloudflare
access_key_id = abc123
secret_access_key = xyz456
endpoint = https://<accountid>.r2.cloudflarestorage.com
acl = private
no_check_bucket = true
And off we go.
rclone -v sync .well-known r2gpg:gpg/.well-known
rclone tree r2gpg:gpg/.well-known/
# /
# └── openpgpkey
# └── mydomain.com
# ├── hu
# │ └── n6h6dt1ftdd9w3y3sujj5oxwejt8uqob
# └── policy
#
# 3 directories, 2 files
Now when I visited my openpgp
domain, I could browse this file structure. The final test was if gpg-wks-client
would magically find my key if I searched for my email address.
gpg-wks-client -v check [email protected]
# gpg-wks-client: public key for '[email protected]' found via WKD
# gpg-wks-client: fingerprint: XXXXXXXX
# gpg-wks-client: user-id: [email protected] <[email protected]>
# gpg-wks-client: created: Fri 14 Jun 09:17:34 2024 BST
# gpg-wks-client: addr-spec: [email protected]
Yay! Now technically clients that support WKD should automatically lookup if I have a key and can send me encrypted mails on that domain. To update the key or add new keys I can just sync them with the R2 bucket.
The next step for managing keys if I had to do a bit more might be to have them in a git
repository and either have a worker update the R2 bucket, or make use of git pages using a CNAME and have it automatically provisioned that way.
Other options might be using the full Web Key Service or another project I found that seemed interesting was Mailvelope Keyserver