1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
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==.,
|