blog: Move a blog to drafts, publish gpgme/python blog
[gnupg-doc.git] / misc / blog.gnupg.org / 20160830-web-key-service.org
1 # Some notes on our new Web Key Service
2 #+STARTUP: showall
3 #+AUTHOR: Werner
4 #+DATE: August 30, 2016
5
6 ** Key Discovery Made Simple
7
8    A major hassle with sending encrypted mails is to find the key
9    matching the recipients mail address.  A naïve method is to look
10    for the key at a keyserver.  In most cases this works surprisingly
11    well.  However, there is no guarantee that this key really matches
12    the mail address --- anyone can create a key and put an arbitrary
13    mail address there.  It is quite disturbing to receive a mail which
14    you can't decrypt because it was encrypted to another key.
15
16    GnuPG 2.1 provides an simple but efficient solution to store a key
17    under a well known URL and lookup it up via https.  For practical
18    deployment of this method (as well as for OpenPGP DANE) a method to
19    publishing a key is required.  The new [[https://tools.ietf.org/id/draft-koch-openpgp-webkey-service-01.html][Web Key Service]] protocol
20    such a protocol and GnuPG 2.1.15 comes with the tools to implement
21    this.  Aside from GnuPG the other pre-requisites are:
22
23    - A mail server for your domain with the full authority on the user
24      mail addresses for this domain.
25
26    - A Unix system where you have an account to receive mails to a
27      dedicated mail address and to send mails via the sendmail tool.
28      An account on the mail server will be the best choice.
29
30    - A web server for the same domain to deliver static pages over TLS.
31      Re-direction to a different server is possible
32
33    - The ability to install the latest GnuPG version from source.
34
35    Here is a first step by step description on how to install and test
36    that service.
37
38 *** Install GnuPG 2.1
39
40     Your system will already have a gpg version but we want the very
41     latest one and we want to install it locally.
42
43     First you should create a new account on the machine.  Let's use
44     =webkey=.  Nothing special is required; thus a simple
45
46     : # adduser --disabled-password webkey
47
48     as root will do.  Add an =.ssh/authorized_keys= file to make it
49     easy to access.  Now download GnuPG (as of this writing version
50     2.1.15):
51
52     : $ cd ~webkey
53     : $ wget ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-2.1.15.tar.bz2
54     : $ wget ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-2.1.15.tar.bz2.sig
55     : $ wget -O - https://gnupg.org/signature_key.html | gpg --import
56     : $ gpg --verify gnupg-2.1.15.tar.bz2.sig gnupg-2.1.15.tar.bz2
57
58     The last line uses the standard gpg to check that the integrity of
59     the tarball.  Then please verify that the displayed fingerprints
60     match the desired ones; see
61     https://gnupg.org/download/integrity_check.html for more on this.
62
63     The easiest way to install the latest GnuPG version is to use
64     Speedo, which downloads, verifies and builds all dependent
65     packages.  To do this first unpack the tarball:
66
67     : $ tar xjf gnupg-2.1.15.tar.bz2
68
69     On non GNU system you may need to use this instead:
70
71     : $ zcat gnupg-2.1.15.tar.bz2 | tar xf -
72
73     Then run:
74
75     : $ make -f gnupg-2.1.15/build-aux/speedo.mk INSTALL_PREFIX=. \
76     : >   speedo_pkg_gnupg_configure='--enable-gpg2-is-gpg        \
77     : >      --disable-g13 --enable-wks-tools' native
78
79     If you run into errors you are probably missing some development
80     tools; install them and try again.  If all succeeds you will
81     notice a bunch of new directories below webkey's home directory:
82
83     : PLAY  bin  include  lib  libexec  sbin  share  swdb.lst  swdb.lst.sig
84
85     Optionally you may delete what is not anymore required:
86
87     : $ rm -rf PLAY include lib swdb.*
88
89     To make use of your new GnuPG installation you need to run this
90     first (you should add it to webkey's .profile or .bashrc):
91
92     : PATH="$HOME/bin:$PATH"
93     : LD_LIBRARY_PATH="$(pwd)/lib"
94     : export LD_LIBRARY_PATH
95
96 *** Prepare the mail and web servers
97
98     The Web Key Service requires a working directory to store keys
99     pending for publication.  As root create a working directory:
100
101     : # mkdir /var/lib/gnupg/wks
102     : # chown webkey:webkey /var/lib/gnupg/wks
103     : # chmod 2750 /var/lib/gnupg/wks
104
105     Then under your webkey account create directories for all your
106     domains.  Here we do it for “example.org”:
107
108     : $ mkdir /var/lib/gnupg/wks/example.org
109
110     Then run
111
112     : $ gpg-wks-server --list-domains
113
114     to create the required sub-directories with the permission set
115     correctly.  In particular the =hu= directory (“hashed-userid”) to
116     store pending keys must only be accessible by the webkey user.
117     Running the above command will also remind you to create a file
118     with the submission address for the domain.  Let’s do that:
119
120     : $ cd /var/lib/gnupg/wks/example.org
121     : $ echo key-submission@example.org >submission-address
122
123     The submission address is the address the client uses to contact
124     the Web Key Service.  To make this actually work, that address
125     needs to be redirected to the webkey user; use the alias file of
126     your MTA to do this.
127
128     To setup the web server there are at least two ways: If the web
129     server is on the same machine it is possible to use symlinks to
130     publish the working directories.  For example:
131
132     : $ cd /var/www/example.org/htdocs
133     : $ mkdir -p .well-known/openpgpkey
134     : $ cd .well-known/openpgpkey
135     : $ ln -s /var/lib/gnupg/wks/example.org/hu .
136     : $ ln -s /var/lib/gnupg/wks/example.org/submission-address .
137
138     The more flexible way is the use of rsync optionally using an ssh
139     connection to a remote web server.  This can be done with a cron
140     job; run =crontab -e= and add this line (the backslashes below are
141     used to indicate line wrapping here; do not enter them into the
142     crontab but use a single long line):
143
144     : */4 * * * * rsync -r -p --chmod=Fa+r --delete \
145     :     /var/lib/gnupg/wks/example/hu/            \
146     :     webserver:/var/www/all/example.org/.well-known/openpgpkey/hu/
147
148     This job syncs every 4 minutes the local copy of the published
149     keys to the server.  The submission-address file does not change
150     and thus it is sufficient to copy it once by hand to the server.
151
152 *** Create submission key
153
154     The protocol suggests that the key to be published is sent with an
155     encrypted mail to the service.  Thus you need to create a key for
156     the submission address:
157
158     : $ gpg --batch --passphrase '' --quick-gen-key key-submission@example.org
159     : $ gpg --with-wkd-hash -K key-submission@example.org
160
161     The output of the last command looks similar to this:
162
163     #+begin_example
164     sec   rsa2048 2016-08-30 [SC]
165           C0FCF8642D830C53246211400346653590B3795B
166     uid           [ultimate] key-submission@example.org
167                   bxzcxpxk8h87z1k7bzk86xn5aj47intu@example.org
168     ssb   rsa2048 2016-08-30 [E]
169     #+end_example
170
171     Take the hash of the string “key-submission”, which is
172     =bxzcxpxk8h87z1k7bzk86xn5aj47intu= and manually publish that key:
173
174     : $ gpg --export-options export-minimal --export key-submission@example.org
175     : >  -o /var/lib/gnupg/wks/example.org/hu/bxzcxpxk8h87z1k7bzk86xn5aj47intu
176
177     Make sure that the created file is world readable.  We will
178     eventually provide a tool to make that step easier.
179
180 *** Install the WKS server tool
181
182     The tool gpg-wks-server implements the server part of the web key
183     service protocol.  There are several ways to install this tool,
184     what I describe here is a setup which allows easy debugging.
185
186     First install procmail and make sure that your MTA (Exim, Postfix,
187     sendmail) can run procmail as delivery agent.  In most cases it is
188     sufficient to create the file =.procmailrc= in the home directory
189     (e.g. =/home/webkey/.procmailrc=).  Here is that file; you need to
190     replace “example.org” by your own domain name:
191
192     #+begin_example
193     PATH=$HOME/bin:/usr/bin:/bin:/usr/local/bin
194     LD_LIBRARY_PATH=$HOME/lib
195
196     MAILDIR=$HOME/Mail
197     LOGFILE=$HOME/Mail/from
198     LOCKFILE=$HOME/Mail/.lockmail
199     VERBOSE=yes
200
201     :0
202     * ^FROM_DAEMON
203     from-daemon/
204
205     :0 c
206     archive/
207
208     :0
209     * !^From: webkey@example.org
210     * !^X-WKS-Loop: webkey.example.org
211     |$HOME/bin/gpg-wks-server -v --receive \
212          --header X-WKS-Loop=webkey.example.org \
213          --from webkey@example.org --send -o $HOME/send.log
214
215     :0
216     cruft/
217     #+end_example
218
219     What it does: The first 6 lines set environment variables for
220     use by this tool and programs invoked.  In particular the setting
221     of =PATH= and =LD_LIBRARY_PATH= is important so that
222     gpg-wks-server can properly work.
223
224     The first rule (rules are started with a colon line) detects mails
225     sent from daemon processes.  We don't want them and thus we save
226     them to the Maildir style folder =Mail/from-daemon= for later
227     inspection.  For a production system it would be better to
228     directly send those mails to the bit bucket by replacing the last
229     line of that rule with =/dev/null=.
230
231     The second rule stores a copy of all incoming mails to the folder
232     =Mail/archive=.  This is useful for debugging and to view the flow
233     of mails.  The 'c' after the ':0' means continue with the next
234     rule after having processed this rule (i.e. storing to the archive
235     folder).  By the way, do not forget the trailing slash at folder
236     names; without a slash a plain mbox style would be written (you can
237     use an mbox too, but Maildir is considered a better way to store
238     mails).
239
240     The third rule is the heart of this procmail script (in procmail
241     parlance “recipe”).  The two lines starting with an asterisk give
242     two conditions on when this rule shall be skipped: If the mail
243     comes from us or if the mail has our loop detection mail header.
244     The command run on this mail is the wks server in a mode which
245     uses the /usr/lib/sendmail tool for sending responses to the
246     mail.  The output of the tool is stored to the file =send.log=
247     in the home directory; to append to a log file use =-o -= and
248     redirect to a log file.
249
250     The final rule stores all not processed mails to the =cruft/=
251     folder.  This can as well be replaced by =/dev/null=/
252
253     Finally add an entry to your crontab (run =crontab -e=) to expire non
254     confirmed publication requests:  At the top of your crontab add:
255
256     : PATH=/home/webkey/bin:/usr/local/bin:/usr/bin:/bin
257     : LD_LIBRARY_PATH=/home/webkey/lib
258     :
259     : 42 3 * * * gpg-wks-server --cron
260
261     so that the server tool is run each night at, say, 3:42.
262
263
264 *** Test your installation
265
266     To test the Web Key Service, you can create some test accounts for
267     your domain and run the protocol.  For a proper test, do not just
268     use a different account on the server but use client box.
269
270     Developers of [[https://userbase.kde.org/KMail][KMail]] should already be able to use its brand new
271     builtin support for the Web Key Service.
272
273     Integration of the Web Key Service into the other mail clients has
274     not yet been done.  Thus you need to run the test manually.  In
275     this example we assume that on your own box a sendmail-like tool is
276     installed and you also installed GnuPG 2.1 along with the client
277     part of Web Key Service (gpg-wks-client which may require that you
278     pass --enable-wks-tools to the configure run).
279
280     An easy way of testing the system exists for [[http://www.mutt.org][Mutt]] users: By adding
281     the two lines
282
283     : application/vnd.gnupg.wks; /usr/local/bin/gpg-wks-client \
284     :    -v --read --send; needsterminal; description=WKS message
285
286     to =/etc/mailcap= Mutt will do the decryption job and then call
287     the wks-client for the protocol handling.  It can be expected that
288     Mutt users have a /usr/lib/sendmail installed which is required
289     here.  Note that =--read= is used which tells the client that the
290     input mail has already been decrypted.
291
292     For all others the protocol can be run by hand.  Let’s assume, you
293     have the key
294
295 #+begin_example
296 sub   cv25519 2016-07-15 [E]
297       C444189BD549468C97992D7D3C79E8F960C69FCE
298 pub   ed25519 2016-06-28 [SC]
299       64944BC035493D929EF2A2B9D19D22B06EE78668
300 uid           [ultimate] dewey@test.gnupg.org
301 sub   cv25519 2016-06-28 [E]
302       B3746B6927FF8021486561D83452DE414E0B5CCD
303 #+end_example
304
305     which in fact is a real key of our own test environment.  To
306     publish that key you send the key to the mail provider:
307
308     : $ /usr/local/libexec/gpg-wks-client --create --send \
309     : >  64944BC035493D929EF2A2B9D19D22B06EE78668 dewey@test.gnupg.org
310
311
312     As already mentioned, =--send= invokes =/usr/lib/sendmail= and sends
313     out the mail.  If that option is not used, the mail is
314     written to stdout (or to the file given with =--output=) and the
315     user is responsible for feeding this to the mail system.  If this all
316     works a single message will be shown:
317
318 #+begin_example
319 gpg-wks-client: submitting request to 'key-submission@test.gnupg.org'
320 #+end_example
321
322     Now, wait until you receive a mail back from your provider.  In
323     this example that mail was received and stored in the file
324     =new/1472561079.6352_1.foobar=.  We feed this file to the
325     wks-client:
326
327     : $ /usr/local/libexec/gpg-wks-client --receive --send \
328     : >       < new/1472561079.6352_1.foobar
329
330     which may respond like this:
331
332 #+begin_example
333 gpg-wks-client: gpg: encrypted with 256-bit ECDH key, ID 3452DE414E[...]
334 gpg-wks-client: gpg:       "dewey@test.gnupg.org"
335 gpg-wks-client: new 'application/vnd.gnupg.wks' message part
336 gpg-wks-client: gpg: automatically retrieved 'key-submission@test.g[...]
337 #+end_example
338
339    and has sent the confirmation mail back to the provider.  Over
340    there the confirmation mail is matched to the pending key database
341    and the key is then published.
342
343    To check that the key has been published, use this:
344
345  : $ gpg -v --auto-key-locate=clear,wkd,local --locate-key dewey@test.gnupg.org
346
347    you should see:
348
349 #+begin_example
350 gpg: pub  ed25519/D19D22B06EE78668 2016-06-28  dewey@test.gnupg.org
351 gpg: key D19D22B06EE78668: "dewey@test.gnupg.org" not changed
352 gpg: Total number processed: 1
353 gpg:              unchanged: 1
354 gpg: auto-key-locate found fingerprint 64944BC035493D929EF2A2B9D19D22B06EE78668
355 gpg: automatically retrieved 'dewey@test.gnupg.org' via WKD
356 pub   ed25519 2016-06-28 [SC]
357       64944BC035493D929EF2A2B9D19D22B06EE78668
358 uid           [ultimate] dewey@test.gnupg.org
359 sub   cv25519 2016-06-28 [E]
360       B3746B6927FF8021486561D83452DE414E0B5CCD
361 #+end_example
362
363    Despite that it tells you that the key did not change (well, you
364    asked the provider to publish this key), it also tells that the key
365    was found using the Web Key Directory (WKD).
366
367    You may also use this lower level test:
368
369    : $ gpg-connect-agent --dirmngr --hex 'wkd_get dewey@test.gnupg.org' /bye
370
371    which results in a hex listing of the key
372
373 *** Future work
374
375     The tools are not yet finished and improvements can be expected
376     over the next few GnuPG releases.  For example the server should
377     send a final mail back to announce that the key has been
378     published.  We are also considering slight changes to the protocol
379     but the general procedure on how to drive the tools is unlikely to
380     change.
381
382     We still need to add manual pages to describe the server and
383     client tools.  For now =--help= and the [[https://lists.gnupg.org/mailman/listinfo/gnupg-devel][gnupg-devel]] mailing list
384     are your best friends.  For those who want to integrate support
385     for the Web Key Service into a MUA but do not want to fiddle with
386     the server side of things, we are happy to provide mail addresses
387     for testing.