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 Export the Wiki's key for encrypting messages sent to the Wiki:
52
53 gpg --homedir wiki/gnupg --armor --output 0891463A.asc --export 0891463A
54
55 This exported key can now be imported into your own environment:
56
57 gpg --import 0891463A.asc
58
59 Configuring the Wiki
60 --------------------
61
62 In the Wiki configuration, define the following settings:
63
64 moinmessage_gpg_homedir
65 This sets the path to the homedir initialised above.
66
67 moinmessage_gpg_users_page (optional, default is MoinMessageUserDict)
68 This provides a mapping from key fingerprints to Moin usernames.
69
70 moinmessage_gpg_signing_users_page (optional, default is MoinMessageSigningUserDict)
71 This provides a mapping from Moin usernames to key fingerprints.
72
73 moinmessage_gpg_recipients_page (optional, default is MoinMessageRecipientsDict)
74 This provides a mapping from recipients to remote URLs and key fingerprints.
75 Each user can define the named page as a subpage of their own home page.
76 If no such personal mapping exists, a common mapping exists relative to the
77 site root.
78
79 moinmessage_reject_messages_without_dates (optional, default is True)
80 This causes messages sent to a Wiki using the PostMessage action to be
81 rejected if date information is missing.
82
83 moinmessage_static_files (optional, may refer to the built-in htdocs directory)
84 This explicitly defines the path to static resources used by Moin, enabling
85 such resources to be attached to messages. When set, the path must refer to
86 the htdocs directory (possibly renamed) containing the different theme
87 resource directories, together with the robots.txt and favicon.ico files.)
88
89 For signature verification to function, the following needs to be added:
90
91 from MoinMoin.auth.pgp import PGPAuth
92
93 This should import an authentication handler installed when the MoinMessage
94 software is installed as an extension package.
95
96 Within the configuration class itself, the auth setting needs to be updated to
97 include PGPAuth in the list of registered handlers. For example:
98
99 auth = [MoinAuth(), PGPAuth()]
100
101 This would permit the traditional Moin authentication and add signature-based
102 authentication so that messages can be accepted by the Wiki.
103
104 Fingerprints and Keys
105 ---------------------
106
107 All fingerprints mentioned in the various configuration pages must exclude
108 space characters - that is, the letters and digits must appear together in a
109 continuous block of text - and refer to keys available in the Wiki homedir.
110
111 The Fingerprint-to-Username Mapping
112 -----------------------------------
113
114 The mapping from fingerprints to usernames typically defined by the
115 MoinMessageUserDict page is a WikiDict having the following general format:
116
117 fingerprint:: username
118
119 Each fingerprint corresponds to a key used by a person wanting to send
120 messages to the Wiki to sign such messages.
121
122 Each username must correspond to a registered user in the Wiki.
123
124 The Username-to-Signing Key Mapping
125 -----------------------------------
126
127 The mapping from usernames to fingerprints typically defined by the
128 MoinMessageSigningUserDict page is a WikiDict having the following general
129 format:
130
131 username:: fingerprint
132
133 Each fingerprint corresponds to a key available in the Wiki's GPG homedir
134 generated for the purpose of signing the specified user's messages. Such a key
135 is not the same as one used by a person to send messages to the Wiki since
136 only the public key used to verify such messages should be known to the Wiki.
137
138 The Recipients Mapping
139 ----------------------
140
141 The mapping from recipients to remote URLs and fingerprints typically defined
142 by the MoinMessageRecipientsDict page is a WikiDict having the following
143 general format:
144
145 recipient:: type location [ fingerprint ]
146
147 Where the type is "page", the accompanying location must be a page name
148 indicating a page that provides a message store that will accept messages.
149
150 Where the type is "url", the accompanying location must be a URL that must
151 itself refer to a resource that can accept MoinMessage content.
152
153 Where a type of "url" has been given, a fingerprint must accompany this
154 information in order to encrypt messages sent to the specified resource.
155
156 Each fingerprint corresponds to a key used by the Wiki to encrypt messages and
157 by the remote site (as identified by the URL) to decrypt messages.
158
159 Quick Start: Signing, Encrypting and Sending Messages
160 -----------------------------------------------------
161
162 To send a message signed and encrypted to a resource on localhost:
163
164 python tests/test_send.py 1C1AAF83 0891463A http://localhost/wiki/ShareTest \
165 collection update 'An update to the Wiki.' 'Another update.'
166
167 Here, the first identifier is a reference to the signing key (over which you
168 have complete control), and the second identifier is a reference to the
169 encryption key (which is a public key published for the Wiki).
170
171 This needs password protection to be removed from the secret key in the Web
172 server environment. It also uses a modified trust model when invoking gpg in
173 order to avoid complaints about the identity of the sender during encryption.
174
175 Below, the mechanisms employed are illustrated through the use of the other
176 test programs.
177
178 Signing
179 -------
180
181 Prepare a message signed with a "detached signature" (note that this does not
182 seem to be what gpg calls a detached signature with the --detach-sig option):
183
184 python tests/test_message.py collection update 'An update to the Wiki.' \
185 'Another update.' \
186 | python tests/test_sign.py 1C1AAF83
187
188 The complicated recipe based on the individual operations is as follows:
189
190 python tests/test_message.py collection update 'An update to the Wiki.' \
191 'Another update.' \
192 > test.txt \
193 && cat test.txt \
194 | gpg --armor -u 1C1AAF83 --detach-sig \
195 | python tests/test_sign_wrap.py test.txt
196
197 Encryption
198 ----------
199
200 Prepare a message with an encrypted payload using the above key:
201
202 python tests/test_message.py collection update 'An update to the Wiki.' \
203 'Another update.' \
204 | python tests/test_encrypt.py 0891463A
205
206 The complicated recipe based on the individual operations is as follows:
207
208 python tests/test_message.py collection update 'An update to the Wiki.' \
209 'Another update.' \
210 > test.txt \
211 && cat test.txt \
212 | gpg --armor -r 0891463A --encrypt --trust-model always \
213 | python tests/test_encrypt_wrap.py
214
215 Note that "--trust-model always" is used only to avoid prompting issues.
216
217 Signing and Encrypting
218 ----------------------
219
220 Sign and encrypt a message:
221
222 python tests/test_message.py collection update 'An update to the Wiki.' \
223 'Another update.' \
224 | python tests/test_sign.py 1C1AAF83 \
225 | python tests/test_encrypt.py 0891463A
226
227 The complicated recipe based on the individual operations is as follows:
228
229 python tests/test_message.py collection update 'An update to the Wiki.' \
230 'Another update.' \
231 > test.txt \
232 && cat test.txt \
233 | gpg --armor -u 1C1AAF83 --detach-sig \
234 | python tests/test_sign_wrap.py test.txt \
235 | gpg --armor -r 0891463A --encrypt --trust-model always \
236 | python tests/test_encrypt_wrap.py
237
238 Posting a Message
239 -----------------
240
241 To post a signed and/or encrypted message, output from the above activities
242 can be piped into the following command:
243
244 python tests/test_post.py http://localhost/wiki/ShareTest
245
246 Here, the resource "/wiki/ShareTest" on localhost is presented with the
247 message.
248
249 Fetching Messages
250 -----------------
251
252 To fetch messages from a message store associated with a page, the following
253 command can be used:
254
255 python tests/test_fetch.py 1C1AAF83 0891463A http://localhost/wiki/ShareTest \
256 RETR
257
258 This should retrieve all messages from the store associated with the
259 "/wiki/ShareTest" resource on localhost.
260
261 The Message Format
262 ------------------
263
264 Messages are MIME-encoded and consist of one or more update fragments. Where
265 the "Update-Type" header is present and set to a value of "collection", a
266 multipart message describes as many updates as there are parts. Otherwise,
267 only a single update is described by the message.
268
269 For each update, the "Update-Action" header indicates the action to be taken
270 with the update content. Where it is absent, the content is inserted into the
271 Wiki page specified in the request; where it is present and set to "replace",
272 the content replaces all content on the Wiki page; where it is set to "store",
273 the content is stored in a message store associated with the Wiki page.
274
275 Each update may describe multiple representations of some content by employing
276 a multipart/alternative section containing parts for each of the
277 representations. Alternatively, a single message part may describe a single
278 representation.
279
280 HTTP Methods
281 ------------
282
283 Since MoinMoin seems to reserve POST methods for request/entity bodies that
284 contain HTML form data, it is necessary to use alternative methods to post
285 messages to a site served by MoinMoin and to fetch messages from such a site.
286 Consequently, MoinMessage uses PUT to post messages and recommends GET to
287 fetch messages.