Posted on :: 729 Words :: Tags: , ,

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.

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/policy0

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.

publicbucket

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):

r2tokenperms

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