summaryrefslogtreecommitdiff
path: root/plugins/MirOTR/libotr/read/Protocol-v1.txt
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/MirOTR/libotr/read/Protocol-v1.txt')
-rw-r--r--plugins/MirOTR/libotr/read/Protocol-v1.txt625
1 files changed, 625 insertions, 0 deletions
diff --git a/plugins/MirOTR/libotr/read/Protocol-v1.txt b/plugins/MirOTR/libotr/read/Protocol-v1.txt
new file mode 100644
index 0000000000..27429bb76d
--- /dev/null
+++ b/plugins/MirOTR/libotr/read/Protocol-v1.txt
@@ -0,0 +1,625 @@
+ Off-The-Record Wire Protocol Documentation
+ ------------------------------------------
+
+ Nikita Borisov and Ian Goldberg
+ <otr@cypherpunks.ca>
+
+Definitions
+-----------
+
+Data encodings:
+
+ Bytes (BYTE):
+ 1 byte unsigned value
+ Shorts (SHORT):
+ 2 byte unsigned value, big-endian
+ Ints (INT):
+ 4 byte unsigned value, big-endian
+ Multi-precision integers (MPI):
+ 4 byte unsigned len, big-endian
+ len byte unsigned value, big-endian
+ (MPIs must use the minimum-length encoding; i.e. no leading 0x00
+ bytes. This is important when calculating public key fingerprints.)
+ Opaque variable-length data (DATA):
+ 4 byte unsigned len, big-endian
+ len byte data
+ DSA signature (DSASIG):
+ (len is the length of the DSA public parameter q)
+ len byte unsigned r, big-endian
+ len byte unsigned s, big-endian
+ Initial CTR-mode counter value (CTR):
+ 8 bytes data
+ Message Authentication Code (MAC):
+ 20 bytes MAC data
+
+Policies:
+
+ Clients can set one of four OTR policies. This can be done either
+ on a per-correspondent basis, or globally, or both. The policies
+ are:
+
+ NEVER:
+ Never perform OTR with this correspondent.
+ MANUAL:
+ Only start OTR if one of you specifically requests it.
+ OPPORTUNISTIC:
+ Start OTR if there's any indication the correspondent supports it.
+ ALWAYS:
+ Only use OTR with this correspondent; it is an error to send an
+ unencrypted message to him.
+
+ The default setting should be OPPORTUNISTIC.
+
+Whitespace Tag:
+
+ There is an OTR_MESSAGE_TAG, which is a 24-byte string of whitespace
+ that clients can optionally append to (or insert in) messages to
+ unobtrusively indicate that they understand the OTR protocol. The
+ string is as follows (in C notation):
+
+ \x20\x09\x20\x20\x09\x09\x09\x09
+ \x20\x09\x20\x09\x20\x09\x20\x20
+ \x20\x09\x20\x09\x20\x20\x09\x20
+
+ [This is the bit pattern of the string "OTR" as expressed in spaces and
+ tabs.]
+
+Protocol
+--------
+
+An OTR client maintains a separate state with each of its
+correspondents. Initially, all correspondents start in the UNCONNECTED
+state.
+
+This is the state machine for the default (OPPORTUNISTIC) policy. The
+modifications for other policies are below.
+
+In the UNCONNECTED state:
+
+ - It may, at the user's instigation or otherwise (for example, if the
+ correspondent's AIM Capability list indicates he supports OTR), send
+ an OTR Query message, and remain in the UNCONNECTED state.
+
+ - If it receives an OTR Query message, it replies with an OTR Key
+ Exchange message, and moves to the SETUP state.
+
+ - If it receives an OTR Key Exchange message, it:
+ - verifies the information in the Key Exchange message
+ - If the verification fails, send an OTR Error message, and remain
+ in the UNCONNECTED state.
+ - If the verification succeeds, reply with an OTR Key Exchange
+ message with the Reply field set to 0x01 (_even if_ the received
+ Key Exchange message itself had the Reply field set), inform the
+ user that private communication has been established, and move to
+ the CONNECTED state.
+
+ - If it receives an OTR Data message, it replies with an OTR Error
+ message, sends a Key Exchange message (with Reply set to 0x00), and
+ moves to the SETUP state.
+
+ - If it receives an OTR Error message, it should display the message to
+ the user, send a Key Exchange message (with Reply set to 0x00), and
+ move to the SETUP state.
+
+ - If it receives an non-OTR message:
+ - If the message contains the OTR_MESSAGE_TAG, it should reply with
+ an OTR Key Exchange message, strip the OTR_MESSAGE_TAG from the
+ message, display the message to the user, and move to the SETUP state.
+ - Otherwise, it should display the message to the user, and remain in
+ the UNCONNECTED state.
+
+In the SETUP state:
+
+ - The user, through a UI action, may elect to reset the connection
+ to the UNCONNECTED state.
+
+ - If it receives an OTR Query message, it replies with an OTR Key
+ Exchange message, and remains in the SETUP state.
+
+ - If it receives an OTR Key Exchange message, it:
+ - verifies the information in the Key Exchange message
+ - If the verification fails, send an OTR Error message, display a
+ notice of the error to the user, and remain in the SETUP state.
+ - If the verification succeeds:
+ - If the received Key Exchange message did not have the Reply field
+ set to 0x01, reply with an OTR Key Exchange (with the Reply field
+ set to 0x01).
+ - In any event, inform the user that private communication has
+ been established, and move to the CONNECTED state.
+
+ - If it receives an OTR Data message, it replies with an OTR Error
+ message, sends a Key Exchange message (with Reply set to 0x00), and
+ remains in the SETUP state.
+
+ - If it receives an OTR Error message, it should display the message to
+ the user, send a Key Exchange message (with Reply set to 0x00), and
+ remain in the SETUP state.
+
+ - If it receives an non-OTR message:
+ - If the message contains the OTR_MESSAGE_TAG, it should reply with
+ an OTR Key Exchange message, and strip the OTR_MESSAGE_TAG from the
+ message, display the message to the user, and remain to the SETUP state.
+ - Otherwise, it should display the message to the user, and remain
+ in the SETUP state.
+
+In the CONNECTED state:
+
+ - The user, through a UI action, may elect to reset the connection
+ to the UNCONNECTED state.
+
+ - If it receives an OTR Query message, it replies with an OTR Key
+ Exchange message, and remains in the CONNECTED state.
+
+ - If it receives an OTR Key Exchange message, it:
+ - verifies the information in the Key Exchange message
+ - If the verification fails, send an OTR Error message, display a
+ notice of the error to the user, and remain in the CONNECTED
+ state.
+ - If the verification succeeds:
+ - If the received Key Exchange message did not have the Reply field
+ set to 0x01, reply with an OTR Key Exchange (with the Reply field
+ set to 0x01).
+ - In any event, remain in the CONNECTED state.
+
+ - If it receives an OTR Data message, it:
+ - verifies the information in the Data message
+ - If the verification fails, send an OTR Error message, display a
+ notice of the error to the user, and remain in the CONNECTED
+ state.
+ - If the verification succeeds, display the (decrypted) message to
+ the user, and remain in the CONNECTED state.
+
+ - If it receives an OTR Error message, it should display the message to
+ the user, and remain in the CONNECTED state.
+
+ - If it receives an non-OTR message, it should reply with an OTR Error
+ message, and remain in the CONNECTED state.
+
+Other policies:
+
+ The above decribes what to do in the default (OPPORTUNISTIC) policy.
+
+ If the policy is NEVER: behave as if OTR is not enabled at all.
+ Pass all received messages to the user, and send all of the user's
+ messages out untouched.
+
+ If the policy is MANUAL: never send the OTR_MESSAGE_TAG in messages,
+ and never respond to one you receive. Don't send a Key Exchange
+ Message (or change state) in response to receiving a Data or Error
+ Message in the UNCONNECTED or SETUP states.
+
+ If the policy is ALWAYS: never send an unencrypted message. Either
+ report an error to the user, or else hold on to the message, send an
+ OTR Query Message instead, and once you enter the CONNECTED state,
+ send the original message. Warn the user if you receive an
+ unencrypted message.
+
+Protocol messages
+-----------------
+
+There are four types of messages in the OTR protocol:
+ - OTR Query
+ - OTR Key Exchange
+ - OTR Data
+ - OTR Error
+
+OTR Query
+---------
+
+This message is sent to inquire if the correspondent supports the OTR
+protocol.
+
+Format:
+
+Any message containing the string "?OTR?" is considered an OTR Query.
+
+Since this message will be visible to the correspondent in the event
+that he does not support the OTR protocol, it may also contain
+human-readable information after this initial string.
+
+Example:
+
+?OTR?\nYour client does not support the OTR Private Messaging
+Protocol.\nSee https://otr.cypherpunks.ca/ for more information.
+
+OTR Key Exchange
+----------------
+
+This message is sent to inform the correspondent of your public
+signature key, and your current DH encryption key.
+
+Format:
+
+The message must contain the five bytes "?OTR:". After that is the
+base-64 encoding of the following, followed by the byte ".":
+
+ - Protocol version (SHORT)
+ - The version number of this protocol is 0x0001.
+ - Message type (BYTE)
+ - OTR Key Exchange has message type 0x0a.
+ - Reply (BYTE)
+ - 0x01 if this Key Exchange message is being sent in reply to a Key
+ Exchange message that was just received. 0x00 otherwise.
+ - DSA p (MPI)
+ - DSA q (MPI)
+ - DSA g (MPI)
+ - DSA e (MPI)
+ - The DSA public key (p,q,g,e).
+ [The parameter 'e' is usually called 'y', but that name's taken by
+ the DH public key, below.]
+ - Sender keyid (INT)
+ - The keyid for this initial key. Must be greater than 0.
+ - DH y (MPI)
+ - The initial DH public encryption key. The DH group is the one
+ defined in RFC 3526 with 1536-bit modulus (hex, big-endian):
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+ 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+ EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+ E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+ EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
+ C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
+ 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
+ 670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF
+ and generator 2.
+ - Signature (DSASIG)
+ - A signature with the private DSA key corresponding to (p,q,g,e).
+ Take a SHA-1 hash of everything from the protocol version to the
+ end of the value of y, and sign that value.
+
+ The DSA key given in this message has a "Fingerprint", which is the
+ SHA-1 hash of the portion of the message from the beginning of the "p"
+ field (including the MPI length) to the end of the "e" field. This
+ fingerprint should be displayed to the recipient so that he may verify
+ the sender's key.
+
+OTR Data
+--------
+
+This message is used to transmit a private message to the correspondent.
+It is also used to reveal old MAC keys.
+
+The plaintext message (either before encryption, or after decryption)
+consists of a human-readable message, optionally followed by:
+ - a single NUL (a BYTE with value 0x00)
+ AND
+ - zero or more TLV (type/length/value) records (with no padding
+ between them)
+
+Each TLV record is of the form:
+ - Type (SHORT)
+ - The type of this record. Records with unrecognized types should
+ be ignored.
+ - Length (SHORT)
+ - The length of the following field
+ - Value (len BYTEs) [where len is the value of the Length field]
+ - Any pertinent data for the record type.
+
+Some TLV examples:
+
+ \x00\x01\x00\x00
+ A TLV of type 1, containing no data
+
+ \x00\x00\x00\x05\x68\x65\x6c\x6c\x6f
+ A TLV of type 0, containing the value "hello"
+
+The currently defined TLV record types are:
+
+ Type 0: Padding
+ The value may be an arbitrary amount of data, which should be
+ ignored. This type can be used to disguise the length of the
+ plaintext message.
+
+ Type 1: Disconnected
+ If the user requests to close the private connection, you may
+ send a message (possibly with empty human-readable part)
+ containing a record with this TLV type just before you discard
+ the session keys. If you receive a TLV record of this type,
+ you may inform the user that his correspondent has closed his
+ end of the private connection, and the user should do the same.
+
+Format:
+
+The message must contain the five bytes "?OTR:". After that is the
+base-64 encoding of the following, followed by the byte ".":
+
+ - Protocol version (SHORT)
+ - The version number of this protocol is 0x0001.
+ - Message type (BYTE)
+ - OTR Data has message type 0x03.
+ - Sender keyid (INT)
+ - Must be strictly greater than 0, and increment by 1 with each key
+ change
+ - Recipient keyid (INT)
+ - Must therefore be strictly greater than 0, as the receiver has no
+ key with id 0
+ - The sender and recipient keyids are those used to encrypt and MAC
+ this message.
+ - DH y (MPI)
+ - The *next* [i.e. sender_keyid+1] public key for the sender
+ - Top half of counter init (CTR)
+ - This should monotonically increase (as a big-endian value) for
+ each message sent with the same (sender keyid, recipient keyid)
+ pair , and must not be all 0x00.
+ - Encrypted message (DATA)
+ - Using the appropriate encryption key (see below) derived from the
+ sender's and recipient's DH public keys (with the keyids given in
+ this message), perform AES128 counter-mode (CTR) encryption of the
+ message. The initial counter is a 16-byte value whose first 8
+ bytes are the above "top half of counter init" value, and whose
+ last 8 bytes are all 0x00. Note that counter mode does not change
+ the length of the message, so no message padding needs to be done.
+ If you *want* to do message padding (to disguise the length of
+ your message), pad with NULs (bytes of 0x00). Upon receiving
+ and successfully decrypting an OTR Data Message, the decrypted
+ payload should be truncated just before the first NUL (if any).
+ - SHA1-HMAC, using the appropriate MAC key (see below) of everything
+ from the Protocol version to the end of the encrypted message (MAC)
+ - Old MAC keys to be revealed (DATA)
+ - See "Revealing MAC Keys", below.
+
+OTR Error
+---------
+
+This message is sent when a problem has occurred in the protocol.
+
+Format:
+
+Any message containing "?OTR Error:" is an OTR Error message. The
+following part of the message should contain human-readable details of
+the error.
+
+Key Management
+--------------
+
+For each correspondent, keep track of:
+ - My two most recent DH public/private key pairs
+ - our_dh[our_keyid] (most recent) and our_dh[our_keyid-1] (previous)
+ - His two most recent DH public keys
+ - their_y[their_keyid] (most recent) and their_y[their_keyid-1] (previous)
+
+When starting a private conversation with a correspondent, generate
+two DH key pairs for yourself, and set our_keyid = 2. Note that all DH
+key pairs should have a private part that is at least 320 bits long.
+
+When you send an OTR Key Exchange message:
+ Send the public part of our_dh[our_keyid-1], with the keyid field,
+ of course, set to (our_keyid-1).
+
+When you receive an OTR Key Exchange message:
+ If the specified keyid equals either their_keyid or their_keyid-1,
+ and the DH pubkey contained in the Key Exchange message matches the
+ one we've stored for that keyid, that's great. Otherwise, forget
+ all values of their_y[], and of their_keyid, and set their_keyid to
+ the keyid value given in the Key Exchange message, and
+ their_y[their_keyid] to the DH pubkey value given in the Key
+ Exchange message. their_y[their_keyid-1] should be set to NULL.
+
+ In any event, if the Reply field of the Key Exchange message was set
+ to 0x00, send a Key Exchange message with the Reply field set to
+ 0x01.
+
+When you send an OTR Data message:
+ Set the sender keyid to (our_keyid-1), and the recipient keyid to
+ (their_keyid). Set the DH pubkey in the Data message to the public
+ part of our_dh[our_keyid]. Use our_dh[our_keyid-1] and
+ their_y[their_keyid] to calculate session keys, as outlined below.
+ Use the "sending AES key" to encrypt the message, and the "sending
+ MAC key" to calculate its MAC.
+
+When you receive an OTR Data message:
+ Use the keyids in the message to select which of your DH key pairs
+ and which of his DH pubkeys to use to verify the MAC. If the keyids
+ do not represent either the most recent key or the previous key (for
+ either the sender or receiver), reject the message. Also reject the
+ message if the sender keyid is their_keyid-1, but
+ their_y[their_keyid-1] is NULL.
+
+ Otherwise, calculate the session keys as outlined below. Use the
+ "receiving MAC key" to verify the MAC on the message. If it does not
+ verify, reject the message.
+
+ Check that the counter in the Data message is strictly larger than the
+ last counter we saw using this pair of keys. If not, reject the
+ message.
+
+ If the MAC verifies, decrypt the message using the "receiving AES key".
+
+ Finally, check if keys need rotation:
+ - If the "recipient keyid" in the Data message equals our_keyid, then
+ he's seen the public part of our most recent DH key pair, so we
+ securely forget our_dh[our_keyid-1], increment our_keyid, and set
+ our_dh[our_keyid] to a new DH key pair which we generate.
+ - If the "sender keyid" in the Data message equals their_keyid,
+ increment their_keyid, and set their_y[their_keyid] to the new DH
+ pubkey specified in the Data message.
+
+ If the message you get after decryption is of zero length, this is a
+ "heartbeat" packet. Don't display it to the user. (But it's still
+ useful to effect key rotations.)
+
+Calculating session keys:
+ Given one of our DH key pairs, and one of his DH pubkeys, we
+ calculate a DH secure id, two AES keys, and two MAC keys as follows:
+
+ Let (our_x, our_y) be the private and public parts of our DH
+ key pair. Let their_y be his DH pubkey.
+
+ First, calculate the shared secret:
+ secret = their_y ^ our_x mod DH_MODULUS
+ (^ denotes exponentiation, and DH_MODULUS is the 1536-bit DH modulus
+ from RFC 3526, as specified above).
+
+ Write the value of secret as a minimum-length MPI, as specific above
+ (4-byte big-endian len, len-byte big-endian value). Let this
+ (4+len)-byte value be "secbytes".
+
+ Next, determine if we are the "low" end or the "high" end of this
+ key exchange. If our_y > their_y, then we are the "high" end.
+ Otherwise, we are the "low" end. Note that who is the "low" end and
+ who is the "high" end can change every time a new DH pubkey is
+ exchanged.
+
+ Calculate the DH secure id as the SHA-1 hash of the (5+len)-byte value
+ composed of the byte 0x00, followed by the (4+len) bytes of
+ secbytes.
+
+ When a new private connection is established, the "secure session
+ id" for the connection is set to be the DH secure id calculated in
+ this way.
+
+ The secure session id should be displayed as two 10-byte
+ (big-endian) values, in C "%20x" format. If we are the "low" end of
+ the key exchange, display the first 10 bytes in bold, and the second
+ 10 bytes in non-bold. If we are the "high" end of the key exchange,
+ display the first 10 bytes in non-bold, and the second 10 bytes in
+ bold. This session id can be used by the parties to verify (say,
+ over the telephone, assuming the parties recognize each others'
+ voices) that there is no man-in-the-middle by having each side read
+ his bold part to the other.
+
+ To be clear, if the user requests to see the secure session id in
+ the middle of the conversation, the value displayed should be the
+ one calculated at the time the private connection was established
+ (the last Key Exchange Message that caused a rekeying), _not_ the DH
+ secure id calculated from DH keys in more recent Data Messages.
+
+ Now set the values of "sendbyte" and "recvbyte" according to whether
+ we are the "low" or the "high" end of the key exchange:
+ - If we are the "high" end, set "sendbyte" to 0x01 and "recvbyte"
+ to 0x02.
+ - If we are the "low" end, set "sendbyte" to 0x02 and "recvbyte"
+ to 0x01.
+
+ Calculate the "sending AES key" to be the first 16 bytes of the
+ SHA-1 hash of the (5+len)-byte value composed of the byte
+ (sendbyte), followed by the (4+len) bytes of secbytes.
+
+ Calculate the "sending MAC key" to be all 20 bytes of the SHA-1 hash
+ of the 16-byte sending AES key.
+
+ Calculate the "receiving AES key" to be the first 16 bytes of the
+ SHA-1 hash of the (5+len)-byte value composed of the byte
+ (recvbyte), followed by the (4+len) bytes of secbytes.
+
+ Calculate the "receiving MAC key" to be all 20 bytes of the SHA-1 hash
+ of the 16-byte receiving AES key.
+
+Revealing MAC keys
+------------------
+
+Whenever you are about to forget either one of your old DH key pairs, or
+one of your correspondent's old DH pubkeys, take all of the MAC keys
+that were generated by that key (note that there are up to four: the
+sending and receiving MAC keys produced by the pairings of that key with
+each of two of the other side's keys; but note that you only need to
+take MAC keys that were actually used to either create a MAC on a
+message, or verify a MAC on a message), and put them (as a set of
+concatenated 20-byte values) into the "Old MAC keys to be revealed"
+section of the next Data message you send. We do this to allow the
+forgeability of OTR transcripts: once the MAC keys are revealed, anyone
+can modify an OTR message and still have it appear valid. But since we
+don't reveal the MAC keys until their corresponding pubkeys are being
+discarded, there is no danger of us accepting a message as valid which
+uses a MAC key which has already been revealed.
+
+Fragments
+---------
+
+[Remember when reading this section that the network model assumes
+in-order delivery, but that some messages may not get delivered at all
+(for example, if the user disconnects). And, of course, there's the
+possibility of an active attacker, who is allowed to perform a Denial of
+Service attack, but not to learn contents of messages.]
+
+Transmitting Fragments:
+
+ If you have information about the maximum size of message you are
+ able to send (the different IM networks have different limits), you
+ can fragment an OTR message as follows:
+
+ - Start with the OTR message as you would normally transmit it. For
+ example, an OTR Data Message would start with "?OTR:AAED" and end
+ with ".".
+ - Break it up into sufficiently small pieces. Let the number of
+ pieces be (n), and the pieces be piece[1],piece[2],...,piece[n].
+ - Transmit (n) messages with the following (printf-like) structure
+ (as k runs from 1 to n inclusive):
+
+ "?OTR,%hu,%hu,%s," , k , n , piece[k]
+
+ - Note that k and n are unsigned short ints (2 bytes), and each has
+ a maximum value of 65535. Also, each piece[k] must be non-empty.
+
+Receiving Fragments:
+
+ If you receive a message containing "?OTR," (note that you'll need
+ to check for this _before_ checking for any of the other "?OTR:"
+ markers):
+
+ - Parse it as the printf statement above into k, n, and piece.
+ - Let (K,N) be your currently stored fragment number, and F be your
+ currently stored fragment. [If you have no currently stored
+ fragment, then K = N = 0 and F = "".]
+
+ - If k == 0 or n == 0 or k > n, discard this (illegal) fragment.
+
+ - If k == 1:
+ - Forget any stored fragment you may have
+ - Store (piece) as F.
+ - Store (k,n) as (K,N).
+
+ - If n == N and k == K+1:
+ - Append (piece) to F.
+ - Store (k,n) as (K,N).
+
+ - Otherwise:
+ - Forget any stored fragment you may have
+ - Store "" as F.
+ - Store (0,0) as (K,N).
+
+ After this, if N > 0 and K == N, treat F as the received message.
+
+ If you receive an unfragmented message, forget any stored fragment
+ you may have, store "" as F and store (0,0) as (K,N).
+
+Example:
+
+ Here is an OTR Key Exchange Message we would like to transmit over a
+ network with an unreasonably small maximum message size:
+
+ ?OTR:AAEKAQAAAICGmmRMlmuq4gY7Ro0GiYAJKWwVZyITNyifFP9VRIVgyxxGxwV
+ bFjoGMhO9XE0xFisuO6M27DPkX7hCtIXZM2glDszmTklQO5hJPu0g/RgDZ84q0ee
+ Q5AvexW3Hmp/VHUPTpZfJPep/Ctiqn0oE2y/2yRPyYQjpZCL440sM5i7B1wAAABT
+ zzL9WbuaxOK8rfrtaw4Lx/iLxeQAAAIAWaGpchsVOV1D6xK5cS5QNANelTvyVHre
+ XPSRjU0NFKIHrNDiFwa8lXcIBH/E8MHoQDzw+J2AuU6MuICPT8GMJYBcSZq0OM7x
+ gmfNlt1viUXxJXbYRpD82ki7QsMA1I7aQo/OqMryKlW5W8UqEjVcCsTOjEyQphLY
+ ENG6St9+ivgAAAIBgUjzleG1+VYCXZszTj+x5gNNidVVNKI+MG5elHMcsg2Guef3
+ DBYEsor6YGeqJLAfhk28Tg7tktMQwGN5GXR1ZNkwkoFIOyVRq3lfabfHtsTp+Hkx
+ 5e8OrhTZ1G+ScDeqYbbTtUj631LhXUoyp+7pllVtpyLgqk5z9JYu6Kw0ZkQAAAAE
+ AAADASZH/uq17EVRo6dBZIL12x9JLx4gpEjgovfNLoORa6E+sMMuG7Z+zfLQVodX
+ H5shi/dvPzwbVrA/Iw72XHSYtld8lK/FLtjsI5mzancvRAEs1ZDBoBJRLW1X54eF
+ HpN/peDi6fBbdXyGahWYyF9MCJxDFCRqAHvEMZbfdyEtkXbFUZM2lJM2SJJG9zGZ
+ LCvd2/gF/VOgMlvdus+8TFW0k7cBhAgm/rb+EUeovkWXy2BiVpInXKCCH+M6EVpU
+ YNG7BPtH44ABwUw6Y5n5sSb6dtout34NGz+dspXMajffkZxFOAcabRwKIpw==.
+
+ We could fragment this message into (for example) three pieces:
+
+ ?OTR,1,3,?OTR:AAEKAQAAAICGmmRMlmuq4gY7Ro0GiYAJKWwVZyITNyifFP9VRI
+ VgyxxGxwVbFjoGMhO9XE0xFisuO6M27DPkX7hCtIXZM2glDszmTklQO5hJPu0g/R
+ gDZ84q0eeQ5AvexW3Hmp/VHUPTpZfJPep/Ctiqn0oE2y/2yRPyYQjpZCL440sM5i
+ 7B1wAAABTzzL9WbuaxOK8rfrtaw4Lx/iLxeQAAAIAWaGpchsVOV1D6xK5cS5QNAN
+ elTvyVHreXPSRjU0NFKIHrNDiFwa8lXcIBH/E8MHoQDzw+J2AuU6MuICPT8GMJYB
+ cSZq0OM7xgmfNlt1viUXxJXbYRpD82ki7QsMA1I7aQo/OqMryKlW5W8UqEjVcCsT
+ OjEyQphLY,
+
+ ?OTR,2,3,ENG6St9+ivgAAAIBgUjzleG1+VYCXZszTj+x5gNNidVVNKI+MG5elHM
+ csg2Guef3DBYEsor6YGeqJLAfhk28Tg7tktMQwGN5GXR1ZNkwkoFIOyVRq3lfabf
+ HtsTp+Hkx5e8OrhTZ1G+ScDeqYbbTtUj631LhXUoyp+7pllVtpyLgqk5z9JYu6Kw
+ 0ZkQAAAAEAAADASZH/uq17EVRo6dBZIL12x9JLx4gpEjgovfNLoORa6E+sMMuG7Z
+ +zfLQVodXH5shi/dvPzwbVrA/Iw72XHSYtld8lK/FLtjsI5mzancvRAEs1ZDBoBJ
+ RLW1X54eFHpN/peDi6fBbdXyGahWYyF9MCJxDFCRqAHvEMZbfdyEtkXbFUZM2lJM
+ 2SJJG9zGZ,
+
+ ?OTR,3,3,LCvd2/gF/VOgMlvdus+8TFW0k7cBhAgm/rb+EUeovkWXy2BiVpInXKC
+ CH+M6EVpUYNG7BPtH44ABwUw6Y5n5sSb6dtout34NGz+dspXMajffkZxFOAcabRw
+ KIpw==.,