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