libsession 0.1.7

Session messenger core library - cryptography, config management, networking
Documentation
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
// iOS - since we use a modern proto-compiler, we must specify the legacy proto format.
syntax = "proto2";

// iOS - package name determines class prefix
package SessionProtos;

option java_package = "org.session.protos";
option optimize_for = LITE_RUNTIME;

message Envelope {

  enum Type {
    SESSION_MESSAGE      = 6;
    CLOSED_GROUP_MESSAGE = 7;
  }

  // @required
  required Type   type            = 1;
  optional string source          = 2;
  optional uint32 sourceDevice    = 7;
  // @required
  required uint64 timestamp       = 5;
  optional bytes  content         = 8;
  optional uint64 serverTimestamp = 10;
  optional bytes  proSig          = 11;
}

message TypingMessage {

    enum Action {
        STARTED = 0;
        STOPPED = 1;
    }

    // @required
    required uint64 timestamp = 1;
    // @required
    required Action action    = 2;
}

message UnsendRequest {
    // @required
    required uint64 timestamp = 1;
    // @required
    required string author    = 2;
}

message MessageRequestResponse {
  // @required
  required bool                      isApproved                = 1; // Whether the request was approved
  optional bytes                     profileKey                = 2;
  optional LokiProfile               profile                   = 3;
}

message Content {

  enum ExpirationType {
    UNKNOWN           = 0;
    DELETE_AFTER_READ = 1;
    DELETE_AFTER_SEND = 2;
  }

  // reserved 7, 11, 15;
  // reserved "configurationMessage", "sharedConfigMessage", "lastDisappearingMessageChangeTimestamp";

  optional DataMessage                dataMessage                            = 1;
  optional CallMessage                callMessage                            = 3;
  optional ReceiptMessage             receiptMessage                         = 5;
  optional TypingMessage              typingMessage                          = 6;
  optional DataExtractionNotification dataExtractionNotification             = 8;
  optional UnsendRequest              unsendRequest                          = 9;
  optional MessageRequestResponse     messageRequestResponse                 = 10;
  optional SharedConfigMessage        sharedConfigMessage                    = 11;
  optional ExpirationType             expirationType                         = 12;
  optional uint32                     expirationTimer                        = 13;

  // NOTE: This timestamp was added to address the issue with 1o1 message envelope timestamps were
  // unauthenticated because 1o1 messages encrypt the Content not the envelope. In Groups, the
  // entire envelope is encrypted and hence can be trusted.
  optional uint64                     sigTimestamp                           = 15;
  optional ProMessage                 proMessage                             = 16;

  // NOTE: Temporary transition field to include the pro-signature into Content for community
  // messages to use.
  //
  // Community messages are currently sent and received as plaintext Content. We call this state of
  // the network v0.
  //
  // We will continue to send Community messages using the Content structure, but, now enhanced with
  // the optional `proSigForCommunityMessageOnly` field which contains the pro signature. We call
  // this network v1. The new clients running v1 will pack the pro-signature into the payload. We
  // maintain forwards compatibility with clients on v0 as we are still sending content
  // on the wire, they skip the new pro data.
  //
  // Simultaneously in v1 the responsibility of parsing the open groups messages will go into
  // libsession. Libsession will be setup to try and parse the open groups message as a `Content`
  // message at first, if that fails it will try to read the community message as an `Envelope`.
  // In summary in a v1 network:
  //
  //   v0 will still receive messages from v1 as they send `Content` community messages.
  //
  //   v1 accepts v0 (`Content`) and v1 (`Envelope`) on the wire for community messages. v1 sends
  //   `Content` community messages so that there's compatibility with v0.
  //
  // After a defined transitionary period, we create a new release and update libsession to stop
  // sending `Content` for communities and transition to sending `Envelope` for messages. We mark
  // this as a v2 network:
  //
  //   v0 will still receive messages from v1 (`Content`) but not v2 (`Envelope`) community
  //   messages.
  //
  //   v1 accepts v0 (`Content`) and v1 (`Envelope`) on the wire for community messages. v1 sends
  //   `Content` community messages so that there's compatibility with v0.
  //
  //   v2 swaps the parsing order. it tries parsing v1 (`envelope`) then v0 (`content`) from a
  //   community message. v2 sends `envelope` community messages so compatbility is maintained with
  //   v1 but not v0.
  //
  // After a final transitionary period, v3, remove parsing content entirely from libsession for
  // community messages and removes the pro-signature from `content`. in this final stage, v2 and v3
  // are the final set of clients that can continue to talk to each other.
  //
  // +---------+----------------+-------------+------------------+-------------+-------------+
  // | Version | Sends          | Receives v0 | Receives v1      | Receives v2 | Receives v3 |
  // |         |                | (Content)   | (Content+ProSig) | (Envelope)  | (Envelope)  |
  // +---------+----------------+-------------+------------------+-------------+-------------+
  // | v0      | Content        | Yes         | Yes              | No          | No          |
  // +---------+----------------+-------------+------------------+-------------+-------------+
  // | v1      | Content+ProSig | Yes         | Yes              | Yes         | Yes         |
  // +---------+----------------+-------------+------------------+-------------+-------------+
  // | v2      | Envelope       | Yes         | Yes              | Yes         | Yes         |
  // +---------+----------------+-------------+------------------+-------------+-------------+
  // | v3      | Envelope       | No          | No               | Yes         | Yes         |
  // +---------+----------------+-------------+------------------+-------------+-------------+
  optional bytes                      proSigForCommunityMessageOnly          = 17;
}

message CallMessage {

    enum Type {
      PRE_OFFER          = 6;
      OFFER              = 1;
      ANSWER             = 2;
      PROVISIONAL_ANSWER = 3;
      ICE_CANDIDATES     = 4;
      END_CALL           = 5;
    }

    // Multiple ICE candidates may be batched together for performance

    // @required
    required Type   type            = 1;
    repeated string sdps            = 2;
    repeated uint32 sdpMLineIndexes = 3;
    repeated string sdpMids         = 4;
    // @required
    required string uuid            = 5;
}

message KeyPair {
  // @required
  required bytes publicKey  = 1;
  // @required
  required bytes privateKey = 2;
}

message DataExtractionNotification {

  enum Type {
    SCREENSHOT  = 1;
    MEDIA_SAVED = 2; // timestamp
  }

  // @required
  required Type   type      = 1;
  optional uint64 timestamp = 2;
}

message LokiProfile {
  optional string displayName = 1;
  optional string profilePicture = 2;
  optional uint64 lastUpdateSeconds = 3; // Timestamp of the last profile update
}

message DataMessage {

  enum Flags {
    EXPIRATION_TIMER_UPDATE = 2;
  }

  message Quote {

    message QuotedAttachment {

      enum Flags {
        VOICE_MESSAGE = 1;
      }

      optional string            contentType = 1;
      optional string            fileName    = 2;
      optional AttachmentPointer thumbnail   = 3;
      optional uint32            flags       = 4;
    }

    // @required
    required uint64            id          = 1;
    // @required
    required string            author      = 2;
    optional string            text        = 3;
    repeated QuotedAttachment  attachments = 4;
  }

  message Preview {
    // @required
    required string            url   = 1;
    optional string            title = 2;
    optional AttachmentPointer image = 3;
  }

  message Reaction {
    enum Action {
        REACT = 0;
        REMOVE = 1;
    }
    // @required
    required uint64 id        = 1; // Message timestamp
    // @required
    required string author    = 2;
    optional string emoji     = 3;
    // @required
    required Action action    = 4;
  }

  message OpenGroupInvitation {
    // @required
    required string url = 1;
    // @required
    required string name = 3;
  }


  //  reserved 3;
  //  reserved "group";
  // reserved 104;
  // reserved "closedGroupControlMessage";

  optional string                    body                           = 1;
  repeated AttachmentPointer         attachments                    = 2;
  optional uint32                    flags                          = 4;
  // optional uint32                 expireTimer                    = 5;  // No longer used
  optional bytes                     profileKey                     = 6;
  optional uint64                    timestamp                      = 7;
  optional Quote                     quote                          = 8;
  repeated Preview                   preview                        = 10;
  optional Reaction                  reaction                       = 11;
  optional LokiProfile               profile                        = 101;
  optional OpenGroupInvitation       openGroupInvitation            = 102;
  optional string                    syncTarget                     = 105;
  optional bool                      blocksCommunityMessageRequests = 106;
  optional GroupUpdateMessage        groupUpdateMessage             = 120;
}

message ReceiptMessage {

  enum Type {
    DELIVERY = 0;
    READ     = 1;
  }

  // @required
  required Type   type      = 1;
  repeated uint64 timestamp = 2;
}

message AttachmentPointer {

  enum Flags {
    VOICE_MESSAGE = 1;
  }

  // @required
  required fixed64 id          = 1;
  optional string  contentType = 2;
  optional bytes   key         = 3;
  optional uint32  size        = 4;
  optional bytes   thumbnail   = 5;
  optional bytes   digest      = 6;
  optional string  fileName    = 7;
  optional uint32  flags       = 8;
  optional uint32  width       = 9;
  optional uint32  height      = 10;
  optional string  caption     = 11;
  optional string  url         = 101;
}

message SharedConfigMessage {
    enum Kind {
        USER_PROFILE            = 1;
        CONTACTS                = 2;
        CONVO_INFO_VOLATILE     = 3;
        USER_GROUPS             = 4;
    }

    // @required
    required Kind   kind        = 1;
    // @required
    required int64  seqno       = 2;
    // @required
    required bytes  data        = 3;
}

// Group Update Messages

message GroupUpdateMessage {
  optional GroupUpdateInviteMessage                  inviteMessage                 = 1;
  optional GroupUpdateInfoChangeMessage              infoChangeMessage             = 2;
  optional GroupUpdateMemberChangeMessage            memberChangeMessage           = 3;
  optional GroupUpdatePromoteMessage                 promoteMessage                = 4;
  optional GroupUpdateMemberLeftMessage              memberLeftMessage             = 5;
  optional GroupUpdateInviteResponseMessage          inviteResponse                = 6;
  optional GroupUpdateDeleteMemberContentMessage     deleteMemberContent           = 7;
  optional GroupUpdateMemberLeftNotificationMessage  memberLeftNotificationMessage = 8;
}

message GroupUpdateInviteMessage {
  // @required
  required string         groupSessionId         = 1; // The `groupIdentityPublicKey` with a `03` prefix
  // @required
  required string         name                   = 2;
  // @required
  required bytes          memberAuthData         = 3;
  // @required
  required bytes          adminSignature         = 4;
}

message GroupUpdatePromoteMessage {
  // @required
  required bytes          groupIdentitySeed       = 1;
  // @required
  required string         name                    = 2;
}

message GroupUpdateInfoChangeMessage {
  enum Type {
    NAME                  = 1;
    AVATAR                = 2;
    DISAPPEARING_MESSAGES = 3;
  }

  // @required
  required Type     type              = 1;
  optional string   updatedName       = 2;
  optional uint32   updatedExpiration = 3;
  // @required
  required bytes    adminSignature    = 4;
}

message GroupUpdateMemberChangeMessage {
  enum Type {
    ADDED    = 1;
    REMOVED  = 2;
    PROMOTED = 3;
  }

  // @required
  required Type   type               = 1;
  repeated string memberSessionIds   = 2;
  optional bool   historyShared      = 3;
  // @required
  required bytes  adminSignature     = 4;
}

message GroupUpdateMemberLeftMessage {
  // the pubkey of the member left is included as part of the closed group encryption logic (senderIdentity on desktop)
}

message GroupUpdateMemberLeftNotificationMessage {
  // the pubkey of the member left is included as part of the closed group encryption logic (senderIdentity on desktop)
}

message GroupUpdateInviteResponseMessage {
  // @required
  required bool                      isApproved                = 1; // Whether the request was approved
}

message GroupUpdateDeleteMemberContentMessage {
  repeated string memberSessionIds   = 1;
  repeated string messageHashes      = 2;
  optional bytes  adminSignature     = 3;
}

message ProProof {
  optional uint32 version           = 1;
  optional bytes  genIndexHash      = 2; // Opaque identifier of this proof produced by the Session Pro backend
  optional bytes  rotatingPublicKey = 3; // Public key whose signatures is authorised to entitle messages with Session Pro
  optional uint64 expiryUnixTs      = 4; // Epoch timestamps in milliseconds
  optional bytes  sig               = 5; // Signature produced by the Session Pro Backend signing over the hash of the proof
}

message ProMessage {
  optional ProProof proof          = 1;
  optional uint64   profileBitset  = 2;
  optional uint64   msgBitset      = 3;
}