@wireapp/core 46.46.6-beta.14.f6fd03fe6 → 46.46.6
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 +156 -51
- package/lib/Account.d.ts.map +1 -1
- package/lib/Account.js +503 -127
- package/lib/Account.test.js +158 -147
- 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 +4 -3
- package/lib/client/ClientService.d.ts.map +1 -1
- package/lib/client/ClientService.js +19 -5
- package/lib/conversation/AbortReason.d.ts +1 -1
- package/lib/conversation/AbortReason.d.ts.map +1 -1
- package/lib/conversation/AssetService/AssetService.d.ts +12 -30
- package/lib/conversation/AssetService/AssetService.d.ts.map +1 -1
- package/lib/conversation/AssetService/AssetService.js +1 -10
- package/lib/conversation/AssetService/AssetService.test.js +8 -3
- 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 +98 -14
- package/lib/conversation/ConversationService/ConversationService.d.ts.map +1 -1
- package/lib/conversation/ConversationService/ConversationService.js +314 -101
- package/lib/conversation/ConversationService/ConversationService.test.js +441 -47
- package/lib/conversation/ConversationService/ConversationService.types.d.ts +5 -4
- 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 +6 -3
- package/lib/conversation/SubconversationService/SubconversationService.d.ts.map +1 -1
- package/lib/conversation/SubconversationService/SubconversationService.js +158 -11
- package/lib/conversation/SubconversationService/SubconversationService.test.js +8 -2
- 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 +7 -1
- 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 +9 -0
- 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 +2 -1
- 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 +13 -11
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceExternal.test.js +21 -16
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts +9 -3
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/E2EIServiceInternal.js +31 -12
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts +6 -0
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/E2EIdentityService/Helper/index.js +19 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts +7 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/IncomingProposalsQueue.js +48 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingProposalsQueue/index.d.ts +2 -0
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingMessagesQueue → IncomingProposalsQueue}/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/{IncomingMessagesQueue → IncomingProposalsQueue}/index.js +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts +0 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/index.js +0 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.js +23 -14
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.js +5 -2
- package/lib/messagingProtocols/mls/EventHandler/events/welcomeMessage/welcomeMessage.test.js +13 -3
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts +38 -2
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.js +41 -6
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts +2 -0
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/MLSService/CoreCryptoMLSError.test.js +124 -0
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts +38 -34
- package/lib/messagingProtocols/mls/MLSService/MLSService.d.ts.map +1 -1
- package/lib/messagingProtocols/mls/MLSService/MLSService.js +267 -208
- package/lib/messagingProtocols/mls/MLSService/MLSService.test.js +157 -160
- 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/recovery/MlsErrorMapper.d.ts +78 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.js +173 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts +2 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/MlsErrorMapper.test.js +117 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts +167 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.js +317 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts +2 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/MlsRecoveryOrchestrator.test.js +248 -0
- package/lib/messagingProtocols/mls/recovery/index.d.ts +5 -0
- package/lib/messagingProtocols/mls/recovery/index.d.ts.map +1 -0
- package/lib/messagingProtocols/mls/recovery/index.js +28 -0
- package/lib/messagingProtocols/mls/types.d.ts +0 -8
- 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 +7 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts +8 -15
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CoreCryptoWrapper/CoreCryptoWrapper.js +97 -62
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts +0 -6
- package/lib/messagingProtocols/proteus/ProteusService/CryptoClient/CryptoClient.types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts +1 -6
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/DecryptionErrorGenerator/DecryptionErrorGenerator.js +19 -22
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts +5 -3
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.js +11 -24
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts +1 -0
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.mocks.js +11 -2
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.test.js +13 -9
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts +3 -2
- package/lib/messagingProtocols/proteus/ProteusService/ProteusService.types.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/WithMockedGenerics.test.js +11 -4
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts +0 -4
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/cryptoMigrationStateStore.js +0 -5
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts +2 -1
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.d.ts.map +1 -1
- package/lib/messagingProtocols/proteus/ProteusService/identityClearer.js +8 -2
- package/lib/messagingProtocols/proteus/Utility/SessionHandler/SessionHandler.test.js +4 -0
- 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 +20 -6
- package/lib/notification/NotificationService.d.ts.map +1 -1
- package/lib/notification/NotificationService.js +23 -14
- package/lib/notification/NotificationService.test.js +8 -0
- package/lib/secretStore/secretKeyGenerator.d.ts +1 -0
- package/lib/secretStore/secretKeyGenerator.d.ts.map +1 -1
- package/lib/secretStore/secretKeyGenerator.js +3 -1
- package/lib/self/SelfService.d.ts +2 -2
- package/lib/self/SelfService.d.ts.map +1 -1
- package/lib/self/SelfService.test.js +5 -2
- package/lib/team/TeamService.d.ts +5 -2
- package/lib/team/TeamService.d.ts.map +1 -1
- package/lib/team/TeamService.js +12 -2
- package/lib/test/StoreHelper.d.ts +2 -0
- package/lib/test/StoreHelper.d.ts.map +1 -0
- package/lib/test/StoreHelper.js +27 -0
- 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/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts +0 -4
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/IncomingMesssagesQueue.js +0 -69
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/IncomingMessagesQueue/index.d.ts +0 -2
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts +0 -2
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.d.ts.map +0 -1
- package/lib/messagingProtocols/mls/EventHandler/events/messageAdd/messageAdd.test.js +0 -98
|
@@ -18,24 +18,20 @@
|
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.MLSService = exports.optionalToUint8Array = void 0;
|
|
22
|
-
const
|
|
23
|
-
const TimeUtil_1 = require("@wireapp/commons/lib/util/TimeUtil");
|
|
21
|
+
exports.MLSService = exports.MLSServiceEvents = exports.optionalToUint8Array = void 0;
|
|
22
|
+
const conversation_1 = require("@wireapp/api-client/lib/conversation");
|
|
24
23
|
const bazinga64_1 = require("bazinga64");
|
|
25
24
|
const commons_1 = require("@wireapp/commons");
|
|
26
25
|
const core_crypto_1 = require("@wireapp/core-crypto");
|
|
27
|
-
const priority_queue_1 = require("@wireapp/priority-queue");
|
|
28
26
|
const ClientMLSError_1 = require("./ClientMLSError");
|
|
29
27
|
const CoreCryptoMLSError_1 = require("./CoreCryptoMLSError");
|
|
30
|
-
const
|
|
31
|
-
const messageSender_1 = require("../../../conversation/message/messageSender");
|
|
28
|
+
const conversation_2 = require("../../../conversation");
|
|
32
29
|
const fullyQualifiedClientIdUtils_1 = require("../../../util/fullyQualifiedClientIdUtils");
|
|
33
30
|
const numberToHex_1 = require("../../../util/numberToHex");
|
|
34
31
|
const TaskScheduler_1 = require("../../../util/TaskScheduler");
|
|
35
32
|
const E2EIServiceInternal_1 = require("../E2EIdentityService/E2EIServiceInternal");
|
|
36
33
|
const Helper_1 = require("../E2EIdentityService/Helper");
|
|
37
34
|
const events_1 = require("../EventHandler/events");
|
|
38
|
-
const messageAdd_1 = require("../EventHandler/events/messageAdd");
|
|
39
35
|
const MLSId_1 = require("../utils/MLSId");
|
|
40
36
|
//@todo: this function is temporary, we wait for the update from core-crypto side
|
|
41
37
|
//they are returning regular array instead of Uint8Array for commit and welcome messages
|
|
@@ -44,9 +40,17 @@ const optionalToUint8Array = (array) => {
|
|
|
44
40
|
};
|
|
45
41
|
exports.optionalToUint8Array = optionalToUint8Array;
|
|
46
42
|
const defaultConfig = {
|
|
47
|
-
keyingMaterialUpdateThreshold:
|
|
43
|
+
keyingMaterialUpdateThreshold: commons_1.TimeUtil.TimeInMillis.DAY * 30,
|
|
48
44
|
nbKeyPackages: 100,
|
|
49
45
|
};
|
|
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 = {}));
|
|
50
54
|
class MLSService extends commons_1.TypedEventEmitter {
|
|
51
55
|
apiClient;
|
|
52
56
|
coreCryptoClient;
|
|
@@ -56,18 +60,31 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
56
60
|
_config;
|
|
57
61
|
textEncoder = new TextEncoder();
|
|
58
62
|
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
|
-
});
|
|
65
63
|
constructor(apiClient, coreCryptoClient, coreDatabase, recurringTaskScheduler) {
|
|
66
64
|
super();
|
|
67
65
|
this.apiClient = apiClient;
|
|
68
66
|
this.coreCryptoClient = coreCryptoClient;
|
|
69
67
|
this.coreDatabase = coreDatabase;
|
|
70
68
|
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);
|
|
71
88
|
}
|
|
72
89
|
/**
|
|
73
90
|
* return true if the MLS service if configured and ready to be used
|
|
@@ -97,24 +114,39 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
97
114
|
...defaultConfig,
|
|
98
115
|
...filteredMLSConfig,
|
|
99
116
|
};
|
|
100
|
-
await this.coreCryptoClient.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
clientIsExistingGroupUser: async () => true,
|
|
104
|
-
authorize: async () => true,
|
|
105
|
-
userAuthorize: async () => true,
|
|
117
|
+
await this.coreCryptoClient.transaction(cx => {
|
|
118
|
+
const clientId = new core_crypto_1.ClientId((0, MLSId_1.generateMLSDeviceId)(userId, client.id));
|
|
119
|
+
return cx.mlsInit(clientId, this.config.ciphersuites, this.config.nbKeyPackages);
|
|
106
120
|
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
121
|
+
try {
|
|
122
|
+
const ccClientSignature = await this.getCCClientSignatureString();
|
|
123
|
+
const mlsDeviceStatus = (0, Helper_1.getMLSDeviceStatus)(client, this.config.defaultCiphersuite, ccClientSignature);
|
|
124
|
+
switch (mlsDeviceStatus) {
|
|
125
|
+
case Helper_1.MLSDeviceStatus.REGISTERED:
|
|
126
|
+
if (!skipInitIdentity) {
|
|
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;
|
|
113
145
|
}
|
|
114
|
-
await this.verifyRemoteMLSKeyPackagesAmount(client.id);
|
|
115
146
|
}
|
|
116
|
-
|
|
117
|
-
this.logger.
|
|
147
|
+
catch (error) {
|
|
148
|
+
this.logger.error(`Error while initializing client ${client.id}`, error);
|
|
149
|
+
throw error;
|
|
118
150
|
}
|
|
119
151
|
}
|
|
120
152
|
/**
|
|
@@ -127,46 +159,62 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
127
159
|
? core_crypto_1.CredentialType.X509
|
|
128
160
|
: core_crypto_1.CredentialType.Basic;
|
|
129
161
|
}
|
|
130
|
-
|
|
162
|
+
_uploadCommitBundle = async ({ commit, groupInfo, welcome, }) => {
|
|
163
|
+
const bundlePayload = new Uint8Array([
|
|
164
|
+
...commit,
|
|
165
|
+
...groupInfo.payload.copyBytes(),
|
|
166
|
+
...(welcome?.copyBytes() || []),
|
|
167
|
+
]);
|
|
131
168
|
try {
|
|
132
|
-
|
|
169
|
+
const response = await this.apiClient.api.conversation.postMlsCommitBundle(bundlePayload);
|
|
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';
|
|
133
177
|
}
|
|
134
178
|
catch (error) {
|
|
135
|
-
|
|
136
|
-
|
|
179
|
+
this.logger.warn(`Failed to upload commit bundle`, error);
|
|
180
|
+
if (error instanceof conversation_1.MLSInvalidLeafNodeSignatureError || error instanceof conversation_1.MLSInvalidLeafNodeIndexError) {
|
|
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
|
+
};
|
|
137
189
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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;
|
|
190
|
+
if (error instanceof conversation_1.MLSStaleMessageError) {
|
|
191
|
+
this.logger.info('Aborting commit bundle upload due to stale MLS message');
|
|
192
|
+
return {
|
|
193
|
+
abort: {
|
|
194
|
+
reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({ message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.MLS_STALE_MESSAGE }),
|
|
195
|
+
},
|
|
196
|
+
};
|
|
159
197
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
198
|
+
if (error instanceof conversation_1.MLSGroupOutOfSyncError) {
|
|
199
|
+
this.logger.info('Aborting commit bundle upload due to group out of sync');
|
|
200
|
+
return {
|
|
201
|
+
abort: {
|
|
202
|
+
reason: (0, CoreCryptoMLSError_1.serializeAbortReason)({
|
|
203
|
+
message: CoreCryptoMLSError_1.UPLOAD_COMMIT_BUNDLE_ABORT_REASONS.MLS_GROUP_OUT_OF_SYNC,
|
|
204
|
+
missing_users: error.missing_users,
|
|
205
|
+
}),
|
|
206
|
+
},
|
|
207
|
+
};
|
|
168
208
|
}
|
|
169
|
-
|
|
209
|
+
this.logger.info('Aborting commit bundle upload due to unknown error');
|
|
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
|
+
}
|
|
170
218
|
};
|
|
171
219
|
/**
|
|
172
220
|
* Will add users to an existing MLS group and send a commit bundle to backend.
|
|
@@ -180,25 +228,26 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
180
228
|
if (keyPackages.length < 1) {
|
|
181
229
|
throw new Error('Empty list of keys provided to addUsersToExistingConversation');
|
|
182
230
|
}
|
|
183
|
-
|
|
184
|
-
|
|
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 };
|
|
231
|
+
const crlNewDistributionPoints = await this.coreCryptoClient.transaction(cx => cx.addClientsToConversation(new core_crypto_1.ConversationId(groupIdBytes), keyPackages));
|
|
232
|
+
this.dispatchNewCrlDistributionPoints(crlNewDistributionPoints);
|
|
200
233
|
}
|
|
201
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Will return a list of client ids which are already in the group at core crypto level
|
|
236
|
+
*
|
|
237
|
+
* @param groupId - the group id of the MLS group
|
|
238
|
+
* @returns list of client ids
|
|
239
|
+
*/
|
|
240
|
+
async getClientIdsInGroup(groupId) {
|
|
241
|
+
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
242
|
+
const currentClientIdsInGroup = [];
|
|
243
|
+
for (const clientId of await this.coreCryptoClient.getClientIds(new core_crypto_1.ConversationId(groupIdBytes))) {
|
|
244
|
+
// [user-id]:[client-id]@[domain] -> [client-id]
|
|
245
|
+
// example: fb880fac-b549-4d8b-9398-4246324c7b85:67f41928e2844b6c@staging.zinfra.io -> 67f41928e2844b6c
|
|
246
|
+
currentClientIdsInGroup.push(bazinga64_1.Converter.arrayBufferViewToStringUTF8(clientId.copyBytes()).split('@')[0].split(':')[1]);
|
|
247
|
+
}
|
|
248
|
+
return currentClientIdsInGroup;
|
|
249
|
+
}
|
|
250
|
+
async getKeyPackagesPayload(qualifiedUsers, skipClientIds = []) {
|
|
202
251
|
/**
|
|
203
252
|
* @note We need to fetch key packages for all the users
|
|
204
253
|
* we want to add to the new MLS conversations,
|
|
@@ -238,18 +287,20 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
238
287
|
if (key_packages.length > 0) {
|
|
239
288
|
return [
|
|
240
289
|
...previousValue,
|
|
241
|
-
...key_packages
|
|
290
|
+
...key_packages
|
|
291
|
+
.filter(keyPackage => !skipClientIds.includes(keyPackage.client))
|
|
292
|
+
.map(keyPackage => bazinga64_1.Decoder.fromBase64(keyPackage.key_package).asBytes),
|
|
242
293
|
];
|
|
243
294
|
}
|
|
244
295
|
return previousValue;
|
|
245
296
|
}, []);
|
|
246
297
|
const failures = [];
|
|
247
298
|
if (emptyKeyPackagesUsers.length > 0) {
|
|
248
|
-
failures.push({ reason:
|
|
299
|
+
failures.push({ reason: conversation_2.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG, users: emptyKeyPackagesUsers });
|
|
249
300
|
}
|
|
250
301
|
if (failedToFetchKeyPackages.length > 0) {
|
|
251
302
|
failures.push({
|
|
252
|
-
reason:
|
|
303
|
+
reason: conversation_2.AddUsersFailureReasons.UNREACHABLE_BACKENDS,
|
|
253
304
|
users: failedToFetchKeyPackages,
|
|
254
305
|
backends: failedToFetchKeyPackages.map(({ domain }) => domain),
|
|
255
306
|
});
|
|
@@ -258,92 +309,98 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
258
309
|
}
|
|
259
310
|
getEpoch(groupId) {
|
|
260
311
|
const groupIdBytes = typeof groupId === 'string' ? bazinga64_1.Decoder.fromBase64(groupId).asBytes : groupId;
|
|
261
|
-
return this.coreCryptoClient.conversationEpoch(groupIdBytes);
|
|
262
|
-
}
|
|
263
|
-
async newProposal(proposalType, args) {
|
|
264
|
-
return this.coreCryptoClient.newProposal(proposalType, args);
|
|
312
|
+
return this.coreCryptoClient.conversationEpoch(new core_crypto_1.ConversationId(groupIdBytes));
|
|
265
313
|
}
|
|
266
314
|
async joinByExternalCommit(getGroupInfo) {
|
|
267
|
-
|
|
268
|
-
|
|
315
|
+
try {
|
|
316
|
+
this.logger.info('Trying to join MLS group via external commit');
|
|
317
|
+
const credentialType = await this.getCredentialType();
|
|
269
318
|
const groupInfo = await getGroupInfo();
|
|
270
|
-
const
|
|
271
|
-
this.dispatchNewCrlDistributionPoints(
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
319
|
+
const welcomeBundle = await this.coreCryptoClient.transaction(cx => cx.joinByExternalCommit(new core_crypto_1.GroupInfo(groupInfo), credentialType));
|
|
320
|
+
await this.dispatchNewCrlDistributionPoints(welcomeBundle.crlNewDistributionPoints);
|
|
321
|
+
this.logger.info('welcome bundle after joining via external commit');
|
|
322
|
+
if (welcomeBundle.id) {
|
|
323
|
+
//after we've successfully joined via external commit, we schedule periodic key material renewal
|
|
324
|
+
const groupIdStr = bazinga64_1.Encoder.toBase64(welcomeBundle.id.copyBytes()).asString;
|
|
325
|
+
const newEpoch = await this.getEpoch(groupIdStr);
|
|
326
|
+
// Schedule the next key material renewal
|
|
327
|
+
await this.scheduleKeyMaterialRenewal(groupIdStr);
|
|
328
|
+
// Notify subscribers about the new epoch
|
|
329
|
+
this.emit(MLSServiceEvents.NEW_EPOCH, { groupId: groupIdStr, epoch: newEpoch });
|
|
330
|
+
this.logger.info(`Joined MLS group with id ${groupIdStr} via external commit, new epoch: ${newEpoch}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
this.logger.warn('Failed to join MLS group via external commit', error);
|
|
335
|
+
throw error;
|
|
284
336
|
}
|
|
285
|
-
return mlsResponse;
|
|
286
337
|
}
|
|
287
338
|
async exportSecretKey(groupId, keyLength) {
|
|
288
339
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
289
|
-
const key = await this.coreCryptoClient.exportSecretKey(groupIdBytes, keyLength);
|
|
340
|
+
const key = await this.coreCryptoClient.exportSecretKey(new core_crypto_1.ConversationId(groupIdBytes), keyLength);
|
|
290
341
|
return bazinga64_1.Encoder.toBase64(key).asString;
|
|
291
342
|
}
|
|
292
|
-
dispatchNewCrlDistributionPoints(
|
|
293
|
-
const { crlNewDistributionPoints } = payload;
|
|
343
|
+
dispatchNewCrlDistributionPoints(crlNewDistributionPoints) {
|
|
294
344
|
if (crlNewDistributionPoints && crlNewDistributionPoints.length > 0) {
|
|
295
|
-
this.emit(
|
|
345
|
+
this.emit(MLSServiceEvents.NEW_CRL_DISTRIBUTION_POINTS, crlNewDistributionPoints);
|
|
296
346
|
}
|
|
297
347
|
}
|
|
298
348
|
async processWelcomeMessage(welcomeMessage) {
|
|
299
|
-
const welcomeBundle = await this.coreCryptoClient.processWelcomeMessage(welcomeMessage);
|
|
300
|
-
this.dispatchNewCrlDistributionPoints(welcomeBundle);
|
|
349
|
+
const welcomeBundle = await this.coreCryptoClient.transaction(cx => cx.processWelcomeMessage(new core_crypto_1.Welcome(welcomeMessage)));
|
|
350
|
+
this.dispatchNewCrlDistributionPoints(welcomeBundle.crlNewDistributionPoints);
|
|
301
351
|
return welcomeBundle.id;
|
|
302
352
|
}
|
|
303
353
|
async decryptMessage(conversationId, payload) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
354
|
+
try {
|
|
355
|
+
const start = Date.now();
|
|
356
|
+
this.logger.info('Decrypting message', { conversationId });
|
|
357
|
+
const decryptedMessage = await this.coreCryptoClient.transaction(cx => cx.decryptMessage(conversationId, payload));
|
|
358
|
+
this.dispatchNewCrlDistributionPoints(decryptedMessage.crlNewDistributionPoints);
|
|
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
|
+
};
|
|
320
370
|
}
|
|
321
|
-
|
|
371
|
+
throw error;
|
|
372
|
+
}
|
|
322
373
|
}
|
|
323
374
|
async encryptMessage(conversationId, message) {
|
|
324
|
-
return this.coreCryptoClient.encryptMessage(conversationId, message);
|
|
375
|
+
return this.coreCryptoClient.transaction(cx => cx.encryptMessage(conversationId, message));
|
|
325
376
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
377
|
+
async updateKeyingMaterial(groupId, retry = true) {
|
|
378
|
+
try {
|
|
379
|
+
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
380
|
+
await this.coreCryptoClient.transaction(cx => cx.updateKeyingMaterial(new core_crypto_1.ConversationId(groupIdBytes)));
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
if (!retry) {
|
|
384
|
+
this.logger.error(`Failed to update keying material for group retrying did not fix the issue`, {
|
|
385
|
+
error,
|
|
386
|
+
groupId,
|
|
387
|
+
});
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
this.logger.warn(`Failed to update keying material for group`, { error, groupId });
|
|
391
|
+
this.emit(MLSServiceEvents.KEY_MATERIAL_UPDATE_FAILURE, { error, groupId });
|
|
392
|
+
setTimeout(async () => {
|
|
393
|
+
try {
|
|
394
|
+
await this.updateKeyingMaterial(groupId, false);
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
this.logger.error(`Failed to update keying material for group on retry`, {
|
|
398
|
+
error,
|
|
399
|
+
groupId,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}, commons_1.TimeUtil.TimeInMillis.SECOND * 10); // retry after 10 seconds
|
|
403
|
+
}
|
|
347
404
|
}
|
|
348
405
|
/**
|
|
349
406
|
* Will create an empty conversation inside of coreCrypto.
|
|
@@ -355,7 +412,9 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
355
412
|
let externalSenders = [];
|
|
356
413
|
if (parentGroupId) {
|
|
357
414
|
const parentGroupIdBytes = bazinga64_1.Decoder.fromBase64(parentGroupId).asBytes;
|
|
358
|
-
externalSenders = [
|
|
415
|
+
externalSenders = [
|
|
416
|
+
new core_crypto_1.ExternalSenderKey(await this.coreCryptoClient.getExternalSender(new core_crypto_1.ConversationId(parentGroupIdBytes))),
|
|
417
|
+
];
|
|
359
418
|
}
|
|
360
419
|
else {
|
|
361
420
|
const mlsKeys = (await this.apiClient.api.client.getPublicKeys()).removal;
|
|
@@ -364,14 +423,14 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
364
423
|
if (!removalKeyForSignature) {
|
|
365
424
|
throw new Error(`Cannot create conversation: No backend removal key found for the signature ${ciphersuiteSignature}`);
|
|
366
425
|
}
|
|
367
|
-
externalSenders = [bazinga64_1.Decoder.fromBase64(removalKeyForSignature).asBytes];
|
|
426
|
+
externalSenders = [new core_crypto_1.ExternalSenderKey(bazinga64_1.Decoder.fromBase64(removalKeyForSignature).asBytes)];
|
|
368
427
|
}
|
|
369
428
|
const configuration = {
|
|
370
429
|
externalSenders,
|
|
371
430
|
ciphersuite: this.config.defaultCiphersuite,
|
|
372
431
|
};
|
|
373
432
|
const credentialType = await this.getCredentialType();
|
|
374
|
-
return this.coreCryptoClient.createConversation(groupIdBytes, credentialType, configuration);
|
|
433
|
+
return this.coreCryptoClient.transaction(cx => cx.createConversation(new core_crypto_1.ConversationId(groupIdBytes), credentialType, configuration));
|
|
375
434
|
}
|
|
376
435
|
/**
|
|
377
436
|
* Will create a conversation inside of coreCrypto, add users to it or update the keying material if empty key packages list is provided.
|
|
@@ -395,19 +454,18 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
395
454
|
}));
|
|
396
455
|
if (keyPackages.length <= 0) {
|
|
397
456
|
// If there are no clients to add, just update the keying material
|
|
398
|
-
|
|
457
|
+
await this.updateKeyingMaterial(groupId);
|
|
399
458
|
await this.scheduleKeyMaterialRenewal(groupId);
|
|
400
|
-
return
|
|
459
|
+
return keysClaimingFailures;
|
|
401
460
|
}
|
|
402
|
-
|
|
461
|
+
await this.addUsersToExistingConversation(groupId, keyPackages);
|
|
403
462
|
// We schedule a periodic key material renewal
|
|
404
463
|
await this.scheduleKeyMaterialRenewal(groupId);
|
|
405
464
|
/**
|
|
406
465
|
* @note If we can't fetch a user's key packages then we can not add them to mls conversation
|
|
407
466
|
* so we're adding them to the list of failed users.
|
|
408
467
|
*/
|
|
409
|
-
|
|
410
|
-
return response;
|
|
468
|
+
return keysClaimingFailures;
|
|
411
469
|
}
|
|
412
470
|
/**
|
|
413
471
|
* Will create a 1:1 conversation inside of coreCrypto, try claiming key packages for user and (if succesfull) add them to the MLS group.
|
|
@@ -423,21 +481,17 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
423
481
|
// If we're missing key packages for the user we want to add, we can't register the conversation
|
|
424
482
|
if (otherUserKeyPackages.length <= 0) {
|
|
425
483
|
if (otherUserKeysClaimingFailures.length > 0 &&
|
|
426
|
-
otherUserKeysClaimingFailures.some(({ reason }) => reason ===
|
|
484
|
+
otherUserKeysClaimingFailures.some(({ reason }) => reason === conversation_2.AddUsersFailureReasons.OFFLINE_FOR_TOO_LONG)) {
|
|
427
485
|
throw new ClientMLSError_1.ClientMLSError(ClientMLSError_1.ClientMLSErrorLabel.NO_KEY_PACKAGES_AVAILABLE);
|
|
428
486
|
}
|
|
429
487
|
}
|
|
430
488
|
const { keyPackages: selfKeyPackages, failures: selfKeysClaimingFailures } = await this.getKeyPackagesPayload([
|
|
431
489
|
{ ...selfUser.user, skipOwnClientId: selfUser.client },
|
|
432
490
|
]);
|
|
433
|
-
|
|
434
|
-
...otherUserKeyPackages,
|
|
435
|
-
...selfKeyPackages,
|
|
436
|
-
]);
|
|
491
|
+
await this.addUsersToExistingConversation(groupId, [...otherUserKeyPackages, ...selfKeyPackages]);
|
|
437
492
|
// We schedule a periodic key material renewal
|
|
438
493
|
await this.scheduleKeyMaterialRenewal(groupId);
|
|
439
|
-
|
|
440
|
-
return response;
|
|
494
|
+
return [...otherUserKeysClaimingFailures, ...selfKeysClaimingFailures];
|
|
441
495
|
}
|
|
442
496
|
catch (error) {
|
|
443
497
|
await this.wipeConversation(groupId);
|
|
@@ -464,6 +518,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
464
518
|
return true;
|
|
465
519
|
}
|
|
466
520
|
catch (error) {
|
|
521
|
+
this.logger.warn("Couldn't establish the MLS group", error);
|
|
467
522
|
// If conversation already existed, locally, nothing more to do, we've received a welcome message.
|
|
468
523
|
if ((0, CoreCryptoMLSError_1.isCoreCryptoMLSConversationAlreadyExistsError)(error)) {
|
|
469
524
|
this.logger.debug(`MLS Group with id ${groupId} already exists, skipping the initialisation.`);
|
|
@@ -483,7 +538,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
483
538
|
*/
|
|
484
539
|
removeClientsFromConversation(groupId, clientIds) {
|
|
485
540
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
486
|
-
return this.
|
|
541
|
+
return this.coreCryptoClient.transaction(cx => cx.removeClientsFromConversation(new core_crypto_1.ConversationId(groupIdBytes), clientIds.map(id => new core_crypto_1.ClientId(this.textEncoder.encode(id)))));
|
|
487
542
|
}
|
|
488
543
|
/**
|
|
489
544
|
* Will check if mls group exists in corecrypto.
|
|
@@ -491,7 +546,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
491
546
|
*/
|
|
492
547
|
async conversationExists(groupId) {
|
|
493
548
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
494
|
-
return this.coreCryptoClient.conversationExists(groupIdBytes);
|
|
549
|
+
return this.coreCryptoClient.conversationExists(new core_crypto_1.ConversationId(groupIdBytes));
|
|
495
550
|
}
|
|
496
551
|
/**
|
|
497
552
|
* Will check if mls group is established in coreCrypto.
|
|
@@ -504,11 +559,11 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
504
559
|
}
|
|
505
560
|
async clientValidKeypackagesCount() {
|
|
506
561
|
const credentialType = await this.getCredentialType();
|
|
507
|
-
return this.coreCryptoClient.clientValidKeypackagesCount(this.config.defaultCiphersuite, credentialType);
|
|
562
|
+
return this.coreCryptoClient.transaction(cx => cx.clientValidKeypackagesCount(this.config.defaultCiphersuite, credentialType));
|
|
508
563
|
}
|
|
509
564
|
async clientKeypackages(amountRequested) {
|
|
510
565
|
const credentialType = await this.getCredentialType();
|
|
511
|
-
return this.coreCryptoClient.clientKeypackages(this.config.defaultCiphersuite, credentialType, amountRequested);
|
|
566
|
+
return this.coreCryptoClient.transaction(cx => cx.clientKeypackages(this.config.defaultCiphersuite, credentialType, amountRequested));
|
|
512
567
|
}
|
|
513
568
|
/**
|
|
514
569
|
* Will send an empty commit into a group (renew key material)
|
|
@@ -610,6 +665,14 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
610
665
|
async getRemoteMLSKeyPackageCount(clientId) {
|
|
611
666
|
return this.apiClient.api.client.getMLSKeyPackageCount(clientId, (0, numberToHex_1.numberToHex)(this.config.defaultCiphersuite));
|
|
612
667
|
}
|
|
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
|
+
}
|
|
613
676
|
/**
|
|
614
677
|
* Will update the given client on backend with its public key.
|
|
615
678
|
*
|
|
@@ -618,13 +681,18 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
618
681
|
*/
|
|
619
682
|
async uploadMLSPublicKeys(client) {
|
|
620
683
|
// If we've already updated a client with its public key, there's no need to do it again.
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
684
|
+
try {
|
|
685
|
+
const clientSignature = await this.getCCClientSignatureString();
|
|
686
|
+
return this.apiClient.api.client.putClient(client.id, {
|
|
687
|
+
mls_public_keys: {
|
|
688
|
+
[(0, Helper_1.getSignatureAlgorithmForCiphersuite)(this.config.defaultCiphersuite)]: clientSignature,
|
|
689
|
+
},
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
this.logger.error(`Failed to upload public keys for client ${client.id}`, error);
|
|
694
|
+
throw error;
|
|
695
|
+
}
|
|
628
696
|
}
|
|
629
697
|
async replaceKeyPackages(clientId, keyPackages) {
|
|
630
698
|
return this.apiClient.api.client.replaceMLSKeyPackages(clientId, keyPackages.map(keyPackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keyPackage))), (0, numberToHex_1.numberToHex)(this.config.defaultCiphersuite));
|
|
@@ -633,7 +701,6 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
633
701
|
return this.apiClient.api.client.uploadMLSKeyPackages(clientId, keyPackages.map(keyPackage => btoa(bazinga64_1.Converter.arrayBufferViewToBaselineString(keyPackage))));
|
|
634
702
|
}
|
|
635
703
|
async wipeConversation(groupId) {
|
|
636
|
-
(0, messageAdd_1.deleteMLSMessagesQueue)(groupId);
|
|
637
704
|
await this.cancelKeyMaterialRenewal(groupId);
|
|
638
705
|
await this.cancelPendingProposalsTask(groupId);
|
|
639
706
|
const doesConversationExist = await this.conversationExists(groupId);
|
|
@@ -642,7 +709,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
642
709
|
return;
|
|
643
710
|
}
|
|
644
711
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
645
|
-
return this.coreCryptoClient.wipeConversation(groupIdBytes);
|
|
712
|
+
return this.coreCryptoClient.transaction(cx => cx.wipeConversation(new core_crypto_1.ConversationId(groupIdBytes)));
|
|
646
713
|
}
|
|
647
714
|
/**
|
|
648
715
|
* If there are pending proposals, we need to either process them,
|
|
@@ -682,25 +749,29 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
682
749
|
*
|
|
683
750
|
* @param groupId groupId of the conversation
|
|
684
751
|
*/
|
|
685
|
-
async commitPendingProposals(groupId, shouldRetry = true) {
|
|
752
|
+
async commitPendingProposals(groupId, shouldRetry = true, params) {
|
|
753
|
+
this.logger.info(`Committing pending proposals for groupId ${groupId}`, { shouldRetry, params });
|
|
686
754
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
687
755
|
try {
|
|
688
|
-
|
|
689
|
-
if (commitBundle) {
|
|
690
|
-
await this.uploadCommitBundle(groupIdBytes, commitBundle);
|
|
691
|
-
}
|
|
756
|
+
await this.coreCryptoClient.transaction(cx => cx.commitPendingProposals(new core_crypto_1.ConversationId(groupIdBytes)));
|
|
692
757
|
await this.cancelPendingProposalsTask(groupId);
|
|
693
758
|
}
|
|
694
759
|
catch (error) {
|
|
695
760
|
if (!shouldRetry) {
|
|
696
761
|
throw error;
|
|
697
762
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
763
|
+
if ((0, core_crypto_1.isMlsMessageRejectedError)(error)) {
|
|
764
|
+
this.logger.warn('Failed to commit proposals, conversation is broken, letting the error bubble up', {
|
|
765
|
+
error,
|
|
766
|
+
groupId,
|
|
767
|
+
});
|
|
768
|
+
throw error;
|
|
769
|
+
}
|
|
770
|
+
this.logger.warn('Failed to commit proposals, clearing the pending commit and retrying', {
|
|
771
|
+
error,
|
|
772
|
+
groupId,
|
|
773
|
+
shouldRetry,
|
|
774
|
+
});
|
|
704
775
|
return this.commitPendingProposals(groupId, false);
|
|
705
776
|
}
|
|
706
777
|
}
|
|
@@ -731,9 +802,9 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
731
802
|
*/
|
|
732
803
|
async getClientIds(groupId) {
|
|
733
804
|
const groupIdBytes = bazinga64_1.Decoder.fromBase64(groupId).asBytes;
|
|
734
|
-
const rawClientIds = await this.coreCryptoClient.getClientIds(groupIdBytes);
|
|
805
|
+
const rawClientIds = await this.coreCryptoClient.getClientIds(new core_crypto_1.ConversationId(groupIdBytes));
|
|
735
806
|
const clientIds = rawClientIds.map(id => {
|
|
736
|
-
const { user, client, domain } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(id));
|
|
807
|
+
const { user, client, domain } = (0, fullyQualifiedClientIdUtils_1.parseFullQualifiedClientId)(this.textDecoder.decode(id.copyBytes()));
|
|
737
808
|
return { userId: user, clientId: client, domain };
|
|
738
809
|
});
|
|
739
810
|
return clientIds;
|
|
@@ -745,7 +816,7 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
745
816
|
if (!groupId) {
|
|
746
817
|
throw new Error(`Could not find a group_id for conversation ${qualifiedConversationId.id}@${qualifiedConversationId.domain}${event.subconv ? `/subconversation:${event.subconv}` : ''}`);
|
|
747
818
|
}
|
|
748
|
-
return (0,
|
|
819
|
+
return (0, events_1.handleMLSMessageAdd)({ event, mlsService: this, groupId });
|
|
749
820
|
}
|
|
750
821
|
async handleMLSWelcomeMessageEvent(event, clientId) {
|
|
751
822
|
// Every time we've received a welcome message, it means that our key package was consumed,
|
|
@@ -769,32 +840,20 @@ class MLSService extends commons_1.TypedEventEmitter {
|
|
|
769
840
|
* @param oAuthIdToken The OAuth id token if the user is already authenticated
|
|
770
841
|
* @returns AcmeChallenge if the user is not authenticated, true if the user is authenticated
|
|
771
842
|
*/
|
|
772
|
-
async enrollE2EI(discoveryUrl, user, client, nbPrekeys, certificateTtl, getOAuthToken) {
|
|
843
|
+
async enrollE2EI(discoveryUrl, user, client, nbPrekeys, certificateTtl, getOAuthToken, getAllConversations) {
|
|
773
844
|
const isCertificateRenewal = await this.coreCryptoClient.e2eiIsEnabled(this.config.defaultCiphersuite);
|
|
774
845
|
const e2eiServiceInternal = new E2EIServiceInternal_1.E2EIServiceInternal(this.coreDatabase, this.coreCryptoClient, this.apiClient, certificateTtl, nbPrekeys, { user, clientId: client.id, discoveryUrl });
|
|
775
|
-
const
|
|
776
|
-
this.dispatchNewCrlDistributionPoints(
|
|
846
|
+
const { keyPackages, newCrlDistributionPoints } = await e2eiServiceInternal.generateCertificate(getOAuthToken, isCertificateRenewal, getAllConversations, this.config.defaultCiphersuite);
|
|
847
|
+
this.dispatchNewCrlDistributionPoints(newCrlDistributionPoints);
|
|
777
848
|
// upload the clients public keys
|
|
778
849
|
if (!this.isInitializedMLSClient(client)) {
|
|
779
850
|
// we only upload public keys for the initial certification process if the device is not already a registered MLS device.
|
|
780
851
|
await this.uploadMLSPublicKeys(client);
|
|
781
852
|
}
|
|
782
853
|
// replace old key packages with new key packages with x509 certificate
|
|
783
|
-
await this.replaceKeyPackages(client.id,
|
|
854
|
+
await this.replaceKeyPackages(client.id, keyPackages);
|
|
784
855
|
// Verify that we have enough key packages
|
|
785
856
|
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
|
-
}
|
|
798
857
|
}
|
|
799
858
|
}
|
|
800
859
|
exports.MLSService = MLSService;
|