1 Introduction
2 ------------
3
4 MoinMessage provides a library for creating, signing, encrypting, decrypting,
5 and verifying PGP/GPG content in Python along with mechanisms for updating
6 MoinMoin wiki instances with such content in such a way that contributors can
7 be identified from their PGP signatures and such details used to authenticate
8 their contributions. It also permits PGP/GPG content to be stored in dedicated
9 message stores when received, enabling further processing of received content
10 and other means of perusal of such content.
11
12 A MoinMessage as understood by this software consists of content that is first
13 signed and then optionally encrypted, where this latter encryption step is
14 used to limit the audience of a message to its recipient and thus to restrict
15 knowledge of the message's author to the recipient. An extra signing step may
16 be employed to authenticate the sender of the message for the recipient, thus
17 providing a way of propagating encrypted messages between parties who trust
18 each other without any decryption of the content or access to details about
19 the author of the content.
20
21 Configuring GPG for a Wiki
22 --------------------------
23
24 Initialise a homedir for GPG and configure it using filesystem ACL (access
25 control list) properties:
26
27 ./scripts/init_wiki_keyring.sh WIKI WEBUSER
28
29 Here, WIKI should be replaced by the top-level wiki instance directory, and
30 WEBUSER should be the name of the user under which the Web server operates.
31
32 Note that this script may need re-running after the homedir has been changed
33 by gpg operations as gpg likes to remove permissions from various files.
34
35 Configuring GPG: Signing Keys
36 -----------------------------
37
38 For a wiki to be able to receive content, signing keys must be made available
39 within the wiki's GPG homedir so that incoming messages can have their senders
40 verified.
41
42 Consider the need to send content to a wiki yourself. To see the keys
43 available to you in your own environment:
44
45 gpg --list-keys --with-fingerprint
46
47 The full fingerprints are used when defining a user mapping in the wiki, and
48 the --with-fingerprint option is used to show them. Otherwise, only the last
49 eight characters of the fingerprints are shown.
50
51 Export the public key used when signing messages from your own environment:
52
53 gpg --armor --output 1C1AAF83.asc --export 1C1AAF83
54
55 Import the key into the wiki's GPG homedir:
56
57 gpg --homedir WIKI/gnupg --import 1C1AAF83.asc
58
59 Signing keys can also be used in the authoring of messages within a wiki, and
60 this is discussed in "The Username-to-Signing-Key Mapping" section below.
61
62 Configuring GPG: Encryption Keys
63 --------------------------------
64
65 For the wiki to receive and decrypt encrypted data, a key for the wiki must be
66 created:
67
68 gpg --homedir WIKI/gnupg --gen-key
69
70 For the wiki environment to be able to use the key, password access must be
71 disabled. This can be done by either not specifying a password or by removing
72 it later using the --edit-key option:
73
74 gpg --homedir WIKI/gnupg --edit-key 0891463A
75 passwd
76
77 Export the wiki's key for encrypting messages sent to the wiki:
78
79 gpg --homedir WIKI/gnupg --armor --output 0891463A.asc --export 0891463A
80
81 This exported key can now be imported into your own environment:
82
83 gpg --import 0891463A.asc
84
85 This key can also be used to sign relayed messages within the wiki, and this
86 is described in more detail in "The Username-to-Signing-Key Mapping" section
87 below.
88
89 Configuring the Wiki
90 --------------------
91
92 In the wiki configuration, define the following settings:
93
94 moinmessage_gpg_homedir
95 This sets the path to the homedir initialised above.
96
97 moinmessage_gpg_users_page (optional, default is MoinMessageUserDict)
98 This provides a mapping from key fingerprints to Moin usernames.
99
100 moinmessage_gpg_signing_users_page (optional, default is MoinMessageSigningUserDict)
101 This provides a mapping from Moin usernames to key fingerprints.
102
103 moinmessage_gpg_relaying_user (optional)
104 This specifies the username of a special user who will sign relayed
105 messages. Partner wikis will need to record the details of this user in
106 their fingerprint-to-user mapping (see moinmessage_gpg_users_page) to be
107 able to receive messages from this wiki.
108
109 moinmessage_gpg_relays_page (optional, default is MoinMessageRelayDict)
110 Where message relaying is specified for a recipient, the relay name will be
111 looked up in the dictionary provided by this page.
112
113 moinmessage_gpg_recipients_page (optional, default is MoinMessageRecipientsDict)
114 This provides a mapping from recipients to remote URLs and key fingerprints.
115 Each user can define the named page as a subpage of their own home page.
116 If no such personal mapping exists, a common mapping exists relative to the
117 site root.
118
119 moinmessage_reject_messages_without_dates (optional, default is True)
120 This causes messages sent to a wiki using the PostMessage action to be
121 rejected if date information is missing.
122
123 moinmessage_static_files (optional, may refer to the built-in htdocs directory)
124 This explicitly defines the path to static resources used by Moin, enabling
125 such resources to be attached to messages. When set, the path must refer to
126 the htdocs directory (possibly renamed) containing the different theme
127 resource directories, together with the robots.txt and favicon.ico files.
128
129 For signature verification to function, the following needs to be added:
130
131 from MoinMoin.auth.pgp import PGPAuth
132
133 This should import an authentication handler installed when the MoinMessage
134 software is installed as an extension package.
135
136 Within the configuration class itself, the auth setting needs to be updated to
137 include PGPAuth in the list of registered handlers. For example:
138
139 auth = [MoinAuth(), PGPAuth()]
140
141 This would permit the traditional Moin authentication and add signature-based
142 authentication so that messages can be accepted by the wiki.
143
144 Fingerprints and Keys
145 ---------------------
146
147 All fingerprints mentioned in the various configuration pages must exclude
148 space characters - that is, the letters and digits must appear together in a
149 continuous block of text - and refer to keys available in the wiki homedir.
150
151 The Fingerprint-to-Username Mapping
152 -----------------------------------
153
154 The mapping from fingerprints to usernames typically defined by the
155 MoinMessageUserDict page is a WikiDict having the following general format:
156
157 fingerprint:: username
158
159 Each fingerprint corresponds to a key used by a person wanting to send
160 messages to the wiki to sign such messages.
161
162 Each username must correspond to a registered user in the wiki.
163
164 If a wiki is to perform message relaying, receiving messages from partner
165 wikis and sending them on, a user is required for this purpose. You could
166 create such a user as follows:
167
168 moin --config-dir=WIKI account create --name=RelayingUser --email=messagerelay
169
170 (You may need to run this command as the Web server user to be able to change
171 the wiki installation, as well as indicating the full path to the moin program
172 either as the program name or by setting the PATH.)
173
174 After doing this, you could define an entry for the relaying user as follows:
175
176 fingerprint:: RelayingUser
177
178 Here, "fingerprint" should be substituted for a key fingerprint used by a
179 partner wiki to sign messages that it then sends to this wiki. See the next
180 section for more information on signing keys and identities.
181
182 It may very well be the case that more than one partner wiki will be sending
183 messages to this wiki: the signing key fingerprint of each partner wiki can be
184 added to this mapping and specify the same relaying user; there is no
185 restriction on each fingerprint needing to map to a different user.
186
187 The Username-to-Actions Mapping
188 -------------------------------
189
190 Each user may have a set of permitted actions defined for them so that they
191 may perform these actions by sending an incoming message to the wiki. This
192 mapping is typically defined by the MoinMessageUserActionsDict page as a
193 WikiDict having the following general format:
194
195 username:: permitted-action ...
196
197 To add content to a page, an entry of the following form would be used:
198
199 username:: Update:SomePage
200
201 Similarly, to allow an incoming message to replace a page's content, the
202 following would be used:
203
204 username:: Replace:SomePage
205
206 And to be able to add messages to a page's message store, the following would
207 be used:
208
209 username:: Store:SomePage
210
211 Multiple actions can be given in a space-separated list, with shell-like
212 quoting used for names containing spaces (and quote characters). For example:
213
214 username:: Store:"Some user's special page"
215
216 Without an entry in this mapping, messages may not perform content
217 modification or storage actions in the wiki.
218
219 The Username-to-Signing-Key Mapping
220 -----------------------------------
221
222 The mapping from usernames to fingerprints typically defined by the
223 MoinMessageSigningUserDict page is a WikiDict having the following general
224 format:
225
226 username:: fingerprint
227
228 Each fingerprint corresponds to a key available in the wiki's GPG homedir
229 generated for the purpose of signing the specified user's messages. Such a key
230 is not the same as one used by a person to send messages to the wiki since
231 only the public key is available to the wiki when verifying such messages,
232 whereas the signing of messages requires access to a private key. Thus, the
233 signing process employs a special private key known to the wiki for a user.
234
235 To create such a key, the following command can be used:
236
237 gpg --homedir WIKI/gnupg --gen-key
238
239 This is just like creating a key for the wiki itself (see "Configuring GPG for
240 a Wiki" above), but you will label the key appropriately for the user and
241 associate the key with the user in the mapping described above. Remember to
242 remove the passphrase so that the wiki can access the key.
243
244 If a wiki is to perform message relaying, the special relaying user must be
245 defined in this mapping together with an appropriate key fingerprint. You can
246 use the key generated during the wiki's configuration (see "Configuring GPG
247 for a Wiki" above) for this purpose. This fingerprint can then be used by
248 partner wikis in their fingerprint-to-user mapping in order to verify incoming
249 messages and to process them as relayed messages.
250
251 All signing keys must be made available in their public form to partner and
252 recipient wikis so that they are able to verify signed content. This can be
253 done as follows:
254
255 gpg --homedir=WIKI/gnupg --armor --output 3FDDF29E.asc --export 3FDDF29E
256
257 They are imported into partner and recipient wikis as follows:
258
259 gpg --homedir=WIKI/gnupg --import 3FDDF29E.asc
260
261 The Recipients Mapping
262 ----------------------
263
264 The mapping from recipients to remote URLs and fingerprints typically defined
265 by the MoinMessageRecipientsDict page is a WikiDict having the following
266 general format:
267
268 recipient:: type location [ fingerprint ]
269
270 Where the type is "page", the accompanying location must be a page name
271 indicating a page that provides a message store that will accept messages.
272 The affected page resides on the same wiki and is thus a bare page name, not
273 the URL of a page on the same or another wiki.
274
275 Where the type is "url", the accompanying location must be a URL that must
276 itself refer to a resource that can accept MoinMessage content.
277
278 Where the type is "relay", the accompanying location is an identifier that
279 must be defined in the relays mapping (see below) and yield a URL that can
280 accept MoinMessage content.
281
282 Where the type is "none" or omitted completely, the recipient is any user that
283 is allowed to fetch messages from the wiki.
284
285 Where a type of "url", "relay" or "none" has been given (or if the type is
286 omitted), a fingerprint must accompany this information in order to encrypt
287 messages sent to the specified resource.
288
289 Each fingerprint corresponds to a key used by the wiki to encrypt messages and
290 by the remote site (as identified by the URL) to decrypt messages.
291
292 Each wiki user can have their own recipients mapping by making a page, called
293 MoinMessageRecipientsDict unless overridden by the configuration, as a subpage
294 of their own home page.
295
296 The Relays Mapping
297 ------------------
298
299 The mapping from relay identifiers to remote URLs defined by the
300 MoinMessageRelayDict page is a WikiDict having the following general format:
301
302 relay:: url
303
304 The URL must be able to accept MoinMessage content, and it will typically be
305 configured so that the user or entity accepting relayed content on the remote
306 site can store such content for later propagation or retrieval.
307
308 Quick Start: Signing, Encrypting and Sending Messages
309 -----------------------------------------------------
310
311 To send a message signed and encrypted to a resource on localhost:
312
313 python tests/test_send.py 1C1AAF83 0891463A http://localhost/wiki/ShareTest \
314 collection update 'An update to the wiki.' 'Another update.'
315
316 Here, the first identifier is a reference to the signing key (over which you
317 have complete control), and the second identifier is a reference to the
318 encryption key (which is a public key published for the wiki).
319
320 This needs password protection to be removed from the secret key in the Web
321 server environment. It also uses a modified trust model when invoking gpg in
322 order to avoid complaints about the identity of the sender during encryption.
323
324 To sign the encrypted message for forwarding, the above command is modified:
325
326 python tests/test_send.py 1C1AAF83 0891463A --forward 1C1AAF83 \
327 http://localhost/wiki/ShareTest \
328 collection update 'An update to the wiki.' 'Another update.'
329
330 Explicit recipient information can be provided for routing purposes:
331
332 python tests/test_send.py 1C1AAF83 0891463A --to PaulBoddie \
333 --forward 1C1AAF83 \
334 http://localhost/wiki/ShareTest \
335 collection update 'An update to the wiki.' 'Another update.'
336
337 Below, the mechanisms employed are illustrated through the use of the other
338 test programs.
339
340 Signing
341 -------
342
343 Prepare a message signed with a "detached signature" (note that this does not
344 seem to be what gpg calls a detached signature with the --detach-sig option):
345
346 python tests/test_message.py collection update 'An update to the wiki.' \
347 'Another update.' \
348 | python tests/test_sign.py 1C1AAF83
349
350 The complicated recipe based on the individual operations is as follows:
351
352 python tests/test_message.py collection update 'An update to the wiki.' \
353 'Another update.' \
354 > test.txt \
355 && cat test.txt \
356 | gpg --armor -u 1C1AAF83 --detach-sig \
357 | python tests/test_sign_wrap.py test.txt
358
359 Encryption
360 ----------
361
362 Prepare a message with an encrypted payload using the above key:
363
364 python tests/test_message.py collection update 'An update to the wiki.' \
365 'Another update.' \
366 | python tests/test_encrypt.py 0891463A
367
368 The complicated recipe based on the individual operations is as follows:
369
370 python tests/test_message.py collection update 'An update to the wiki.' \
371 'Another update.' \
372 > test.txt \
373 && cat test.txt \
374 | gpg --armor -r 0891463A --encrypt --trust-model always \
375 | python tests/test_encrypt_wrap.py
376
377 Note that "--trust-model always" is used only to avoid prompting issues.
378
379 Signing and Encrypting
380 ----------------------
381
382 Sign and encrypt a message:
383
384 python tests/test_message.py collection update 'An update to the wiki.' \
385 'Another update.' \
386 | python tests/test_sign.py 1C1AAF83 \
387 | python tests/test_encrypt.py 0891463A
388
389 The complicated recipe based on the individual operations is as follows:
390
391 python tests/test_message.py collection update 'An update to the wiki.' \
392 'Another update.' \
393 > test.txt \
394 && cat test.txt \
395 | gpg --armor -u 1C1AAF83 --detach-sig \
396 | python tests/test_sign_wrap.py test.txt \
397 | gpg --armor -r 0891463A --encrypt --trust-model always \
398 | python tests/test_encrypt_wrap.py
399
400 Signing and Encrypting then Signing
401 -----------------------------------
402
403 Where a message is to be forwarded and not decrypted, it will be signed by the
404 author, encrypted, but then signed by the forwarder (perhaps initially the
405 author):
406
407 python tests/test_message.py collection update 'An update to the wiki.' \
408 'Another update.' \
409 | python tests/test_sign.py 1C1AAF83 \
410 | python tests/test_encrypt.py 0891463A \
411 | python tests/test_sign.py 1C1AAF83
412
413 The complicated recipe based on the individual operations is as follows:
414
415 python tests/test_message.py collection update 'An update to the wiki.' \
416 'Another update.' \
417 > test.txt \
418 && cat test.txt \
419 | gpg --armor -u 1C1AAF83 --detach-sig \
420 | python tests/test_sign_wrap.py test.txt \
421 | gpg --armor -r 0891463A --encrypt --trust-model always \
422 | python tests/test_encrypt_wrap.py \
423 > test2.txt \
424 && cat test2.txt \
425 | gpg --armor -u 1C1AAF83 --detach-sig \
426 | python tests/test_sign_wrap.py test2.txt
427
428 Posting a Message
429 -----------------
430
431 To post a signed and/or encrypted message, output from the above activities
432 can be piped into the following command:
433
434 python tests/test_post.py http://localhost/wiki/ShareTest
435
436 Here, the resource "/wiki/ShareTest" on localhost is presented with the
437 message.
438
439 Fetching Messages
440 -----------------
441
442 To fetch messages from a message store associated with a page, the following
443 command can be used:
444
445 python tests/test_fetch.py 1C1AAF83 0891463A http://localhost/wiki/ShareTest \
446 RETR
447
448 This should retrieve all messages from the store associated with the
449 "/wiki/ShareTest" resource on localhost.
450
451 Exporting and Sending Keys
452 --------------------------
453
454 To export a public key, the following command can be used:
455
456 python tests/text_export.py 1C1AAF83
457
458 This will output a public key block in a MIME message part suitable for
459 incorporation into a larger message or signing. Signing a message containing
460 such a key can be done as follows:
461
462 python tests/text_export.py 1C1AAF83 \
463 | python tests/test_sign.py 1C1AAF83
464
465 Obviously, this does not provide any additional reassurance about the nature
466 of the exported key other than the originator was able to sign it with the
467 same keypair information.
468
469 The Message Format
470 ------------------
471
472 Messages are MIME-encoded and consist of one or more update fragments. Where
473 the "Update-Type" header is present and set to a value of "collection", a
474 multipart message describes as many updates as there are parts. Otherwise,
475 only a single update is described by the message.
476
477 For each update, the "Update-Action" header indicates the action to be taken
478 with the update content. Where it is absent, the content is inserted into the
479 wiki page specified in the request; where it is present and set to "replace",
480 the content replaces all content on the wiki page; where it is set to "store",
481 the content is stored in a message store associated with the wiki page.
482
483 Each update may describe multiple representations of some content by employing
484 a multipart/alternative section containing parts for each of the
485 representations. Alternatively, a single message part may describe a single
486 representation.
487
488 The Message Fetching Request and Response Formats
489 -------------------------------------------------
490
491 Requests made to fetch or manipulate messages via the FetchMessages action or
492 equivalent service should have the text/x-moinmessage-fetch content type and
493 contain a newline separated sequence of commands resembling those described in
494 the POP3 specification (RFC 1939). However, the actual commands supported are
495 as follows:
496
497 STAT return the number of accessible messages
498
499 RETR [ <number to retrieve> ] retrieve the given number of messages
500 (starting from the first message in the store)
501 or all messages if the number is omitted
502
503 DELE [ <number to delete> ] delete the given number of messages (starting
504 from the first message in the store) or all
505 messages if the number is omitted
506
507 Additional commands may be implemented in future. Note that the transactional
508 commands in POP3 are not supported since the protocol is not intended to be
509 used interactively and there is no notion of a session that is preserved over
510 many requests.
511
512 Requests should be signed and encrypted in order to preserve the privacy of
513 the requester and the nature of their request.
514
515 Responses to such requests should have the text/x-moinmessage-fetch-response
516 content type and contain a complete message in the response body that should
517 be the result of signing and encrypting a response message. (The inclusion of
518 an entire message in the body is intended to work around HTTP limitations,
519 even though HTTP should really be - or have been - MIME compatible.)
520
521 The response message (before signing and encryption) is a multipart/mixed
522 message constructed similarly to collections of message updates. Each part of
523 this multipart message contains either a command result or a retrieved
524 message.
525
526 Command results should have the text/x-moinmessage-fetch-result content type
527 providing the following headers:
528
529 Request-Type the command that was provided
530 Request-Status the status of the command (OK or ERR)
531
532 Any specific result value may be provided as the payload of the command result
533 message part.
534
535 Retrieved messages should have the multipart/mixed content type and provide a
536 retrieved message in each part, where such messages may themselves be signed
537 or encrypted message representations.
538
539 HTTP Methods
540 ------------
541
542 Since MoinMoin seems to reserve POST methods for request/entity bodies that
543 contain HTML form data, it is necessary to use alternative methods to post
544 messages to a site served by MoinMoin and to fetch messages from such a site.
545 Consequently, MoinMessage uses PUT to post and fetch messages. Unfortunately,
546 MoinMoin 1.9 prevents the use of GET with request/entity bodies, and so the
547 natural usage of GET to fetch messages cannot be employed.
548
549 Contact, Copyright and Licence Information
550 ------------------------------------------
551
552 See the following Web page for more information about this work:
553
554 http://moinmo.in/ActionMarket/MoinMessage
555
556 The author can be contacted at the following e-mail address:
557
558 paul@boddie.org.uk
559
560 Copyright and licence information can be found in the docs directory - see
561 docs/COPYING.txt and docs/LICENCE.txt for more information.
562
563 Dependencies
564 ------------
565
566 MoinMessage has the following basic dependencies:
567
568 Packages Release Information
569 -------- -------------------
570
571 MoinSupport Tested with 0.5
572 Source: http://hgweb.boddie.org.uk/MoinSupport