@wireapp/core 38.8.2 → 38.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts +2 -2
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.js +3 -4
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +54 -94
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.js +15 -15
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +50 -42
- package/package.json +4 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { APIClient } from '@wireapp/api-client';
|
|
2
|
-
import {
|
|
2
|
+
import { CryptoClient } from './CryptoClient';
|
|
3
3
|
import { ProteusService } from './ProteusService';
|
|
4
4
|
export declare const buildProteusService: (federated?: boolean) => Promise<[ProteusService, {
|
|
5
5
|
apiClient: APIClient;
|
|
6
|
-
|
|
6
|
+
cryptoClient: CryptoClient;
|
|
7
7
|
}]>;
|
|
8
8
|
//# sourceMappingURL=ProteusService.mocks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProteusService.mocks.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/proteus/ProteusService/ProteusService.mocks.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ProteusService.mocks.d.ts","sourceRoot":"","sources":["../../../../src/messagingProtocols/proteus/ProteusService/ProteusService.mocks.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAIhD,eAAO,MAAM,mBAAmB;eAEQ,SAAS;kBAAgB,YAAY;GAgB5E,CAAC"}
|
|
@@ -21,7 +21,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
21
21
|
exports.buildProteusService = void 0;
|
|
22
22
|
const client_1 = require("@wireapp/api-client/lib/client");
|
|
23
23
|
const api_client_1 = require("@wireapp/api-client");
|
|
24
|
-
const core_crypto_1 = require("@wireapp/core-crypto");
|
|
25
24
|
const CoreCryptoWrapper_1 = require("./CryptoClient/CoreCryptoWrapper");
|
|
26
25
|
const ProteusService_1 = require("./ProteusService");
|
|
27
26
|
const PayloadHelper_1 = require("../../../test/PayloadHelper");
|
|
@@ -32,11 +31,11 @@ const buildProteusService = async (federated = false) => {
|
|
|
32
31
|
userId: (0, PayloadHelper_1.getUUID)(),
|
|
33
32
|
clientId: (0, PayloadHelper_1.getUUID)(),
|
|
34
33
|
};
|
|
35
|
-
const
|
|
36
|
-
const proteusService = new ProteusService_1.ProteusService(apiClient,
|
|
34
|
+
const cryptoClient = new CoreCryptoWrapper_1.CoreCryptoWrapper({}, {}, {});
|
|
35
|
+
const proteusService = new ProteusService_1.ProteusService(apiClient, cryptoClient, {
|
|
37
36
|
nbPrekeys: 0,
|
|
38
37
|
useQualifiedIds: federated,
|
|
39
38
|
});
|
|
40
|
-
return [proteusService, { apiClient,
|
|
39
|
+
return [proteusService, { apiClient, cryptoClient }];
|
|
41
40
|
};
|
|
42
41
|
exports.buildProteusService = buildProteusService;
|
|
@@ -65,7 +65,7 @@ jest.mock('./CryptoClient/PrekeysTracker', () => {
|
|
|
65
65
|
jest.mock('../Utility/Recipients', () => (Object.assign(Object.assign({}, jest.requireActual('../Utility/Recipients')), { getRecipientsForConversation: jest.fn(), getQualifiedRecipientsForConversation: jest.fn() })));
|
|
66
66
|
const MockedRecipients = Recipients;
|
|
67
67
|
const prepareDataForEncryption = async (useQualifiedIds = true) => {
|
|
68
|
-
const [proteusService, {
|
|
68
|
+
const [proteusService, { cryptoClient, apiClient }] = await (0, ProteusService_mocks_1.buildProteusService)(useQualifiedIds);
|
|
69
69
|
const domain = 'staging.zinfra.io';
|
|
70
70
|
//user 1
|
|
71
71
|
const firstUserId = 'bc0c99f1-49a5-4ad2-889a-62885af37088';
|
|
@@ -88,7 +88,7 @@ const prepareDataForEncryption = async (useQualifiedIds = true) => {
|
|
|
88
88
|
//user 2
|
|
89
89
|
const secondUserId = 'cd0c88f1-49a5-4ar2-889a-62885af37069';
|
|
90
90
|
//user 2 client
|
|
91
|
-
const thirdClientId = '
|
|
91
|
+
const thirdClientId = 'ce67218b77d02d69';
|
|
92
92
|
//user 2 sessions
|
|
93
93
|
const secondClientSessionId = (0, SessionHandler_1.constructSessionId)({
|
|
94
94
|
userId: secondUserId,
|
|
@@ -107,7 +107,7 @@ const prepareDataForEncryption = async (useQualifiedIds = true) => {
|
|
|
107
107
|
key: 'pQABARn//wKhAFggJ1Fbpg5l6wnzKOJE+vXpRnkqUYhIvVnR5lNXEbO2o/0DoQChAFggHxZvgvtDktY/vqBcpjjo6rQnXvcNQhfwmy8AJQJKlD0E9g==',
|
|
108
108
|
};
|
|
109
109
|
return {
|
|
110
|
-
services: { proteusService, apiClient,
|
|
110
|
+
services: { proteusService, apiClient, cryptoClient },
|
|
111
111
|
data: {
|
|
112
112
|
firstUser: {
|
|
113
113
|
id: firstUserId,
|
|
@@ -130,29 +130,35 @@ const prepareDataForEncryption = async (useQualifiedIds = true) => {
|
|
|
130
130
|
describe('ProteusService', () => {
|
|
131
131
|
describe('getRemoteFingerprint', () => {
|
|
132
132
|
it('create a session if session does not exists', async () => {
|
|
133
|
-
const [proteusService, { apiClient,
|
|
133
|
+
const [proteusService, { apiClient, cryptoClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
134
134
|
const expectedFingerprint = 'fingerprint-client1';
|
|
135
|
-
const getPrekeyMock = jest.spyOn(apiClient.api.user, 'getClientPreKey').mockResolvedValue({
|
|
136
|
-
client: 'client1',
|
|
137
|
-
prekey: {
|
|
138
|
-
id: 123,
|
|
139
|
-
key: 'pQABARhIAqEAWCCaJpFa9c626ORmjj1aV6OnOYgmTjfoiE3ynOfNfGAOmgOhAKEAWCD60VMzRrLfO+1GSjgyhnVp2N7L58DM+eeJhZJi1tBLfQT2',
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
jest.spyOn(coreCrypto, 'proteusFingerprintRemote').mockResolvedValue(expectedFingerprint);
|
|
143
|
-
jest.spyOn(coreCrypto, 'proteusSessionExists').mockResolvedValue(false);
|
|
144
135
|
const userId = { id: 'user1', domain: 'domain.com' };
|
|
145
136
|
const clientId = 'client1';
|
|
137
|
+
jest.spyOn(apiClient.api.user, 'postQualifiedMultiPreKeyBundles').mockResolvedValue({
|
|
138
|
+
[userId.domain]: {
|
|
139
|
+
[userId.id]: {
|
|
140
|
+
[clientId]: {
|
|
141
|
+
id: 123,
|
|
142
|
+
key: 'pQABARhIAqEAWCCaJpFa9c626ORmjj1aV6OnOYgmTjfoiE3ynOfNfGAOmgOhAKEAWCD60VMzRrLfO+1GSjgyhnVp2N7L58DM+eeJhZJi1tBLfQT2',
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
jest.spyOn(cryptoClient, 'getRemoteFingerprint').mockResolvedValue(expectedFingerprint);
|
|
148
|
+
jest.spyOn(cryptoClient, 'sessionFromPrekey').mockResolvedValue(undefined);
|
|
149
|
+
jest.spyOn(cryptoClient, 'saveSession').mockResolvedValue(undefined);
|
|
150
|
+
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(false);
|
|
146
151
|
const result = await proteusService.getRemoteFingerprint(userId, clientId);
|
|
147
|
-
expect(getPrekeyMock).toHaveBeenCalledWith(userId, clientId);
|
|
148
152
|
expect(result).toBe(expectedFingerprint);
|
|
149
153
|
});
|
|
150
154
|
it('create a session from given prekey if session does not exists', async () => {
|
|
151
|
-
const [proteusService, { apiClient,
|
|
155
|
+
const [proteusService, { apiClient, cryptoClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
152
156
|
const expectedFingerprint = 'fingerprint-client1';
|
|
153
157
|
const getPrekeyMock = jest.spyOn(apiClient.api.user, 'getClientPreKey');
|
|
154
|
-
jest.spyOn(
|
|
155
|
-
jest.spyOn(
|
|
158
|
+
jest.spyOn(cryptoClient, 'getRemoteFingerprint').mockResolvedValue(expectedFingerprint);
|
|
159
|
+
jest.spyOn(cryptoClient, 'sessionFromPrekey').mockResolvedValue(undefined);
|
|
160
|
+
jest.spyOn(cryptoClient, 'saveSession').mockResolvedValue(undefined);
|
|
161
|
+
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(false);
|
|
156
162
|
const userId = { id: 'user1', domain: 'domain.com' };
|
|
157
163
|
const clientId = 'client1';
|
|
158
164
|
const result = await proteusService.getRemoteFingerprint(userId, clientId, {
|
|
@@ -163,12 +169,12 @@ describe('ProteusService', () => {
|
|
|
163
169
|
expect(result).toBe(expectedFingerprint);
|
|
164
170
|
});
|
|
165
171
|
it('returns the fingerprint from existing session', async () => {
|
|
166
|
-
const [proteusService, { apiClient,
|
|
172
|
+
const [proteusService, { apiClient, cryptoClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
167
173
|
const expectedFingerprint = 'fingerprint-client1';
|
|
168
174
|
const getPrekeyMock = jest.spyOn(apiClient.api.user, 'getClientPreKey');
|
|
169
|
-
const sessionFromPrekeyMock = jest.spyOn(
|
|
170
|
-
jest.spyOn(
|
|
171
|
-
jest.spyOn(
|
|
175
|
+
const sessionFromPrekeyMock = jest.spyOn(cryptoClient, 'sessionFromPrekey');
|
|
176
|
+
jest.spyOn(cryptoClient, 'getRemoteFingerprint').mockResolvedValue(expectedFingerprint);
|
|
177
|
+
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(true);
|
|
172
178
|
const userId = { id: 'user1', domain: 'domain.com' };
|
|
173
179
|
const clientId = 'client1';
|
|
174
180
|
const result = await proteusService.getRemoteFingerprint(userId, clientId);
|
|
@@ -188,9 +194,10 @@ describe('ProteusService', () => {
|
|
|
188
194
|
};
|
|
189
195
|
const decryptedMessage = {};
|
|
190
196
|
it('decrypts incoming proteus encrypted events when session already exists', async () => {
|
|
191
|
-
const [proteusService, {
|
|
192
|
-
jest.spyOn(
|
|
193
|
-
const createSessionSpy = jest.spyOn(
|
|
197
|
+
const [proteusService, { cryptoClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
198
|
+
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(true);
|
|
199
|
+
const createSessionSpy = jest.spyOn(cryptoClient, 'sessionFromMessage');
|
|
200
|
+
jest.spyOn(cryptoClient, 'decrypt').mockResolvedValue(new Uint8Array());
|
|
194
201
|
jest.spyOn(protocol_messaging_1.GenericMessage, 'decode').mockReturnValue(decryptedMessage);
|
|
195
202
|
const result = await proteusService.handleEvent(eventPayload);
|
|
196
203
|
expect(result).toBeDefined();
|
|
@@ -198,10 +205,11 @@ describe('ProteusService', () => {
|
|
|
198
205
|
expect(result === null || result === void 0 ? void 0 : result.decryptedData).toBe(decryptedMessage);
|
|
199
206
|
});
|
|
200
207
|
it('decrypts incoming proteus encrypted and creates session if not already existing', async () => {
|
|
201
|
-
const [proteusService, {
|
|
202
|
-
jest.spyOn(
|
|
203
|
-
|
|
204
|
-
const
|
|
208
|
+
const [proteusService, { cryptoClient }] = await (0, ProteusService_mocks_1.buildProteusService)();
|
|
209
|
+
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(false);
|
|
210
|
+
jest.spyOn(cryptoClient, 'saveSession').mockResolvedValue(undefined);
|
|
211
|
+
const createSessionSpy = jest.spyOn(cryptoClient, 'sessionFromMessage').mockResolvedValue(new Uint8Array());
|
|
212
|
+
const decryptSpy = jest.spyOn(cryptoClient, 'decrypt');
|
|
205
213
|
jest.spyOn(protocol_messaging_1.GenericMessage, 'decode').mockReturnValue(decryptedMessage);
|
|
206
214
|
const result = await proteusService.handleEvent(eventPayload);
|
|
207
215
|
expect(result).toBeDefined();
|
|
@@ -212,28 +220,18 @@ describe('ProteusService', () => {
|
|
|
212
220
|
});
|
|
213
221
|
describe('"encrypt"', () => {
|
|
214
222
|
it('returns encrypted payload', async () => {
|
|
215
|
-
const { services, data: { firstUser,
|
|
223
|
+
const { services, data: { firstUser, encryptedMessageBuffer, messageBuffer }, } = await prepareDataForEncryption(false);
|
|
216
224
|
const userClients = {
|
|
217
225
|
[firstUser.id]: [firstUser.clients.first, firstUser.clients.second],
|
|
218
226
|
};
|
|
219
|
-
const preKeyBundleMap = {
|
|
220
|
-
[firstUser.id]: {
|
|
221
|
-
[firstUser.clients.first]: validPreKey,
|
|
222
|
-
[firstUser.clients.second]: validPreKey,
|
|
223
|
-
},
|
|
224
|
-
};
|
|
225
227
|
const encryptedPayload = new Map([
|
|
226
228
|
[firstUser.sessions.first, encryptedMessageBuffer],
|
|
227
229
|
[firstUser.sessions.second, encryptedMessageBuffer],
|
|
228
230
|
]);
|
|
229
|
-
jest
|
|
230
|
-
|
|
231
|
-
.mockImplementationOnce(() => Promise.resolve(preKeyBundleMap));
|
|
232
|
-
jest
|
|
233
|
-
.spyOn(services.coreCryptoClient, 'proteusEncryptBatched')
|
|
234
|
-
.mockImplementationOnce(() => Promise.resolve(encryptedPayload));
|
|
231
|
+
jest.spyOn(services.cryptoClient, 'sessionExists').mockResolvedValue(true);
|
|
232
|
+
jest.spyOn(services.cryptoClient, 'encrypt').mockImplementationOnce(() => Promise.resolve(encryptedPayload));
|
|
235
233
|
const encrypted = await services.proteusService.encrypt(messageBuffer, userClients);
|
|
236
|
-
expect(services.
|
|
234
|
+
expect(services.cryptoClient.encrypt).toHaveBeenCalledWith([firstUser.sessions.first, firstUser.sessions.second], messageBuffer);
|
|
237
235
|
expect(encrypted).toEqual({
|
|
238
236
|
[firstUser.id]: {
|
|
239
237
|
[firstUser.clients.first]: encryptedMessageBuffer,
|
|
@@ -242,33 +240,20 @@ describe('ProteusService', () => {
|
|
|
242
240
|
});
|
|
243
241
|
});
|
|
244
242
|
it('returns encrypted payload for multiple users', async () => {
|
|
245
|
-
const { services, data: { firstUser, secondUser,
|
|
243
|
+
const { services, data: { firstUser, secondUser, encryptedMessageBuffer, messageBuffer }, } = await prepareDataForEncryption(false);
|
|
246
244
|
const userClients = {
|
|
247
245
|
[firstUser.id]: [firstUser.clients.first, firstUser.clients.second],
|
|
248
246
|
[secondUser.id]: [secondUser.clients.first],
|
|
249
247
|
};
|
|
250
|
-
const preKeyBundleMap = {
|
|
251
|
-
[firstUser.id]: {
|
|
252
|
-
[firstUser.clients.first]: validPreKey,
|
|
253
|
-
[firstUser.clients.second]: null,
|
|
254
|
-
},
|
|
255
|
-
[secondUser.id]: {
|
|
256
|
-
[secondUser.clients.first]: validPreKey,
|
|
257
|
-
},
|
|
258
|
-
};
|
|
259
248
|
const encryptedPayload = new Map([
|
|
260
249
|
[firstUser.sessions.first, encryptedMessageBuffer],
|
|
261
250
|
[firstUser.sessions.second, encryptedMessageBuffer],
|
|
262
251
|
[secondUser.sessions.first, encryptedMessageBuffer],
|
|
263
252
|
]);
|
|
264
|
-
jest
|
|
265
|
-
|
|
266
|
-
.mockImplementationOnce(() => Promise.resolve(preKeyBundleMap));
|
|
267
|
-
jest
|
|
268
|
-
.spyOn(services.coreCryptoClient, 'proteusEncryptBatched')
|
|
269
|
-
.mockImplementationOnce(() => Promise.resolve(encryptedPayload));
|
|
253
|
+
jest.spyOn(services.cryptoClient, 'sessionExists').mockResolvedValue(true);
|
|
254
|
+
jest.spyOn(services.cryptoClient, 'encrypt').mockResolvedValueOnce(encryptedPayload);
|
|
270
255
|
const encrypted = await services.proteusService.encrypt(messageBuffer, userClients);
|
|
271
|
-
expect(services.
|
|
256
|
+
expect(services.cryptoClient.encrypt).toHaveBeenCalledWith([firstUser.sessions.first, firstUser.sessions.second, secondUser.sessions.first], messageBuffer);
|
|
272
257
|
expect(encrypted).toEqual({
|
|
273
258
|
[firstUser.id]: {
|
|
274
259
|
[firstUser.clients.first]: encryptedMessageBuffer,
|
|
@@ -282,33 +267,21 @@ describe('ProteusService', () => {
|
|
|
282
267
|
});
|
|
283
268
|
describe('"encryptQualified"', () => {
|
|
284
269
|
it('returns encrypted payload', async () => {
|
|
285
|
-
const { services, data: { firstUser,
|
|
270
|
+
const { services, data: { firstUser, encryptedMessageBuffer, messageBuffer, domain }, } = await prepareDataForEncryption();
|
|
286
271
|
const userClients = {
|
|
287
272
|
[domain]: {
|
|
288
273
|
[firstUser.id]: [firstUser.clients.first, firstUser.clients.second],
|
|
289
274
|
},
|
|
290
275
|
};
|
|
291
|
-
const preKeyBundleMap = {
|
|
292
|
-
[domain]: {
|
|
293
|
-
[firstUser.id]: {
|
|
294
|
-
[firstUser.clients.first]: validPreKey,
|
|
295
|
-
[firstUser.clients.second]: validPreKey,
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
};
|
|
299
276
|
const encryptedPayload = new Map([
|
|
300
277
|
[firstUser.sessions.first, encryptedMessageBuffer],
|
|
301
278
|
[firstUser.sessions.second, encryptedMessageBuffer],
|
|
302
279
|
]);
|
|
303
|
-
jest
|
|
304
|
-
|
|
305
|
-
.mockImplementationOnce(() => Promise.resolve(preKeyBundleMap));
|
|
306
|
-
jest
|
|
307
|
-
.spyOn(services.coreCryptoClient, 'proteusEncryptBatched')
|
|
308
|
-
.mockImplementationOnce(() => Promise.resolve(encryptedPayload));
|
|
280
|
+
jest.spyOn(services.cryptoClient, 'sessionExists').mockResolvedValue(true);
|
|
281
|
+
jest.spyOn(services.cryptoClient, 'encrypt').mockResolvedValueOnce(encryptedPayload);
|
|
309
282
|
const encrypted = await services.proteusService.encryptQualified(messageBuffer, userClients);
|
|
310
283
|
// console.log({encrypted, missing});
|
|
311
|
-
expect(services.
|
|
284
|
+
expect(services.cryptoClient.encrypt).toHaveBeenCalledWith([firstUser.sessions.first, firstUser.sessions.second], messageBuffer);
|
|
312
285
|
expect(encrypted).toEqual({
|
|
313
286
|
[domain]: {
|
|
314
287
|
[firstUser.id]: {
|
|
@@ -319,40 +292,27 @@ describe('ProteusService', () => {
|
|
|
319
292
|
});
|
|
320
293
|
});
|
|
321
294
|
it('returns missing clients and encrypted payload for multiple users', async () => {
|
|
322
|
-
const { services, data: { firstUser, secondUser,
|
|
295
|
+
const { services, data: { firstUser, secondUser, encryptedMessageBuffer, messageBuffer, domain }, } = await prepareDataForEncryption();
|
|
323
296
|
const userClients = {
|
|
324
297
|
[domain]: {
|
|
325
298
|
[firstUser.id]: [firstUser.clients.first, firstUser.clients.second],
|
|
326
299
|
[secondUser.id]: [secondUser.clients.first],
|
|
327
300
|
},
|
|
328
301
|
};
|
|
329
|
-
const preKeyBundleMap = {
|
|
330
|
-
[domain]: {
|
|
331
|
-
[firstUser.id]: {
|
|
332
|
-
[firstUser.clients.first]: validPreKey,
|
|
333
|
-
[firstUser.clients.second]: null,
|
|
334
|
-
},
|
|
335
|
-
[secondUser.id]: {
|
|
336
|
-
[secondUser.clients.first]: validPreKey,
|
|
337
|
-
},
|
|
338
|
-
},
|
|
339
|
-
};
|
|
340
302
|
const encryptedPayload = new Map([
|
|
341
303
|
[firstUser.sessions.first, encryptedMessageBuffer],
|
|
304
|
+
[firstUser.sessions.second, encryptedMessageBuffer],
|
|
342
305
|
[secondUser.sessions.first, encryptedMessageBuffer],
|
|
343
306
|
]);
|
|
344
|
-
jest
|
|
345
|
-
|
|
346
|
-
.mockImplementationOnce(() => Promise.resolve(preKeyBundleMap));
|
|
347
|
-
jest
|
|
348
|
-
.spyOn(services.coreCryptoClient, 'proteusEncryptBatched')
|
|
349
|
-
.mockImplementationOnce(() => Promise.resolve(encryptedPayload));
|
|
307
|
+
jest.spyOn(services.cryptoClient, 'sessionExists').mockResolvedValue(true);
|
|
308
|
+
jest.spyOn(services.cryptoClient, 'encrypt').mockResolvedValueOnce(encryptedPayload);
|
|
350
309
|
const encrypted = await services.proteusService.encryptQualified(messageBuffer, userClients);
|
|
351
|
-
expect(services.
|
|
310
|
+
expect(services.cryptoClient.encrypt).toHaveBeenCalledWith([firstUser.sessions.first, firstUser.sessions.second, secondUser.sessions.first], messageBuffer);
|
|
352
311
|
expect(encrypted).toEqual({
|
|
353
312
|
[domain]: {
|
|
354
313
|
[firstUser.id]: {
|
|
355
314
|
[firstUser.clients.first]: encryptedMessageBuffer,
|
|
315
|
+
[firstUser.clients.second]: encryptedMessageBuffer,
|
|
356
316
|
},
|
|
357
317
|
[secondUser.id]: {
|
|
358
318
|
[secondUser.clients.first]: encryptedMessageBuffer,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionHandler.d.ts","sourceRoot":"","sources":["../../../../../src/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,MAAM,EAAC,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAC,WAAW,EAAC,MAAM,sCAAsC,CAAC;AACjE,OAAO,EAAC,WAAW,EAAE,mBAAmB,EAAC,MAAM,8BAA8B,CAAC;AAE9E,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAK9C,OAAO,EAAC,YAAY,EAAC,MAAM,mCAAmC,CAAC;AAE/D,UAAU,wBAAwB;IAChC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,kBAAkB,kDAAiD,wBAAwB,KAAG,MAKnG,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionHandler.d.ts","sourceRoot":"","sources":["../../../../../src/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAC,MAAM,EAAC,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAC,WAAW,EAAC,MAAM,sCAAsC,CAAC;AACjE,OAAO,EAAC,WAAW,EAAE,mBAAmB,EAAC,MAAM,8BAA8B,CAAC;AAE9E,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAK9C,OAAO,EAAC,YAAY,EAAC,MAAM,mCAAmC,CAAC;AAE/D,UAAU,wBAAwB;IAChC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,kBAAkB,kDAAiD,wBAAwB,KAAG,MAKnG,CAAC;AAuFF;;;GAGG;AACH,QAAA,MAAM,WAAW;YAC6B,WAAW;cAAY,MAAM;;;eAClC,SAAS;kBAAgB,YAAY;MAC3E,QAAQ,MAAM,CAmBhB,CAAC;AAyBF,UAAU,wCAAwC;IAChD,UAAU,EAAE,WAAW,GAAG,mBAAmB,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,QAAA,MAAM,YAAY,6DAMf,wCAAwC,KAAG,QAAQ,MAAM,EAAE,CAgC7D,CAAC;AAEF,UAAU,mBAAmB;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;CAC1B;AACD,iBAAe,aAAa,CAAC,MAAM,EAAE,mBAAmB,iBAGvD;AA+CD,KAAK,iBAAiB,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D;;GAEG;AACH,QAAA,MAAM,sBAAsB,uDAO3B,CAAC;AAEF,OAAO,EAAC,kBAAkB,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAC,CAAC"}
|
|
@@ -43,13 +43,6 @@ const parseSessionId = (sessionId) => {
|
|
|
43
43
|
}
|
|
44
44
|
return match.groups;
|
|
45
45
|
};
|
|
46
|
-
const createSession = async ({ sessionId, initialPrekey, cryptoClient, apiClient, }) => {
|
|
47
|
-
const { userId, clientId, domain } = parseSessionId(sessionId);
|
|
48
|
-
const prekey = initialPrekey !== null && initialPrekey !== void 0 ? initialPrekey : (await apiClient.api.user.getClientPreKey({ id: userId, domain: domain !== null && domain !== void 0 ? domain : '' }, clientId)).prekey;
|
|
49
|
-
const prekeyBuffer = bazinga64_1.Decoder.fromBase64(prekey.key).asBytes;
|
|
50
|
-
await cryptoClient.sessionFromPrekey(sessionId, prekeyBuffer);
|
|
51
|
-
await cryptoClient.saveSession(sessionId);
|
|
52
|
-
};
|
|
53
46
|
const createLegacySessions = async ({ userClients, apiClient, cryptoClient, logger, }) => {
|
|
54
47
|
const preKeyBundleMap = await apiClient.api.user.postMultiPreKeyBundles(userClients);
|
|
55
48
|
const sessions = await createSessionsFromPreKeys({
|
|
@@ -87,15 +80,22 @@ const createQualifiedSessions = async ({ userClientMap, domain, apiClient, crypt
|
|
|
87
80
|
const initSession = async ({ userId, clientId, initialPrekey }, { cryptoClient, apiClient }) => {
|
|
88
81
|
const sessionId = constructSessionId({ userId, clientId, useQualifiedIds: !!userId.domain });
|
|
89
82
|
const sessionExists = await cryptoClient.sessionExists(sessionId);
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
83
|
+
if (sessionExists) {
|
|
84
|
+
return sessionId;
|
|
85
|
+
}
|
|
86
|
+
if (initialPrekey) {
|
|
87
|
+
const prekeyBuffer = bazinga64_1.Decoder.fromBase64(initialPrekey.key).asBytes;
|
|
88
|
+
await cryptoClient.sessionFromPrekey(sessionId, prekeyBuffer);
|
|
89
|
+
await cryptoClient.saveSession(sessionId);
|
|
90
|
+
return sessionId;
|
|
97
91
|
}
|
|
98
|
-
|
|
92
|
+
const sessions = await initSessions({
|
|
93
|
+
recipients: { [userId.id]: [clientId] },
|
|
94
|
+
domain: userId.domain,
|
|
95
|
+
apiClient,
|
|
96
|
+
cryptoClient,
|
|
97
|
+
});
|
|
98
|
+
return sessions[0];
|
|
99
99
|
};
|
|
100
100
|
exports.initSession = initSession;
|
|
101
101
|
/**
|
|
@@ -18,10 +18,28 @@
|
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const api_client_1 = require("@wireapp/api-client");
|
|
21
22
|
const SessionHandler_1 = require("./SessionHandler");
|
|
22
|
-
|
|
23
|
-
const
|
|
23
|
+
function generatePrekeys(userId, clientIds) {
|
|
24
|
+
const clients = clientIds.reduce((prekeys, clientId, index) => {
|
|
25
|
+
return Object.assign(Object.assign({}, prekeys), { [clientId]: {
|
|
26
|
+
id: index,
|
|
27
|
+
key: 'pQABARn//wKhAFggJ1Fbpg5l6wnzKOJE+vXpRnkqUYhIvVnR5lNXEbO2o/0DoQChAFggHxZvgvtDktY/vqBcpjjo6rQnXvcNQhfwmy8AJQJKlD0E9g==',
|
|
28
|
+
} });
|
|
29
|
+
}, {});
|
|
30
|
+
return {
|
|
31
|
+
[userId.id]: Object.assign({}, clients),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
24
34
|
describe('SessionHandler', () => {
|
|
35
|
+
const cryptoClient = {
|
|
36
|
+
sessionFromMessage: jest.fn(),
|
|
37
|
+
sessionFromPrekey: jest.fn(),
|
|
38
|
+
sessionExists: jest.fn(),
|
|
39
|
+
saveSession: jest.fn(),
|
|
40
|
+
deleteSession: jest.fn(),
|
|
41
|
+
};
|
|
42
|
+
const apiClient = new api_client_1.APIClient({ urls: api_client_1.APIClient.BACKEND.STAGING });
|
|
25
43
|
describe('constructSessionId', () => {
|
|
26
44
|
describe('constructs a session ID', () => {
|
|
27
45
|
it('without a domain', () => {
|
|
@@ -66,35 +84,42 @@ describe('SessionHandler', () => {
|
|
|
66
84
|
});
|
|
67
85
|
describe('initSession', () => {
|
|
68
86
|
it('only returns sessions that already exists', async () => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
await (0, SessionHandler_1.initSession)({ userId: { id: 'user1', domain: 'domain' }, clientId: 'client1' }, { apiClient, cryptoClient: new CoreCryptoWrapper_1.CoreCryptoWrapper(coreCrypto, {}, {}) });
|
|
73
|
-
expect(sessionFromPrekeySpy).not.toHaveBeenCalled();
|
|
87
|
+
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(true);
|
|
88
|
+
await (0, SessionHandler_1.initSession)({ userId: { id: 'user1', domain: 'domain' }, clientId: 'client1' }, { apiClient, cryptoClient });
|
|
89
|
+
expect(cryptoClient.sessionFromPrekey).not.toHaveBeenCalled();
|
|
74
90
|
});
|
|
75
91
|
it('creates the session if it does not already exist', async () => {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
jest.spyOn(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
92
|
+
const userId = { id: 'user1', domain: 'domain' };
|
|
93
|
+
const clientId = 'client1';
|
|
94
|
+
jest.spyOn(cryptoClient, 'sessionExists').mockResolvedValue(false);
|
|
95
|
+
jest
|
|
96
|
+
.spyOn(apiClient.api.user, 'postQualifiedMultiPreKeyBundles')
|
|
97
|
+
.mockResolvedValue({ domain: generatePrekeys(userId, [clientId]) });
|
|
98
|
+
const sessionId = (0, SessionHandler_1.constructSessionId)({
|
|
99
|
+
userId,
|
|
100
|
+
clientId,
|
|
101
|
+
useQualifiedIds: true,
|
|
84
102
|
});
|
|
103
|
+
await (0, SessionHandler_1.initSession)({ userId, clientId }, { apiClient, cryptoClient });
|
|
104
|
+
expect(cryptoClient.sessionFromPrekey).toHaveBeenCalledWith(sessionId, expect.any(Object));
|
|
105
|
+
});
|
|
106
|
+
it('indicates the consumer if a session could not be created', async () => {
|
|
107
|
+
const userId = { id: 'user1', domain: 'domain' };
|
|
108
|
+
const clientId = 'client1';
|
|
109
|
+
jest
|
|
110
|
+
.spyOn(apiClient.api.user, 'postQualifiedMultiPreKeyBundles')
|
|
111
|
+
.mockResolvedValue({ domain: generatePrekeys(userId, [clientId]) });
|
|
85
112
|
const sessionId = (0, SessionHandler_1.constructSessionId)({
|
|
86
|
-
userId
|
|
87
|
-
clientId
|
|
113
|
+
userId,
|
|
114
|
+
clientId,
|
|
88
115
|
useQualifiedIds: true,
|
|
89
116
|
});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
expect(sessionFromPrekeySpy).toHaveBeenCalledWith(sessionId, expect.any(Object));
|
|
117
|
+
await (0, SessionHandler_1.initSession)({ userId, clientId }, { apiClient, cryptoClient });
|
|
118
|
+
expect(cryptoClient.sessionFromPrekey).toHaveBeenCalledWith(sessionId, expect.any(Object));
|
|
93
119
|
});
|
|
94
120
|
});
|
|
95
121
|
describe('initSessions', () => {
|
|
96
122
|
it('creates new sessions only for sessions that are missing', async () => {
|
|
97
|
-
const { apiClient, coreCrypto } = (await (0, ProteusService_mocks_1.buildProteusService)())[1];
|
|
98
123
|
const existingUserClients = {
|
|
99
124
|
'existing-user1': ['client1'],
|
|
100
125
|
'existing-user2': ['client1', 'client2'],
|
|
@@ -104,32 +129,15 @@ describe('SessionHandler', () => {
|
|
|
104
129
|
'missing-user2': ['client1', 'client2'],
|
|
105
130
|
};
|
|
106
131
|
jest.spyOn(apiClient.api.user, 'postQualifiedMultiPreKeyBundles').mockResolvedValue({});
|
|
107
|
-
jest.spyOn(apiClient.api.user, 'postMultiPreKeyBundles').mockResolvedValue({
|
|
108
|
-
'missing-user1': {
|
|
109
|
-
client1: {
|
|
110
|
-
id: 1,
|
|
111
|
-
key: 'pQABARn//wKhAFggJ1Fbpg5l6wnzKOJE+vXpRnkqUYhIvVnR5lNXEbO2o/0DoQChAFggHxZvgvtDktY/vqBcpjjo6rQnXvcNQhfwmy8AJQJKlD0E9g==',
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
'missing-user2': {
|
|
115
|
-
client1: {
|
|
116
|
-
id: 1,
|
|
117
|
-
key: 'pQABARn//wKhAFggJ1Fbpg5l6wnzKOJE+vXpRnkqUYhIvVnR5lNXEbO2o/0DoQChAFggHxZvgvtDktY/vqBcpjjo6rQnXvcNQhfwmy8AJQJKlD0E9g==',
|
|
118
|
-
},
|
|
119
|
-
client2: {
|
|
120
|
-
id: 1,
|
|
121
|
-
key: 'pQABARn//wKhAFggJ1Fbpg5l6wnzKOJE+vXpRnkqUYhIvVnR5lNXEbO2o/0DoQChAFggHxZvgvtDktY/vqBcpjjo6rQnXvcNQhfwmy8AJQJKlD0E9g==',
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
});
|
|
132
|
+
jest.spyOn(apiClient.api.user, 'postMultiPreKeyBundles').mockResolvedValue(Object.assign(Object.assign({}, generatePrekeys({ id: 'missing-user1', domain: '' }, ['client1'])), generatePrekeys({ id: 'missing-user2', domain: '' }, ['client1', 'client2'])));
|
|
125
133
|
jest
|
|
126
|
-
.spyOn(
|
|
134
|
+
.spyOn(cryptoClient, 'sessionExists')
|
|
127
135
|
.mockImplementation(sessionId => Promise.resolve(sessionId.includes('missing')));
|
|
128
|
-
const sessionFromPrekeySpy = jest.spyOn(
|
|
136
|
+
const sessionFromPrekeySpy = jest.spyOn(cryptoClient, 'sessionFromPrekey');
|
|
129
137
|
const sessions = await (0, SessionHandler_1.initSessions)({
|
|
130
138
|
recipients: Object.assign(Object.assign({}, existingUserClients), missingUserClients),
|
|
131
139
|
apiClient,
|
|
132
|
-
cryptoClient
|
|
140
|
+
cryptoClient,
|
|
133
141
|
});
|
|
134
142
|
expect(sessionFromPrekeySpy).toHaveBeenCalledTimes(3);
|
|
135
143
|
expect(sessions).toHaveLength(6);
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"./lib/cryptography/AssetCryptography/crypto.node": "./lib/cryptography/AssetCryptography/crypto.browser.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@wireapp/api-client": "^22.15.
|
|
14
|
+
"@wireapp/api-client": "^22.15.1",
|
|
15
15
|
"@wireapp/commons": "^5.0.4",
|
|
16
16
|
"@wireapp/core-crypto": "0.6.0-rc.3",
|
|
17
17
|
"@wireapp/cryptobox": "12.8.0",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@wireapp/protocol-messaging": "1.44.0",
|
|
20
20
|
"@wireapp/store-engine": "5.0.3",
|
|
21
21
|
"@wireapp/store-engine-dexie": "^2.0.5",
|
|
22
|
-
"axios": "1.
|
|
22
|
+
"axios": "1.3.0",
|
|
23
23
|
"bazinga64": "6.0.3",
|
|
24
24
|
"hash.js": "1.1.7",
|
|
25
25
|
"http-status-codes": "2.2.0",
|
|
@@ -60,6 +60,6 @@
|
|
|
60
60
|
"test:coverage": "jest --coverage",
|
|
61
61
|
"watch": "tsc --watch"
|
|
62
62
|
},
|
|
63
|
-
"version": "38.8.
|
|
64
|
-
"gitHead": "
|
|
63
|
+
"version": "38.8.3",
|
|
64
|
+
"gitHead": "b37fb8e63a6d258cf0aed3be478fc5411f9bd6fe"
|
|
65
65
|
}
|