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.
9
10 Configuring GPG for a Wiki
11 --------------------------
12
13 Initialise a homedir for GPG and configure it using filesystem ACL (access
14 control list) properties:
15
16 ./scripts/init_wiki_keyring.sh WIKI WEBUSER
17
18 Here, WIKI should be replaced by the top-level wiki instance directory, and
19 WEBUSER should be the name of the user under which the Web server operates.
20
21 Note that this script may need re-running after the homedir has been changed
22 by gpg operations as gpg likes to remove permissions from various files.
23
24 To be in any way useful, signing keys must be made available within this
25 homedir so that incoming messages can have their senders verified.
26
27 To see the keys available to you in your own environment:
28
29 gpg --list-keys --with-fingerprint
30
31 The full fingerprints are used when defining a user mapping in the wiki, and
32 the --with-fingerprint option is used to show them. Otherwise, only the last
33 eight characters of the fingerprints are shown.
34
35 Export the public key used when signing messages from your own environment:
36
37 gpg --armor --output 1C1AAF83.asc --export 1C1AAF83
38
39 Import the key into the wiki's GPG homedir:
40
41 gpg --homedir wiki/gnupg --import 1C1AAF83.asc
42
43 For the wiki to receive encrypted data, a key for the wiki must be created:
44
45 gpg --homedir wiki/gnupg --gen-key
46
47 For the wiki environment to be able to use the key, password access must be
48 disabled. This can be done by either not specifying a password or by removing
49 it later using the --edit-key option:
50
51 gpg --homedir wiki/gnupg --edit-key 0891463A
52 passwd
53
54 Export the wiki's key for encrypting messages sent to the wiki:
55
56 gpg --homedir wiki/gnupg --armor --output 0891463A.asc --export 0891463A
57
58 This exported key can now be imported into your own environment:
59
60 gpg --import 0891463A.asc
61
62 Configuring the Wiki
63 --------------------
64
65 In the wiki configuration, define the following settings:
66
67 moinmessage_gpg_homedir
68 This sets the path to the homedir initialised above.
69
70 moinmessage_gpg_users_page (optional, default is MoinMessageUserDict)
71 This provides a mapping from key fingerprints to Moin usernames.
72
73 moinmessage_gpg_signing_users_page (optional, default is MoinMessageSigningUserDict)
74 This provides a mapping from Moin usernames to key fingerprints.
75
76 moinmessage_gpg_recipients_page (optional, default is MoinMessageRecipientsDict)
77 This provides a mapping from recipients to remote URLs and key fingerprints.
78 Each user can define the named page as a subpage of their own home page.
79 If no such personal mapping exists, a common mapping exists relative to the
80 site root.
81
82 moinmessage_reject_messages_without_dates (optional, default is True)
83 This causes messages sent to a wiki using the PostMessage action to be
84 rejected if date information is missing.
85
86 moinmessage_static_files (optional, may refer to the built-in htdocs directory)
87 This explicitly defines the path to static resources used by Moin, enabling
88 such resources to be attached to messages. When set, the path must refer to
89 the htdocs directory (possibly renamed) containing the different theme
90 resource directories, together with the robots.txt and favicon.ico files.)
91
92 For signature verification to function, the following needs to be added:
93
94 from MoinMoin.auth.pgp import PGPAuth
95
96 This should import an authentication handler installed when the MoinMessage
97 software is installed as an extension package.
98
99 Within the configuration class itself, the auth setting needs to be updated to
100 include PGPAuth in the list of registered handlers. For example:
101
102 auth = [MoinAuth(), PGPAuth()]
103
104 This would permit the traditional Moin authentication and add signature-based
105 authentication so that messages can be accepted by the wiki.
106
107 Fingerprints and Keys
108 ---------------------
109
110 All fingerprints mentioned in the various configuration pages must exclude
111 space characters - that is, the letters and digits must appear together in a
112 continuous block of text - and refer to keys available in the wiki homedir.
113
114 The Fingerprint-to-Username Mapping
115 -----------------------------------
116
117 The mapping from fingerprints to usernames typically defined by the
118 MoinMessageUserDict page is a WikiDict having the following general format:
119
120 fingerprint:: username
121
122 Each fingerprint corresponds to a key used by a person wanting to send
123 messages to the wiki to sign such messages.
124
125 Each username must correspond to a registered user in the wiki.
126
127 The Username-to-Signing Key Mapping
128 -----------------------------------
129
130 The mapping from usernames to fingerprints typically defined by the
131 MoinMessageSigningUserDict page is a WikiDict having the following general
132 format:
133
134 username:: fingerprint
135
136 Each fingerprint corresponds to a key available in the wiki's GPG homedir
137 generated for the purpose of signing the specified user's messages. Such a key
138 is not the same as one used by a person to send messages to the wiki since
139 only the public key is available to the wiki when verifying such messages,
140 whereas the signing of messages requires access to a private key. Thus, the
141 signing process employs a special private key known to the wiki for a user.
142
143 The Recipients Mapping
144 ----------------------
145
146 The mapping from recipients to remote URLs and fingerprints typically defined
147 by the MoinMessageRecipientsDict page is a WikiDict having the following
148 general format:
149
150 recipient:: type location [ fingerprint ]
151
152 Where the type is "page", the accompanying location must be a page name
153 indicating a page that provides a message store that will accept messages.
154
155 Where the type is "url", the accompanying location must be a URL that must
156 itself refer to a resource that can accept MoinMessage content.
157
158 Where a type of "url" has been given, a fingerprint must accompany this
159 information in order to encrypt messages sent to the specified resource.
160
161 Each fingerprint corresponds to a key used by the wiki to encrypt messages and
162 by the remote site (as identified by the URL) to decrypt messages.
163
164 Each wiki user can have their own recipients mapping by making a page, called
165 MoinMessageRecipientsDict unless overridden by the configuration, as a subpage
166 of their own home page.
167
168 Quick Start: Signing, Encrypting and Sending Messages
169 -----------------------------------------------------
170
171 To send a message signed and encrypted to a resource on localhost:
172
173 python tests/test_send.py 1C1AAF83 0891463A http://localhost/wiki/ShareTest \
174 collection update 'An update to the wiki.' 'Another update.'
175
176 Here, the first identifier is a reference to the signing key (over which you
177 have complete control), and the second identifier is a reference to the
178 encryption key (which is a public key published for the wiki).
179
180 This needs password protection to be removed from the secret key in the Web
181 server environment. It also uses a modified trust model when invoking gpg in
182 order to avoid complaints about the identity of the sender during encryption.
183
184 To sign the encrypted message for forwarding, the above command is modified:
185
186 python tests/test_send.py 1C1AAF83 0891463A --forward 1C1AAF83 \
187 http://localhost/wiki/ShareTest \
188 collection update 'An update to the wiki.' 'Another update.'
189
190 Below, the mechanisms employed are illustrated through the use of the other
191 test programs.
192
193 Signing
194 -------
195
196 Prepare a message signed with a "detached signature" (note that this does not
197 seem to be what gpg calls a detached signature with the --detach-sig option):
198
199 python tests/test_message.py collection update 'An update to the wiki.' \
200 'Another update.' \
201 | python tests/test_sign.py 1C1AAF83
202
203 The complicated recipe based on the individual operations is as follows:
204
205 python tests/test_message.py collection update 'An update to the wiki.' \
206 'Another update.' \
207 > test.txt \
208 && cat test.txt \
209 | gpg --armor -u 1C1AAF83 --detach-sig \
210 | python tests/test_sign_wrap.py test.txt
211
212 Encryption
213 ----------
214
215 Prepare a message with an encrypted payload using the above key:
216
217 python tests/test_message.py collection update 'An update to the wiki.' \
218 'Another update.' \
219 | python tests/test_encrypt.py 0891463A
220
221 The complicated recipe based on the individual operations is as follows:
222
223 python tests/test_message.py collection update 'An update to the wiki.' \
224 'Another update.' \
225 > test.txt \
226 && cat test.txt \
227 | gpg --armor -r 0891463A --encrypt --trust-model always \
228 | python tests/test_encrypt_wrap.py
229
230 Note that "--trust-model always" is used only to avoid prompting issues.
231
232 Signing and Encrypting
233 ----------------------
234
235 Sign and encrypt a message:
236
237 python tests/test_message.py collection update 'An update to the wiki.' \
238 'Another update.' \
239 | python tests/test_sign.py 1C1AAF83 \
240 | python tests/test_encrypt.py 0891463A
241
242 The complicated recipe based on the individual operations is as follows:
243
244 python tests/test_message.py collection update 'An update to the wiki.' \
245 'Another update.' \
246 > test.txt \
247 && cat test.txt \
248 | gpg --armor -u 1C1AAF83 --detach-sig \
249 | python tests/test_sign_wrap.py test.txt \
250 | gpg --armor -r 0891463A --encrypt --trust-model always \
251 | python tests/test_encrypt_wrap.py
252
253 Signing and Encrypting then Signing
254 -----------------------------------
255
256 Where a message is to be forwarded and not decrypted, it will be signed by the
257 author, encrypted, but then signed by the forwarder (perhaps initially the
258 author):
259
260 python tests/test_message.py collection update 'An update to the wiki.' \
261 'Another update.' \
262 | python tests/test_sign.py 1C1AAF83 \
263 | python tests/test_encrypt.py 0891463A \
264 | python tests/test_sign.py 1C1AAF83
265
266 The complicated recipe based on the individual operations is as follows:
267
268 python tests/test_message.py collection update 'An update to the wiki.' \
269 'Another update.' \
270 > test.txt \
271 && cat test.txt \
272 | gpg --armor -u 1C1AAF83 --detach-sig \
273 | python tests/test_sign_wrap.py test.txt \
274 | gpg --armor -r 0891463A --encrypt --trust-model always \
275 | python tests/test_encrypt_wrap.py \
276 > test2.txt \
277 && cat test2.txt \
278 | gpg --armor -u 1C1AAF83 --detach-sig \
279 | python tests/test_sign_wrap.py test2.txt
280
281 Posting a Message
282 -----------------
283
284 To post a signed and/or encrypted message, output from the above activities
285 can be piped into the following command:
286
287 python tests/test_post.py http://localhost/wiki/ShareTest
288
289 Here, the resource "/wiki/ShareTest" on localhost is presented with the
290 message.
291
292 Fetching Messages
293 -----------------
294
295 To fetch messages from a message store associated with a page, the following
296 command can be used:
297
298 python tests/test_fetch.py 1C1AAF83 0891463A http://localhost/wiki/ShareTest \
299 RETR
300
301 This should retrieve all messages from the store associated with the
302 "/wiki/ShareTest" resource on localhost.
303
304 The Message Format
305 ------------------
306
307 Messages are MIME-encoded and consist of one or more update fragments. Where
308 the "Update-Type" header is present and set to a value of "collection", a
309 multipart message describes as many updates as there are parts. Otherwise,
310 only a single update is described by the message.
311
312 For each update, the "Update-Action" header indicates the action to be taken
313 with the update content. Where it is absent, the content is inserted into the
314 wiki page specified in the request; where it is present and set to "replace",
315 the content replaces all content on the wiki page; where it is set to "store",
316 the content is stored in a message store associated with the wiki page.
317
318 Each update may describe multiple representations of some content by employing
319 a multipart/alternative section containing parts for each of the
320 representations. Alternatively, a single message part may describe a single
321 representation.
322
323 HTTP Methods
324 ------------
325
326 Since MoinMoin seems to reserve POST methods for request/entity bodies that
327 contain HTML form data, it is necessary to use alternative methods to post
328 messages to a site served by MoinMoin and to fetch messages from such a site.
329 Consequently, MoinMessage uses PUT to post and fetch messages. Unfortunately,
330 MoinMoin 1.9 prevents the use of GET with request/entity bodies, and so the
331 natural usage of GET to fetch messages cannot be employed.
332
333 Contact, Copyright and Licence Information
334 ------------------------------------------
335
336 See the following Web page for more information about this work:
337
338 http://moinmo.in/ActionMarket/MoinMessage
339
340 The author can be contacted at the following e-mail address:
341
342 paul@boddie.org.uk
343
344 Copyright and licence information can be found in the docs directory - see
345 docs/COPYING.txt and docs/LICENCE.txt for more information.
346
347 Dependencies
348 ------------
349
350 MoinMessage has the following basic dependencies:
351
352 Packages Release Information
353 -------- -------------------
354
355 MoinSupport Tested with 0.4
356 Source: http://hgweb.boddie.org.uk/MoinSupport