@wireapp/core 46.46.6-beta.10.d7a6c4c53 → 46.46.6-beta.14.f6fd03fe6
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/Account.d.ts +51 -168
- package/lib/Account.d.ts.map +1 -1
- package/lib/Account.js +127 -517
- package/lib/Account.test.js +147 -158
- package/lib/broadcast/AvailabilityType.d.ts +1 -1
- package/lib/broadcast/AvailabilityType.d.ts.map +1 -1
- package/lib/broadcast/BroadcastService.d.ts +1 -1
- package/lib/broadcast/BroadcastService.d.ts.map +1 -1
- package/lib/broadcast/BroadcastService.js +1 -1
- package/lib/client/ClientService.d.ts +3 -4
- package/lib/client/ClientService.d.ts.map +1 -1
- package/lib/client/ClientService.js +5 -19
- package/lib/conversation/AbortReason.d.ts +1 -1
- package/lib/conversation/AbortReason.d.ts.map +1 -1
- package/lib/conversation/AssetService/AssetService.d.ts +30 -12
- package/lib/conversation/AssetService/AssetService.d.ts.map +1 -1
- package/lib/conversation/AssetService/AssetService.js +10 -1
- package/lib/conversation/AssetService/AssetService.test.js +3 -8
- package/lib/conversation/ClientActionType.d.ts +1 -1
- package/lib/conversation/ClientActionType.d.ts.map +1 -1
- package/lib/conversation/ClientActionType.js +1 -1
- package/lib/conversation/ConversationService/ConversationService.d.ts +14 -98
- package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.js +101 -314
- package/lib/conversation/ConversationService/ConversationService.test.js +47 -441
- package/lib/conversation/ConversationService/ConversationService.types.d.ts +4 -5
- package/lib/conversation/ConversationService/ConversationService.types.d.ts.map +1 -1
- package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.d.ts.map +1 -1
- package/lib/conversation/ConversationService/Utility/getConversationQualifiedMembers.js +3 -6
- package/lib/conversation/SubconversationService/SubconversationService.d.ts.map +1 -1
- package/lib/conversation/SubconversationService/SubconversationService.js +11 -158
- package/lib/conversation/SubconversationService/SubconversationService.test.js +2 -8
- package/lib/conversation/content/AssetContent.d.ts +1 -1
- package/lib/conversation/content/AssetContent.d.ts.map +1 -1
- package/lib/conversation/content/ButtonActionConfirmationContent.d.ts +1 -1
- package/lib/conversation/content/ButtonActionConfirmationContent.d.ts.map +1 -1
- package/lib/conversation/content/ButtonActionContent.d.ts +1 -1
- package/lib/conversation/content/ButtonActionContent.d.ts.map +1 -1
- package/lib/conversation/content/ClearedContent.d.ts +1 -1
- package/lib/conversation/content/ClearedContent.d.ts.map +1 -1
- package/lib/conversation/content/ClientActionContent.d.ts +1 -1
- package/lib/conversation/content/ClientActionContent.d.ts.map +1 -1
- package/lib/conversation/content/CompositeContent.d.ts +1 -1
- package/lib/conversation/content/CompositeContent.d.ts.map +1 -1
- package/lib/conversation/content/ConfirmationContent.d.ts +1 -1
- package/lib/conversation/content/ConfirmationContent.d.ts.map +1 -1
- package/lib/conversation/content/DeletedContent.d.ts +1 -1
- package/lib/conversation/content/DeletedContent.d.ts.map +1 -1
- package/lib/conversation/content/HiddenContent.d.ts +1 -1
- package/lib/conversation/content/HiddenContent.d.ts.map +1 -1
- package/lib/conversation/content/KnockContent.d.ts +1 -1
- package/lib/conversation/content/KnockContent.d.ts.map +1 -1
- package/lib/conversation/content/LinkPreviewContent.d.ts +1 -1
- package/lib/conversation/content/LinkPreviewContent.d.ts.map +1 -1
- package/lib/conversation/content/MentionContent.d.ts +1 -1
- package/lib/conversation/content/MentionContent.d.ts.map +1 -1
- package/lib/conversation/content/MultipartContent.d.ts +1 -1
- package/lib/conversation/content/MultipartContent.d.ts.map +1 -1
- package/lib/conversation/content/QuoteContent.d.ts +1 -1
- package/lib/conversation/content/QuoteContent.d.ts.map +1 -1
- package/lib/conversation/content/TweetContent.d.ts +1 -1
- package/lib/conversation/content/TweetContent.d.ts.map +1 -1
- package/lib/conversation/content/index.d.ts +1 -1
- package/lib/conversation/content/index.d.ts.map +1 -1
- package/lib/conversation/content/index.js +1 -1
- package/lib/conversation/message/MessageBuilder.d.ts +1 -1
- package/lib/conversation/message/MessageBuilder.d.ts.map +1 -1
- package/lib/conversation/message/MessageBuilder.js +1 -1
- package/lib/conversation/message/MessageService.d.ts.map +1 -1
- package/lib/conversation/message/MessageService.js +1 -1
- package/lib/conversation/message/MessageService.test.js +1 -7
- package/lib/conversation/message/MessageToProtoMapper.d.ts +1 -1
- package/lib/conversation/message/MessageToProtoMapper.d.ts.map +1 -1
- package/lib/conversation/message/MessageToProtoMapper.js +1 -1
- package/lib/conversation/message/messageSender.js +2 -2
- package/lib/cryptography/AssetCryptography/EncryptedAsset.d.ts +2 -2
- package/lib/cryptography/AssetCryptography/EncryptedAsset.d.ts.map +1 -1
- package/lib/messagingProtocols/common.types.d.ts +0 -9
- package/lib/messagingProtocols/common.types.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.d.ts +2 -2
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIService.types.js +1 -2
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.d.ts +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.js +11 -13
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.test.js +16 -21
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts +3 -9
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.js +12 -31
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts +0 -6
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.js +1 -19
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts +4 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.js +69 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/index.d.ts +2 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingProposalsQueue → IncomingMessagesQueue}/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingProposalsQueue → IncomingMessagesQueue}/index.js +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts +1 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.js +1 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +14 -23
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts +2 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.js +98 -0
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.js +2 -5
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.test.js +3 -13
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts +2 -38
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.js +6 -41
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +34 -38
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.js +208 -267
- package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +160 -157
- package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.js +3 -3
- package/lib/messagingProtocols/mls/MLSService/commitBundleUtil.test.js +5 -5
- package/lib/messagingProtocols/mls/conversationRejoinQueue.js +2 -2
- package/lib/messagingProtocols/mls/types.d.ts +8 -0
- package/lib/messagingProtocols/mls/types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/EventHandler/events/otrMessageAdd/otrMessageAdd.js +1 -7
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts +15 -8
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.js +62 -97
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts +6 -0
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts +6 -1
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.js +22 -19
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +3 -5
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +24 -11
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts +0 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.js +2 -11
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +9 -13
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts +2 -3
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/WithMockedGenerics.test.js +4 -11
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts +4 -0
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.js +5 -0
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts +1 -2
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.js +2 -8
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +0 -4
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts +1 -1
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/Utility/getGenericMessageParams.js +1 -1
- package/lib/notification/NotificationService.d.ts +6 -20
- package/lib/notification/NotificationService.d.ts.map +1 -1
- package/lib/notification/NotificationService.js +14 -23
- package/lib/notification/NotificationService.test.js +0 -8
- package/lib/secretStore/secretKeyGenerator.d.ts +0 -1
- package/lib/secretStore/secretKeyGenerator.d.ts.map +1 -1
- package/lib/secretStore/secretKeyGenerator.js +1 -3
- package/lib/self/SelfService.d.ts +2 -2
- package/lib/self/SelfService.d.ts.map +1 -1
- package/lib/self/SelfService.test.js +2 -5
- package/lib/team/TeamService.d.ts +2 -5
- package/lib/team/TeamService.d.ts.map +1 -1
- package/lib/team/TeamService.js +2 -12
- package/lib/user/UserService.d.ts +2 -2
- package/lib/user/UserService.d.ts.map +1 -1
- package/lib/user/UserService.js +3 -3
- package/lib/util/TypePredicateUtil.d.ts.map +1 -1
- package/lib/util/TypePredicateUtil.js +2 -2
- package/package.json +3 -3
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts +0 -7
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.js +0 -48
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/index.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.js +0 -124
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts +0 -78
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.js +0 -173
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.js +0 -117
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts +0 -167
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.js +0 -317
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.js +0 -248
- package/lib/messagingProtocols/mls/recovery/index.d.ts +0 -5
- package/lib/messagingProtocols/mls/recovery/index.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/recovery/index.js +0 -28
- package/lib/test/StoreHelper.d.ts +0 -2
- package/lib/test/StoreHelper.d.ts.map +0 -1
- package/lib/test/StoreHelper.js +0 -27
|
@@ -18,20 +18,24 @@
|
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.MLSService = exports.
|
|
22
|
-
const
|
|
21
|
+
exports.MLSService = exports.optionalToUint8Array = void 0;
|
|
22
|
+
const http_1 = require("@wireapp/api-client/lib/http");
|
|
23
|
+
const TimeUtil_1 = require("@wireapp/commons/lib/util/TimeUtil");
|
|
23
24
|
const bazinga64_1 = require("bazinga64");
|
|
24
25
|
const commons_1 = require("@wireapp/commons");
|
|
25
26
|
const core_crypto_1 = require("@wireapp/core-crypto");
|
|
27
|
+
const priority_queue_1 = require("@wireapp/priority-queue");
|
|
26
28
|
const ClientMLSError_1 = require("./ClientMLSError");
|
|
27
29
|
const CoreCryptoMLSError_1 = require("./CoreCryptoMLSError");
|
|
28
|
-
const
|
|
30
|
+
const conversation_1 = require("../../../conversation");
|
|
31
|
+
const messageSender_1 = require("../../../conversation/message/messageSender");
|
|
29
32
|
const fullyQualifiedClientIdUtils_1 = require("../../../util/fullyQualifiedClientIdUtils");
|
|
30
33
|
const numberToHex_1 = require("../../../util/numberToHex");
|
|
31
34
|
const TaskScheduler_1 = require("../../../util/TaskScheduler");
|
|
32
35
|
const E2EIServiceInternal_1 = require("../E2EIdentityService/E2EIServiceInternal");
|
|
33
36
|
const Helper_1 = require("../E2EIdentityService/Helper");
|
|
34
37
|
const events_1 = require("../EventHandler/events");
|
|
38
|
+
const messageAdd_1 = require("../EventHandler/events/messageAdd");
|
|
35
39
|
const MLSId_1 = require("../utils/MLSId");
|
|
36
40
|
//@todo: this function is temporary, we wait for the update from core-crypto side
|
|
37
41
|
//they are returning regular array instead of Uint8Array for commit and welcome messages
|
|
@@ -40,17 +44,9 @@ const optionalToUint8Array = (array) => {
|
|
|
40
44
|
};
|
|
41
45
|
exports.optionalToUint8Array = optionalToUint8Array;
|
|
42
46
|
const defaultConfig = {
|
|
43
|
-
keyingMaterialUpdateThreshold:
|
|
47
|
+
keyingMaterialUpdateThreshold: 1000 * 60 * 60 * 24 * 30, //30 days
|
|
44
48
|
nbKeyPackages: 100,
|
|
45
49
|
};
|
|
46
|
-
var MLSServiceEvents;
|
|
47
|
-
(function (MLSServiceEvents) {
|
|
48
|
-
MLSServiceEvents["NEW_EPOCH"] = "newEpoch";
|
|
49
|
-
MLSServiceEvents["MLS_CLIENT_MISMATCH"] = "mlsClientMismatch";
|
|
50
|
-
MLSServiceEvents["NEW_CRL_DISTRIBUTION_POINTS"] = "newCrlDistributionPoints";
|
|
51
|
-
MLSServiceEvents["MLS_EVENT_DISTRIBUTED"] = "mlsEventDistributed";
|
|
52
|
-
MLSServiceEvents["KEY_MATERIAL_UPDATE_FAILURE"] = "keyMaterialUpdateFailure";
|
|
53
|
-
})(MLSServiceEvents || (exports.MLSServiceEvents = MLSServiceEvents = {}));
|
|
54
50
|
class MLSService extends commons_1.TypedEventEmitter {
|
|
55
51
|
apiClient;
|
|
56
52
|
coreCryptoClient;
|
|
@@ -60,31 +56,18 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
60
56
|
_config;
|
|
61
57
|
textEncoder = new TextEncoder();
|
|
62
58
|
textDecoder = new TextDecoder();
|
|
59
|
+
conflictBackoffQueue = new priority_queue_1.PriorityQueue({
|
|
60
|
+
maxRetries: 10,
|
|
61
|
+
retryDelay: 500,
|
|
62
|
+
maxRetryDelay: TimeUtil_1.TimeInMillis.SECOND * 32,
|
|
63
|
+
shouldRetry: error => error instanceof http_1.BackendError && error.code === http_1.StatusCode.CONFLICT,
|
|
64
|
+
});
|
|
63
65
|
constructor(apiClient, coreCryptoClient, coreDatabase, recurringTaskScheduler) {
|
|
64
66
|
super();
|
|
65
67
|
this.apiClient = apiClient;
|
|
66
68
|
this.coreCryptoClient = coreCryptoClient;
|
|
67
69
|
this.coreDatabase = coreDatabase;
|
|
68
70
|
this.recurringTaskScheduler = recurringTaskScheduler;
|
|
69
|
-
const mlsTransport = {
|
|
70
|
-
sendCommitBundle: this._uploadCommitBundle,
|
|
71
|
-
// Info: This is not used for now, but we need to implement it to be able to use the mls transport
|
|
72
|
-
sendMessage: async () => {
|
|
73
|
-
return 'success';
|
|
74
|
-
},
|
|
75
|
-
prepareForTransport: async () => {
|
|
76
|
-
throw new Error('Method not implemented.');
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
const epochObserver = {
|
|
80
|
-
epochChanged: async (groupId, epoch) => {
|
|
81
|
-
const groupIdStr = bazinga64_1.Encoder.toBase64(groupId.copyBytes()).asString;
|
|
82
|
-
this.logger.info(`Epoch changed for group ${groupIdStr}, new epoch: ${epoch}`);
|
|
83
|
-
this.emit(MLSServiceEvents.NEW_EPOCH, { epoch, groupId: groupIdStr });
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
void this.coreCryptoClient.registerEpochObserver(epochObserver);
|
|
87
|
-
void this.coreCryptoClient.provideTransport(mlsTransport);
|
|
88
71
|
}
|
|
89
72
|
/**
|
|
90
73
|
* return true if the MLS service if configured and ready to be used
|
|
@@ -114,39 +97,24 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
114
97
|
...defaultConfig,
|
|
115
98
|
...filteredMLSConfig,
|
|
116
99
|
};
|
|
117
|
-
await this.coreCryptoClient.
|
|
118
|
-
|
|
119
|
-
|
|
100
|
+
await this.coreCryptoClient.mlsInit((0, MLSId_1.generateMLSDeviceId)(userId, client.id), this.config.ciphersuites, this.config.nbKeyPackages);
|
|
101
|
+
await this.coreCryptoClient.registerCallbacks({
|
|
102
|
+
// All authorization/membership rules are enforced on backend
|
|
103
|
+
clientIsExistingGroupUser: async () => true,
|
|
104
|
+
authorize: async () => true,
|
|
105
|
+
userAuthorize: async () => true,
|
|
120
106
|
});
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
await this.verifyRemoteMLSKeyPackagesAmount(client.id);
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
|
|
131
|
-
}
|
|
132
|
-
break;
|
|
133
|
-
case Helper_1.MLSDeviceStatus.MISMATCH:
|
|
134
|
-
this.logger.error(`Client ${client.id} is registered but with a different signature`);
|
|
135
|
-
this.emit(MLSServiceEvents.MLS_CLIENT_MISMATCH);
|
|
136
|
-
break;
|
|
137
|
-
case Helper_1.MLSDeviceStatus.FRESH:
|
|
138
|
-
if (!skipInitIdentity) {
|
|
139
|
-
await this.uploadMLSPublicKeys(client);
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
|
|
143
|
-
}
|
|
144
|
-
break;
|
|
107
|
+
const isFreshMLSSelfClient = !this.isInitializedMLSClient(client);
|
|
108
|
+
const shouldinitIdentity = !(isFreshMLSSelfClient && skipInitIdentity);
|
|
109
|
+
if (shouldinitIdentity) {
|
|
110
|
+
// We need to make sure keypackages and public key are uploaded to the backend
|
|
111
|
+
if (isFreshMLSSelfClient) {
|
|
112
|
+
await this.uploadMLSPublicKeys(client);
|
|
145
113
|
}
|
|
114
|
+
await this.verifyRemoteMLSKeyPackagesAmount(client.id);
|
|
146
115
|
}
|
|
147
|
-
|
|
148
|
-
this.logger.
|
|
149
|
-
throw error;
|
|
116
|
+
else {
|
|
117
|
+
this.logger.info(`Blocked initial key package upload for client ${client.id} as E2EI is enabled`);
|
|
150
118
|
}
|
|
151
119
|
}
|
|
152
120
|
/**
|
|
@@ -159,62 +127,46 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
159
127
|
? core_crypto_1.CredentialType.X509
|
|
160
128
|
: core_crypto_1.CredentialType.Basic;
|
|
161
129
|
}
|
|
162
|
-
|
|
163
|
-
const bundlePayload = new Uint8Array([
|
|
164
|
-
...commit,
|
|
165
|
-
...groupInfo.payload.copyBytes(),
|
|
166
|
-
...(welcome?.copyBytes() || []),
|
|
167
|
-
]);
|
|
130
|
+
uploadCommitBundle = async (groupId, commitBundle, { isExternalCommit = false, regenerateCommitBundle } = {}) => {
|
|
168
131
|
try {
|
|
169
|
-
|
|
170
|
-
if (response.failed_to_send) {
|
|
171
|
-
this.logger.warn(`Failed to send commit bundle to backend`);
|
|
172
|
-
return 'retry';
|
|
173
|
-
}
|
|
174
|
-
const { events, time } = response;
|
|
175
|
-
this.emit(MLSServiceEvents.MLS_EVENT_DISTRIBUTED, { events, time });
|
|
176
|
-
return 'success';
|
|
132
|
+
return await this._uploadCommitBundle(groupId, async () => commitBundle, isExternalCommit);
|
|
177
133
|
}
|
|
178
134
|
catch (error) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
this.logger.info('Aborting commit bundle upload due to broken MLS conversation');
|
|
182
|
-
return {
|
|
183
|
-
abort: {
|
|
184
|
-
reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
|
|
185
|
-
message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.BROKEN_MLS_CONVERSATION,
|
|
186
|
-
}),
|
|
187
|
-
},
|
|
188
|
-
};
|
|
135
|
+
if (error instanceof http_1.BackendError && error.code === http_1.StatusCode.CONFLICT && regenerateCommitBundle) {
|
|
136
|
+
return this.conflictBackoffQueue.add(async () => this._uploadCommitBundle(groupId, regenerateCommitBundle, isExternalCommit));
|
|
189
137
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
_uploadCommitBundle = async (groupId, generateCommitBundle, isExternalCommit) => {
|
|
142
|
+
const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
|
|
143
|
+
// We need to lock the incoming mls messages queue while we are uploading the commit bundle
|
|
144
|
+
// it's possible that we will be sent some mls messages before we receive the response from backend and accept a commit locally.
|
|
145
|
+
return (0, messageAdd_1.withLockedMLSMessagesQueue)(groupIdStr, async () => {
|
|
146
|
+
const { commit, groupInfo, welcome } = await generateCommitBundle();
|
|
147
|
+
const bundlePayload = new Uint8Array([...commit, ...groupInfo.payload, ...(welcome || [])]);
|
|
148
|
+
try {
|
|
149
|
+
const response = await this.apiClient.api.conversation.postMlsCommitBundle(bundlePayload);
|
|
150
|
+
if (isExternalCommit) {
|
|
151
|
+
await this.coreCryptoClient.mergePendingGroupFromExternalCommit(groupId);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
await this.coreCryptoClient.commitAccepted(groupId);
|
|
155
|
+
}
|
|
156
|
+
const newEpoch = await this.getEpoch(groupId);
|
|
157
|
+
this.emit('newEpoch', { epoch: newEpoch, groupId: groupIdStr });
|
|
158
|
+
return response;
|
|
197
159
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
},
|
|
207
|
-
};
|
|
160
|
+
catch (error) {
|
|
161
|
+
if (isExternalCommit) {
|
|
162
|
+
await this.coreCryptoClient.clearPendingGroupFromExternalCommit(groupId);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
await this.coreCryptoClient.clearPendingCommit(groupId);
|
|
166
|
+
}
|
|
167
|
+
throw error;
|
|
208
168
|
}
|
|
209
|
-
|
|
210
|
-
return {
|
|
211
|
-
abort: {
|
|
212
|
-
reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
|
|
213
|
-
message: error instanceof Error ? error.message : CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.OTHER,
|
|
214
|
-
}),
|
|
215
|
-
},
|
|
216
|
-
};
|
|
217
|
-
}
|
|
169
|
+
});
|
|
218
170
|
};
|
|
219
171
|
/**
|
|
220
172
|
* Will add users to an existing MLS group and send a commit bundle to backend.
|
|
@@ -228,26 +180,25 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
228
180
|
if (keyPackages.length < 1) {
|
|
229
181
|
throw new Error('Empty list of keys provided to addUsersToExistingConversation');
|
|
230
182
|
}
|
|
231
|
-
|
|
232
|
-
this.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
return currentClientIdsInGroup;
|
|
183
|
+
//TODO: handle federation error when sending a commit bundle to backend like we do in ProteusService
|
|
184
|
+
const response = await this.processCommitAction(groupIdBytes, async () => {
|
|
185
|
+
const commitBundle = await this.coreCryptoClient.addClientsToConversation(groupIdBytes, keyPackages);
|
|
186
|
+
this.dispatchNewCrlDistributionPoints(commitBundle);
|
|
187
|
+
return commitBundle;
|
|
188
|
+
});
|
|
189
|
+
const failedUsers = response.failed;
|
|
190
|
+
const failures = failedUsers
|
|
191
|
+
? [
|
|
192
|
+
{
|
|
193
|
+
users: failedUsers,
|
|
194
|
+
backends: failedUsers.map(({ domain }) => domain),
|
|
195
|
+
reason: conversation_1.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
|
|
196
|
+
},
|
|
197
|
+
]
|
|
198
|
+
: [];
|
|
199
|
+
return { ...response, failures };
|
|
249
200
|
}
|
|
250
|
-
async getKeyPackagesPayload(qualifiedUsers
|
|
201
|
+
async getKeyPackagesPayload(qualifiedUsers) {
|
|
251
202
|
/**
|
|
252
203
|
* @note We need to fetch key packages for all the users
|
|
253
204
|
* we want to add to the new MLS conversations,
|
|
@@ -287,20 +238,18 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
287
238
|
if (key_packages.length > 0) {
|
|
288
239
|
return [
|
|
289
240
|
...previousValue,
|
|
290
|
-
...key_packages
|
|
291
|
-
.filter(keyPackage => !skipClientIds.includes(keyPackage.client))
|
|
292
|
-
.map(keyPackage => bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes),
|
|
241
|
+
...key_packages.map(keyPackage => bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes),
|
|
293
242
|
];
|
|
294
243
|
}
|
|
295
244
|
return previousValue;
|
|
296
245
|
}, []);
|
|
297
246
|
const failures = [];
|
|
298
247
|
if (emptyKeyPackagesUsers.length > 0) {
|
|
299
|
-
failures.push({ reason:
|
|
248
|
+
failures.push({ reason: conversation_1.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG, users: emptyKeyPackagesUsers });
|
|
300
249
|
}
|
|
301
250
|
if (failedToFetchKeyPackages.length > 0) {
|
|
302
251
|
failures.push({
|
|
303
|
-
reason:
|
|
252
|
+
reason: conversation_1.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
|
|
304
253
|
users: failedToFetchKeyPackages,
|
|
305
254
|
backends: failedToFetchKeyPackages.map(({ domain }) => domain),
|
|
306
255
|
});
|
|
@@ -309,98 +258,92 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
309
258
|
}
|
|
310
259
|
getEpoch(groupId) {
|
|
311
260
|
const groupIdBytes = typeof groupId === 'string' ? bazinga64_1.Decoder.fromBase64(groupId).asBytes : groupId;
|
|
312
|
-
return this.coreCryptoClient.conversationEpoch(
|
|
261
|
+
return this.coreCryptoClient.conversationEpoch(groupIdBytes);
|
|
262
|
+
}
|
|
263
|
+
async newProposal(proposalType, args) {
|
|
264
|
+
return this.coreCryptoClient.newProposal(proposalType, args);
|
|
313
265
|
}
|
|
314
266
|
async joinByExternalCommit(getGroupInfo) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const credentialType = await this.getCredentialType();
|
|
267
|
+
const credentialType = await this.getCredentialType();
|
|
268
|
+
const generateCommit = async () => {
|
|
318
269
|
const groupInfo = await getGroupInfo();
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
catch (error) {
|
|
334
|
-
this.logger.warn('Failed to join MLS group via external commit', error);
|
|
335
|
-
throw error;
|
|
270
|
+
const joinRequest = await this.coreCryptoClient.joinByExternalCommit(groupInfo, credentialType);
|
|
271
|
+
this.dispatchNewCrlDistributionPoints(joinRequest);
|
|
272
|
+
const { conversationId, ...commitBundle } = joinRequest;
|
|
273
|
+
return { groupId: conversationId, commitBundle };
|
|
274
|
+
};
|
|
275
|
+
const { commitBundle, groupId } = await generateCommit();
|
|
276
|
+
const mlsResponse = await this.uploadCommitBundle(groupId, commitBundle, {
|
|
277
|
+
isExternalCommit: true,
|
|
278
|
+
regenerateCommitBundle: async () => (await generateCommit()).commitBundle,
|
|
279
|
+
});
|
|
280
|
+
if (mlsResponse) {
|
|
281
|
+
//after we've successfully joined via external commit, we schedule periodic key material renewal
|
|
282
|
+
const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
|
|
283
|
+
await this.scheduleKeyMaterialRenewal(groupIdStr);
|
|
336
284
|
}
|
|
285
|
+
return mlsResponse;
|
|
337
286
|
}
|
|
338
287
|
async exportSecretKey(groupId, keyLength) {
|
|
339
288
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
340
|
-
const key = await this.coreCryptoClient.exportSecretKey(
|
|
289
|
+
const key = await this.coreCryptoClient.exportSecretKey(groupIdBytes, keyLength);
|
|
341
290
|
return bazinga64_1.Encoder.toBase64(key).asString;
|
|
342
291
|
}
|
|
343
|
-
dispatchNewCrlDistributionPoints(
|
|
292
|
+
dispatchNewCrlDistributionPoints(payload) {
|
|
293
|
+
const { crlNewDistributionPoints } = payload;
|
|
344
294
|
if (crlNewDistributionPoints && crlNewDistributionPoints.length > 0) {
|
|
345
|
-
this.emit(
|
|
295
|
+
this.emit('newCrlDistributionPoints', crlNewDistributionPoints);
|
|
346
296
|
}
|
|
347
297
|
}
|
|
348
298
|
async processWelcomeMessage(welcomeMessage) {
|
|
349
|
-
const welcomeBundle = await this.coreCryptoClient.
|
|
350
|
-
this.dispatchNewCrlDistributionPoints(welcomeBundle
|
|
299
|
+
const welcomeBundle = await this.coreCryptoClient.processWelcomeMessage(welcomeMessage);
|
|
300
|
+
this.dispatchNewCrlDistributionPoints(welcomeBundle);
|
|
351
301
|
return welcomeBundle.id;
|
|
352
302
|
}
|
|
353
303
|
async decryptMessage(conversationId, payload) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
this.logger.info('Message decrypted successfully', { conversationId, duration: Date.now() - start });
|
|
360
|
-
return decryptedMessage;
|
|
361
|
-
}
|
|
362
|
-
catch (error) {
|
|
363
|
-
this.logger.warn('Failed to decrypt MLS message', { conversationId, error });
|
|
364
|
-
// According to CoreCrypto JS doc on .decryptMessage method, we should ignore some errors (corecrypto handle them internally)
|
|
365
|
-
if ((0, CoreCryptoMLSError_1.shouldMLSDecryptionErrorBeIgnored)(error)) {
|
|
366
|
-
return {
|
|
367
|
-
hasEpochChanged: false,
|
|
368
|
-
isActive: false,
|
|
369
|
-
};
|
|
304
|
+
return await this.coreCryptoClient.transaction(async (cx) => {
|
|
305
|
+
try {
|
|
306
|
+
const decryptedMessage = await cx.decryptMessage(conversationId, payload);
|
|
307
|
+
this.dispatchNewCrlDistributionPoints(decryptedMessage);
|
|
308
|
+
return decryptedMessage;
|
|
370
309
|
}
|
|
371
|
-
|
|
372
|
-
|
|
310
|
+
catch (error) {
|
|
311
|
+
// According to CoreCrypto JS doc on .decryptMessage method, we should ignore some errors (corecrypto handle them internally)
|
|
312
|
+
if ((0, CoreCryptoMLSError_1.shouldMLSDecryptionErrorBeIgnored)(error)) {
|
|
313
|
+
return {
|
|
314
|
+
hasEpochChanged: false,
|
|
315
|
+
isActive: false,
|
|
316
|
+
proposals: [],
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
throw error;
|
|
320
|
+
}
|
|
321
|
+
});
|
|
373
322
|
}
|
|
374
323
|
async encryptMessage(conversationId, message) {
|
|
375
|
-
return this.coreCryptoClient.
|
|
324
|
+
return this.coreCryptoClient.encryptMessage(conversationId, message);
|
|
376
325
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
this.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
error,
|
|
399
|
-
groupId,
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
}, commons_1.TimeUtil.TimeInMillis.SECOND * 10); // retry after 10 seconds
|
|
403
|
-
}
|
|
326
|
+
/**
|
|
327
|
+
* Will wrap a coreCrypto call that generates a CommitBundle and do all the necessary work so that commitbundle is handled the right way.
|
|
328
|
+
* It does:
|
|
329
|
+
* - commit the pending proposal
|
|
330
|
+
* - then generates the commitBundle with the given function
|
|
331
|
+
* - uploads the commitBundle to backend
|
|
332
|
+
* - warns coreCrypto that the commit was successfully processed
|
|
333
|
+
* @param groupId
|
|
334
|
+
* @param generateCommit The function that will generate a coreCrypto CommitBundle
|
|
335
|
+
*/
|
|
336
|
+
async processCommitAction(groupId, generateCommit) {
|
|
337
|
+
const groupIdStr = bazinga64_1.Encoder.toBase64(groupId).asString;
|
|
338
|
+
return (0, messageSender_1.sendMessage)(async () => {
|
|
339
|
+
await this.commitPendingProposals(groupIdStr);
|
|
340
|
+
const commitBundle = await generateCommit();
|
|
341
|
+
return this.uploadCommitBundle(groupId, commitBundle, { regenerateCommitBundle: generateCommit });
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
updateKeyingMaterial(groupId) {
|
|
345
|
+
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
346
|
+
return this.processCommitAction(groupIdBytes, () => this.coreCryptoClient.updateKeyingMaterial(groupIdBytes));
|
|
404
347
|
}
|
|
405
348
|
/**
|
|
406
349
|
* Will create an empty conversation inside of coreCrypto.
|
|
@@ -412,9 +355,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
412
355
|
let externalSenders = [];
|
|
413
356
|
if (parentGroupId) {
|
|
414
357
|
const parentGroupIdBytes = bazinga64_1.Decoder.fromBase64(parentGroupId).asBytes;
|
|
415
|
-
externalSenders = [
|
|
416
|
-
new core_crypto_1.ExternalSenderKey(await this.coreCryptoClient.getExternalSender(new core_crypto_1.ConversationId(parentGroupIdBytes))),
|
|
417
|
-
];
|
|
358
|
+
externalSenders = [await this.coreCryptoClient.getExternalSender(parentGroupIdBytes)];
|
|
418
359
|
}
|
|
419
360
|
else {
|
|
420
361
|
const mlsKeys = (await this.apiClient.api.client.getPublicKeys()).removal;
|
|
@@ -423,14 +364,14 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
423
364
|
if (!removalKeyForSignature) {
|
|
424
365
|
throw new Error(`Cannot create conversation: No backend removal key found for the signature ${ciphersuiteSignature}`);
|
|
425
366
|
}
|
|
426
|
-
externalSenders = [
|
|
367
|
+
externalSenders = [bazinga64_1.Decoder.fromBase64(removalKeyForSignature).asBytes];
|
|
427
368
|
}
|
|
428
369
|
const configuration = {
|
|
429
370
|
externalSenders,
|
|
430
371
|
ciphersuite: this.config.defaultCiphersuite,
|
|
431
372
|
};
|
|
432
373
|
const credentialType = await this.getCredentialType();
|
|
433
|
-
return this.coreCryptoClient.
|
|
374
|
+
return this.coreCryptoClient.createConversation(groupIdBytes, credentialType, configuration);
|
|
434
375
|
}
|
|
435
376
|
/**
|
|
436
377
|
* Will create a conversation inside of coreCrypto, add users to it or update the keying material if empty key packages list is provided.
|
|
@@ -454,18 +395,19 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
454
395
|
}));
|
|
455
396
|
if (keyPackages.length <= 0) {
|
|
456
397
|
// If there are no clients to add, just update the keying material
|
|
457
|
-
await this.updateKeyingMaterial(groupId);
|
|
398
|
+
const response = await this.updateKeyingMaterial(groupId);
|
|
458
399
|
await this.scheduleKeyMaterialRenewal(groupId);
|
|
459
|
-
return keysClaimingFailures;
|
|
400
|
+
return { ...response, failures: keysClaimingFailures };
|
|
460
401
|
}
|
|
461
|
-
await this.addUsersToExistingConversation(groupId, keyPackages);
|
|
402
|
+
const response = await this.addUsersToExistingConversation(groupId, keyPackages);
|
|
462
403
|
// We schedule a periodic key material renewal
|
|
463
404
|
await this.scheduleKeyMaterialRenewal(groupId);
|
|
464
405
|
/**
|
|
465
406
|
* @note If we can't fetch a user's key packages then we can not add them to mls conversation
|
|
466
407
|
* so we're adding them to the list of failed users.
|
|
467
408
|
*/
|
|
468
|
-
|
|
409
|
+
response.failures = [...keysClaimingFailures, ...response.failures];
|
|
410
|
+
return response;
|
|
469
411
|
}
|
|
470
412
|
/**
|
|
471
413
|
* Will create a 1:1 conversation inside of coreCrypto, try claiming key packages for user and (if succesfull) add them to the MLS group.
|
|
@@ -481,17 +423,21 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
481
423
|
// If we're missing key packages for the user we want to add, we can't register the conversation
|
|
482
424
|
if (otherUserKeyPackages.length <= 0) {
|
|
483
425
|
if (otherUserKeysClaimingFailures.length > 0 &&
|
|
484
|
-
otherUserKeysClaimingFailures.some(({ reason }) => reason ===
|
|
426
|
+
otherUserKeysClaimingFailures.some(({ reason }) => reason === conversation_1.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG)) {
|
|
485
427
|
throw new ClientMLSError_1.ClientMLSError(ClientMLSError_1.ClientMLSErrorLabel.NO_KEY_PACKAGES_AVAILABLE);
|
|
486
428
|
}
|
|
487
429
|
}
|
|
488
430
|
const { keyPackages: selfKeyPackages, failures: selfKeysClaimingFailures } = await this.getKeyPackagesPayload([
|
|
489
431
|
{ ...selfUser.user, skipOwnClientId: selfUser.client },
|
|
490
432
|
]);
|
|
491
|
-
await this.addUsersToExistingConversation(groupId, [
|
|
433
|
+
const response = await this.addUsersToExistingConversation(groupId, [
|
|
434
|
+
...otherUserKeyPackages,
|
|
435
|
+
...selfKeyPackages,
|
|
436
|
+
]);
|
|
492
437
|
// We schedule a periodic key material renewal
|
|
493
438
|
await this.scheduleKeyMaterialRenewal(groupId);
|
|
494
|
-
|
|
439
|
+
response.failures = [...otherUserKeysClaimingFailures, ...selfKeysClaimingFailures, ...response.failures];
|
|
440
|
+
return response;
|
|
495
441
|
}
|
|
496
442
|
catch (error) {
|
|
497
443
|
await this.wipeConversation(groupId);
|
|
@@ -518,7 +464,6 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
518
464
|
return true;
|
|
519
465
|
}
|
|
520
466
|
catch (error) {
|
|
521
|
-
this.logger.warn("Couldn't establish the MLS group", error);
|
|
522
467
|
// If conversation already existed, locally, nothing more to do, we've received a welcome message.
|
|
523
468
|
if ((0, CoreCryptoMLSError_1.isCoreCryptoMLSConversationAlreadyExistsError)(error)) {
|
|
524
469
|
this.logger.debug(`MLS Group with id ${groupId} already exists, skipping the initialisation.`);
|
|
@@ -538,7 +483,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
538
483
|
*/
|
|
539
484
|
removeClientsFromConversation(groupId, clientIds) {
|
|
540
485
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
541
|
-
return this.
|
|
486
|
+
return this.processCommitAction(groupIdBytes, () => this.coreCryptoClient.removeClientsFromConversation(groupIdBytes, clientIds.map(id => this.textEncoder.encode(id))));
|
|
542
487
|
}
|
|
543
488
|
/**
|
|
544
489
|
* Will check if mls group exists in corecrypto.
|
|
@@ -546,7 +491,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
546
491
|
*/
|
|
547
492
|
async conversationExists(groupId) {
|
|
548
493
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
549
|
-
return this.coreCryptoClient.conversationExists(
|
|
494
|
+
return this.coreCryptoClient.conversationExists(groupIdBytes);
|
|
550
495
|
}
|
|
551
496
|
/**
|
|
552
497
|
* Will check if mls group is established in coreCrypto.
|
|
@@ -559,11 +504,11 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
559
504
|
}
|
|
560
505
|
async clientValidKeypackagesCount() {
|
|
561
506
|
const credentialType = await this.getCredentialType();
|
|
562
|
-
return this.coreCryptoClient.
|
|
507
|
+
return this.coreCryptoClient.clientValidKeypackagesCount(this.config.defaultCiphersuite, credentialType);
|
|
563
508
|
}
|
|
564
509
|
async clientKeypackages(amountRequested) {
|
|
565
510
|
const credentialType = await this.getCredentialType();
|
|
566
|
-
return this.coreCryptoClient.
|
|
511
|
+
return this.coreCryptoClient.clientKeypackages(this.config.defaultCiphersuite, credentialType, amountRequested);
|
|
567
512
|
}
|
|
568
513
|
/**
|
|
569
514
|
* Will send an empty commit into a group (renew key material)
|
|
@@ -665,14 +610,6 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
665
610
|
async getRemoteMLSKeyPackageCount(clientId) {
|
|
666
611
|
return this.apiClient.api.client.getMLSKeyPackageCount(clientId, (0, numberToHex_1.numberToHex)(this.config.defaultCiphersuite));
|
|
667
612
|
}
|
|
668
|
-
async getCCClientSignatureString() {
|
|
669
|
-
const credentialType = await this.getCredentialType();
|
|
670
|
-
const publicKey = await this.coreCryptoClient.clientPublicKey(this.config.defaultCiphersuite, credentialType);
|
|
671
|
-
if (!publicKey) {
|
|
672
|
-
throw new Error('No public key found for client');
|
|
673
|
-
}
|
|
674
|
-
return btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(publicKey));
|
|
675
|
-
}
|
|
676
613
|
/**
|
|
677
614
|
* Will update the given client on backend with its public key.
|
|
678
615
|
*
|
|
@@ -681,18 +618,13 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
681
618
|
*/
|
|
682
619
|
async uploadMLSPublicKeys(client) {
|
|
683
620
|
// If we've already updated a client with its public key, there's no need to do it again.
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
692
|
-
catch (error) {
|
|
693
|
-
this.logger.error(`Failed to upload public keys for client ${client.id}`, error);
|
|
694
|
-
throw error;
|
|
695
|
-
}
|
|
621
|
+
const credentialType = await this.getCredentialType();
|
|
622
|
+
const publicKey = await this.coreCryptoClient.clientPublicKey(this.config.defaultCiphersuite, credentialType);
|
|
623
|
+
return this.apiClient.api.client.putClient(client.id, {
|
|
624
|
+
mls_public_keys: {
|
|
625
|
+
[(0, Helper_1.getSignatureAlgorithmForCiphersuite)(this.config.defaultCiphersuite)]: btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(publicKey)),
|
|
626
|
+
},
|
|
627
|
+
});
|
|
696
628
|
}
|
|
697
629
|
async replaceKeyPackages(clientId, keyPackages) {
|
|
698
630
|
return this.apiClient.api.client.replaceMLSKeyPackages(clientId, keyPackages.map(keyPackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keyPackage))), (0, numberToHex_1.numberToHex)(this.config.defaultCiphersuite));
|
|
@@ -701,6 +633,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
701
633
|
return this.apiClient.api.client.uploadMLSKeyPackages(clientId, keyPackages.map(keyPackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keyPackage))));
|
|
702
634
|
}
|
|
703
635
|
async wipeConversation(groupId) {
|
|
636
|
+
(0, messageAdd_1.deleteMLSMessagesQueue)(groupId);
|
|
704
637
|
await this.cancelKeyMaterialRenewal(groupId);
|
|
705
638
|
await this.cancelPendingProposalsTask(groupId);
|
|
706
639
|
const doesConversationExist = await this.conversationExists(groupId);
|
|
@@ -709,7 +642,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
709
642
|
return;
|
|
710
643
|
}
|
|
711
644
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
712
|
-
return this.coreCryptoClient.
|
|
645
|
+
return this.coreCryptoClient.wipeConversation(groupIdBytes);
|
|
713
646
|
}
|
|
714
647
|
/**
|
|
715
648
|
* If there are pending proposals, we need to either process them,
|
|
@@ -749,29 +682,25 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
749
682
|
*
|
|
750
683
|
* @param groupId groupId of the conversation
|
|
751
684
|
*/
|
|
752
|
-
async commitPendingProposals(groupId, shouldRetry = true
|
|
753
|
-
this.logger.info(`Committing pending proposals for groupId ${groupId}`, { shouldRetry, params });
|
|
685
|
+
async commitPendingProposals(groupId, shouldRetry = true) {
|
|
754
686
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
755
687
|
try {
|
|
756
|
-
await this.coreCryptoClient.
|
|
688
|
+
const commitBundle = await this.coreCryptoClient.commitPendingProposals(groupIdBytes);
|
|
689
|
+
if (commitBundle) {
|
|
690
|
+
await this.uploadCommitBundle(groupIdBytes, commitBundle);
|
|
691
|
+
}
|
|
757
692
|
await this.cancelPendingProposalsTask(groupId);
|
|
758
693
|
}
|
|
759
694
|
catch (error) {
|
|
760
695
|
if (!shouldRetry) {
|
|
761
696
|
throw error;
|
|
762
697
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
}
|
|
770
|
-
this.logger.warn('Failed to commit proposals, clearing the pending commit and retrying', {
|
|
771
|
-
error,
|
|
772
|
-
groupId,
|
|
773
|
-
shouldRetry,
|
|
774
|
-
});
|
|
698
|
+
this.logger.warn('Failed to commit proposals, clearing the pending commit and retrying', error);
|
|
699
|
+
// If we failed to commit the proposals, we need to clear the pending commit and retry
|
|
700
|
+
// this is to avoid a situation where we are stuck with pending proposals that we can't commit.
|
|
701
|
+
// If there's nothing to clear the methods might throw an error, which we can ignore.
|
|
702
|
+
await this.coreCryptoClient.clearPendingCommit(groupIdBytes).catch(() => undefined);
|
|
703
|
+
await this.coreCryptoClient.clearPendingGroupFromExternalCommit(groupIdBytes).catch(() => undefined);
|
|
775
704
|
return this.commitPendingProposals(groupId, false);
|
|
776
705
|
}
|
|
777
706
|
}
|
|
@@ -802,9 +731,9 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
802
731
|
*/
|
|
803
732
|
async getClientIds(groupId) {
|
|
804
733
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
805
|
-
const rawClientIds = await this.coreCryptoClient.getClientIds(
|
|
734
|
+
const rawClientIds = await this.coreCryptoClient.getClientIds(groupIdBytes);
|
|
806
735
|
const clientIds = rawClientIds.map(id => {
|
|
807
|
-
const { user, client, domain } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(id
|
|
736
|
+
const { user, client, domain } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(id));
|
|
808
737
|
return { userId: user, clientId: client, domain };
|
|
809
738
|
});
|
|
810
739
|
return clientIds;
|
|
@@ -816,7 +745,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
816
745
|
if (!groupId) {
|
|
817
746
|
throw new Error(`Could not find a group_id for conversation ${qualifiedConversationId.id}@${qualifiedConversationId.domain}${event.subconv ? `/subconversation:${event.subconv}` : ''}`);
|
|
818
747
|
}
|
|
819
|
-
return (0, events_1.handleMLSMessageAdd)({ event, mlsService: this, groupId });
|
|
748
|
+
return (0, messageAdd_1.queueIncomingMLSMessage)(groupId, () => (0, events_1.handleMLSMessageAdd)({ event, mlsService: this, groupId }));
|
|
820
749
|
}
|
|
821
750
|
async handleMLSWelcomeMessageEvent(event, clientId) {
|
|
822
751
|
// Every time we've received a welcome message, it means that our key package was consumed,
|
|
@@ -840,20 +769,32 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
840
769
|
* @param oAuthIdToken The OAuth id token if the user is already authenticated
|
|
841
770
|
* @returns AcmeChallenge if the user is not authenticated, true if the user is authenticated
|
|
842
771
|
*/
|
|
843
|
-
async enrollE2EI(discoveryUrl, user, client, nbPrekeys, certificateTtl, getOAuthToken
|
|
772
|
+
async enrollE2EI(discoveryUrl, user, client, nbPrekeys, certificateTtl, getOAuthToken) {
|
|
844
773
|
const isCertificateRenewal = await this.coreCryptoClient.e2eiIsEnabled(this.config.defaultCiphersuite);
|
|
845
774
|
const e2eiServiceInternal = new E2EIServiceInternal_1.E2EIServiceInternal(this.coreDatabase, this.coreCryptoClient, this.apiClient, certificateTtl, nbPrekeys, { user, clientId: client.id, discoveryUrl });
|
|
846
|
-
const
|
|
847
|
-
this.dispatchNewCrlDistributionPoints(
|
|
775
|
+
const rotateBundle = await e2eiServiceInternal.generateCertificate(getOAuthToken, isCertificateRenewal, this.config.defaultCiphersuite);
|
|
776
|
+
this.dispatchNewCrlDistributionPoints(rotateBundle);
|
|
848
777
|
// upload the clients public keys
|
|
849
778
|
if (!this.isInitializedMLSClient(client)) {
|
|
850
779
|
// we only upload public keys for the initial certification process if the device is not already a registered MLS device.
|
|
851
780
|
await this.uploadMLSPublicKeys(client);
|
|
852
781
|
}
|
|
853
782
|
// replace old key packages with new key packages with x509 certificate
|
|
854
|
-
await this.replaceKeyPackages(client.id,
|
|
783
|
+
await this.replaceKeyPackages(client.id, rotateBundle.newKeyPackages);
|
|
855
784
|
// Verify that we have enough key packages
|
|
856
785
|
await this.verifyRemoteMLSKeyPackagesAmount(client.id);
|
|
786
|
+
// Update keying material
|
|
787
|
+
for (const [groupId, commitBundle] of rotateBundle.commits) {
|
|
788
|
+
const groupIdAsBytes = bazinga64_1.Converter.hexStringToArrayBufferView(groupId);
|
|
789
|
+
// manual copy of the commit bundle data because of a problem while cloning it
|
|
790
|
+
const newCommitBundle = {
|
|
791
|
+
commit: commitBundle.commit,
|
|
792
|
+
// @ts-ignore
|
|
793
|
+
groupInfo: commitBundle?.group_info || commitBundle.groupInfo,
|
|
794
|
+
welcome: commitBundle?.welcome,
|
|
795
|
+
};
|
|
796
|
+
await this.uploadCommitBundle(groupIdAsBytes, newCommitBundle);
|
|
797
|
+
}
|
|
857
798
|
}
|
|
858
799
|
}
|
|
859
800
|
exports.MLSService = MLSService;
|