Web Key Service
The contents originally came from The according blog post. Check https://gnupg.org/faq/wkd.html for official notes. (Last checked 2021-02-22 there are no additional notes.)
A Web Key Service is a service that allows users to upload keys per mail as described in the: Web Key Service (current draft)
It is one of many ways to provide a Web Key Directory.
- GnuPG >= 2.2.14, including the gpg-wks-server command.
- A mail server for your domain with the full authority on the user mail addresses for this domain.
- A Unix system where you have an account to receive mails to a dedicated mail address and to send mails via the sendmail tool. An account on the mail server will be the best choice.
- A web server for the same domain to deliver static pages over TLS. Re-direction to a different server is possible
- A GNU/Linux like server system (for example Ubuntu Server, Debian, CentOS, OpenSuse, FreeBSD).
Install GnuPG 2.2 (optional)
If the GnuPG packages from your distribution are current and include the additional tools, you are fine. Otherwise you can install a GnuPG locally from the latest public source code.
First you should create a new account on the machine. Let's use webkey. Nothing special is required; thus a simple
adduser --disabled-password webkey
as root will do. Add an .ssh/authorized_keys file to make it easy to access. Now download GnuPG source code from a trusted source, see https://gnupg.org/download/index.html.
cd ~webkey wget ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-2.1.15.tar.bz2 wget ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-2.1.15.tar.bz2.sig wget -O - https://gnupg.org/signature_key.html | gpg --import gpg --verify gnupg-2.1.15.tar.bz2.sig gnupg-2.1.15.tar.bz2
The last line uses the standard gpg to check that the integrity of the tarball. Then please verify that the displayed fingerprints match the desired ones; see https://gnupg.org/download/integrity_check.html for more on this.
The easiest way to install the latest GnuPG version is to use Speedo, which downloads, verifies and builds all dependent packages. To do this first unpack the tarball:
tar xjf gnupg-2.1.15.tar.bz2
On non GNU system you may need to use this instead:
zcat gnupg-2.1.15.tar.bz2 | tar xf -
make -f gnupg-2.1.15/build-aux/speedo.mk INSTALL_PREFIX=. \ speedo_pkg_gnupg_configure='--enable-gpg2-is-gpg \ --disable-g13 --enable-wks-tools' native
If you run into errors you are probably missing some development tools; install them and try again. If all succeeds you will notice a bunch of new directories below webkey's home directory:
PLAY bin include lib libexec sbin share swdb.lst swdb.lst.sig
Optionally you may delete what is not anymore required:
rm -rf PLAY include lib swdb.*
To make use of your new GnuPG installation you need to run this first (you should add it to webkey's .profile or .bashrc):
PATH="$HOME/bin:$PATH" LD_LIBRARY_PATH="$(pwd)/lib" export LD_LIBRARY_PATH
Prepare the mail and web servers
The Web Key Service requires a working directory to store keys pending for publication. As root create a working directory:
mkdir /var/lib/gnupg/wks chown webkey:webkey /var/lib/gnupg/wks chmod 2750 /var/lib/gnupg/wks
Then under your webkey account create directories for all your domains. Here we do it for “example.org”:
to create the required sub-directories with the permission set correctly. In particular the hu directory (“hashed-userid”) to store pending keys must only be writable by the webkey user. Running the above command will also remind you to create a file with the submission address for the domain. Let’s do that:
cd /var/lib/gnupg/wks/example.org echo email@example.com >submission-address
The submission address is the address the client uses to contact the Web Key Service. To make this actually work, that address needs to be redirected to the webkey user; use the alias file of your MTA to do this.
To setup the web server there are at least two ways: If the web server is on the same machine it is possible to use symlinks to publish the working directories. For example:
cd /var/www/example.org/htdocs mkdir -p .well-known/openpgpkey cd .well-known/openpgpkey ln -s /var/lib/gnupg/wks/example.org/hu . ln -s /var/lib/gnupg/wks/example.org/submission-address .
The more flexible way is the use of rsync optionally using an ssh connection to a remote web server. This can be done with a cron job; run crontab -e and add this line (the backslashes below are used to indicate line wrapping here; do not enter them into the crontab but use a single long line):
*/4 * * * * rsync -r -p --chmod=Fa+r --delete \ /var/lib/gnupg/wks/example/hu/ \ webserver:/var/www/all/example.org/.well-known/openpgpkey/hu/
This job syncs every 4 minutes the local copy of the published keys to the server. The submission-address file does not change and thus it is sufficient to copy it once by hand to the server.
Create submission key
The protocol suggests that the key to be published is sent with an encrypted mail to the service. Thus you need to create a key for the submission address:
gpg --batch --passphrase '' --quick-gen-key firstname.lastname@example.org gpg --with-wkd-hash -K email@example.com
The output of the last command looks similar to this:
sec rsa2048 2016-08-30 [SC] C0FCF8642D830C53246211400346653590B3795B uid [ultimate] firstname.lastname@example.org email@example.com ssb rsa2048 2016-08-30 [E]
Take the hash of the string “key-submission”, which is 54f6ry7x1qqtpor16txw5gdmdbbh6a73 and manually publish that key:
gpg -o /var/lib/gnupg/wks/example.org/hu/54f6ry7x1qqtpor16txw5gdmdbbh6a73 \ --export-options export-minimal --export firstname.lastname@example.org
Make sure that the created file is world readable. We will eventually provide a tool to make that step easier.
Install the WKS server tool
The tool gpg-wks-server implements the server part of the web key service protocol. There are several ways to install this tool, what I describe here is a setup which allows easy debugging.
First install procmail and make sure that your MTA (Exim, Postfix, sendmail) can run procmail as delivery agent. In most cases it is sufficient to create the file .procmailrc in the home directory (e.g. /home/webkey/.procmailrc. Here is that file; you need to replace “example.org” by your own domain name:
PATH=$HOME/bin:/usr/bin:/bin:/usr/local/bin LD_LIBRARY_PATH=$HOME/lib MAILDIR=$HOME/Mail LOGFILE=$HOME/Mail/from LOCKFILE=$HOME/Mail/.lockmail VERBOSE=yes :0 * ^FROM_DAEMON from-daemon/ :0 c archive/ :0 w * !^From: email@example.com * !^X-WKS-Loop: wks.example.org |$HOME/bin/gpg-wks-server -v --receive \ --header X-WKS-Loop=wks.example.org \ --from firstname.lastname@example.org --send -o $HOME/send.log :0 e cruft/
What it does: The first 6 lines set environment variables for use by this tool and programs invoked. In particular the setting of PATH= and =LD_LIBRARY_PATH is important so that gpg-wks-server can properly work.
The first rule (rules are started with a colon line) detects mails sent from daemon processes. We don't want them and thus we save them to the Maildir style folder Mail/from-daemon for later inspection. For a production system it would be better to directly send those mails to the bit bucket by replacing the last line of that rule with /dev/null.
The second rule stores a copy of all incoming mails to the folder Mail/archive. This is useful for debugging and to view the flow of mails. The 'c' after the ':0' means continue with the next rule after having processed this rule (i.e. storing to the archive folder). By the way, do not forget the trailing slash at folder names; without a slash a plain mbox style would be written (you can use an mbox too, but Maildir is considered a better way to store mails).
The third rule is the heart of this procmail script (in procmail parlance “recipe”). The two lines starting with an asterisk give two conditions on when this rule shall be skipped: If the mail comes from us or if the mail has our loop detection mail header. The command run on this mail is the wks server in a mode which uses the /usr/lib/sendmail tool for sending responses to the mail. The output of the tool is stored to the file send.log in the home directory; to append to a log file use -o - and redirect to a log file.
The final rule stores all not processed mails to the cruft/ folder. This can as well be replaced by /dev/null/
Finally add an entry to your crontab (run crontab -e) to expire non confirmed publication requests: At the top of your crontab add:
PATH=/home/webkey/bin:/usr/local/bin:/usr/bin:/bin LD_LIBRARY_PATH=/home/webkey/lib 42 3 * * * gpg-wks-server --cron
so that the server tool is run each night at, say, 3:42.
Test your installation
To test the Web Key Service, you can create some test accounts for your domain and run the protocol. For a proper test, do not just use a different account on the server but use client box.
Developers of KMail should already be able to use its brand new builtin support for the Web Key Service.
Thunderbird + Enigmail offers WKS auto-publishing which can be used to debug a new WKS setup.
Integration of the Web Key Service into the other mail clients has not yet been done. Thus you need to run the test manually. In this example we assume that on your own box a sendmail-like tool is installed and you also installed GnuPG 2.1 along with the client part of Web Key Service (gpg-wks-client which may require that you pass --enable-wks-tools to the configure run).
An easy way of testing the system exists for Mutt users: By adding the two lines
application/vnd.gnupg.wks; /usr/local/bin/gpg-wks-client \ -v --read --send; needsterminal; description=WKS message
to /etc/mailcap Mutt will do the decryption job and then call the wks-client for the protocol handling. It can be expected that Mutt users have a /usr/lib/sendmail installed which is required here. Note that --read is used which tells the client that the input mail has already been decrypted.
For all others the protocol can be run by hand. Let’s assume, you have the key
sub cv25519 2016-07-15 [E] C444189BD549468C97992D7D3C79E8F960C69FCE pub ed25519 2016-06-28 [SC] 64944BC035493D929EF2A2B9D19D22B06EE78668 uid [ultimate] email@example.com sub cv25519 2016-06-28 [E] B3746B6927FF8021486561D83452DE414E0B5CCD
which in fact is a real key of our own test environment. To publish that key you send the key to the mail provider:
/usr/local/libexec/gpg-wks-client --create --send \ 64944BC035493D929EF2A2B9D19D22B06EE78668 firstname.lastname@example.org
As already mentioned, --send= invokes =/usr/lib/sendmail and sends out the mail. If that option is not used, the mail is written to stdout (or to the file given with --output) and the user is responsible for feeding this to the mail system. If this all works a single message will be shown:
gpg-wks-client: submitting request to 'email@example.com'
Now, wait until you receive a mail back from your provider. In this example that mail was received and stored in the file new/1472561079.6352_1.foobar. We feed this file to the wks-client:
/usr/local/libexec/gpg-wks-client --receive --send \ new/1472561079.6352_1.foobar
which may respond like this:
gpg-wks-client: gpg: encrypted with 256-bit ECDH key, ID 3452DE414E[...] gpg-wks-client: gpg: "firstname.lastname@example.org" gpg-wks-client: new 'application/vnd.gnupg.wks' message part gpg-wks-client: gpg: automatically retrieved 'email@example.com[...]
and has sent the confirmation mail back to the provider. Over there the confirmation mail is matched to the pending key database and the key is then published.
To check that the key has been published, use this:
gpg -v --auto-key-locate=clear,wkd,nodefault --locate-key firstname.lastname@example.org
you should see:
gpg: pub ed25519/D19D22B06EE78668 2016-06-28 email@example.com gpg: key D19D22B06EE78668: "firstname.lastname@example.org" not changed gpg: Total number processed: 1 gpg: unchanged: 1 gpg: auto-key-locate found fingerprint 64944BC035493D929EF2A2B9D19D22B06EE78668 gpg: automatically retrieved 'email@example.com' via WKD pub ed25519 2016-06-28 [SC] 64944BC035493D929EF2A2B9D19D22B06EE78668 uid [ultimate] firstname.lastname@example.org sub cv25519 2016-06-28 [E] B3746B6927FF8021486561D83452DE414E0B5CCD
Despite that it tells you that the key did not change (well, you asked the provider to publish this key), it also tells that the key was found using the Web Key Directory (WKD).
You may also use this lower level test:
gpg-connect-agent --dirmngr --hex 'wkd_get email@example.com' /bye
which results in a hex listing of the key
The tools are not yet finished and improvements can be expected over the next few GnuPG releases. For example the server should send a final mail back to announce that the key has been published. We are also considering slight changes to the protocol but the general procedure on how to drive the tools is unlikely to change.
We still need to add manual pages to describe the server and client tools. For now --help and the gnupg-devel mailing list are your best friends. For those who want to integrate support for the Web Key Service into a MUA but do not want to fiddle with the server side of things, we are happy to provide mail addresses for testing.
Self-hosted email setups offering WKS
- caesonia - OpenBSD email service.
- Excision Mail - OpenBSD email service using ansible: Has multiple-domain WKS support.