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