livekit-client 2.5.8 → 2.5.9
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/livekit-client.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +49 -20
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +2 -2
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts +25 -5
- package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/ts4.2/src/e2ee/worker/ParticipantKeyHandler.d.ts +25 -5
- package/package.json +2 -2
- package/src/e2ee/worker/FrameCryptor.test.ts +311 -113
- package/src/e2ee/worker/FrameCryptor.ts +10 -5
- package/src/e2ee/worker/ParticipantKeyHandler.test.ts +169 -5
- package/src/e2ee/worker/ParticipantKeyHandler.ts +50 -20
- package/src/e2ee/worker/__snapshots__/ParticipantKeyHandler.test.ts.snap +356 -0
- package/src/room/participant/LocalParticipant.ts +4 -1
@@ -5941,10 +5941,14 @@ class FrameCryptor extends BaseFrameCryptor {
|
|
5941
5941
|
}
|
5942
5942
|
const data = new Uint8Array(encodedFrame.data);
|
5943
5943
|
const keyIndex = data[encodedFrame.data.byteLength - 1];
|
5944
|
-
if (this.keys.
|
5944
|
+
if (this.keys.hasInvalidKeyAtIndex(keyIndex)) {
|
5945
|
+
// drop frame
|
5946
|
+
return;
|
5947
|
+
}
|
5948
|
+
if (this.keys.getKeySet(keyIndex)) {
|
5945
5949
|
try {
|
5946
5950
|
const decodedFrame = yield this.decryptFrame(encodedFrame, keyIndex);
|
5947
|
-
this.keys.decryptionSuccess();
|
5951
|
+
this.keys.decryptionSuccess(keyIndex);
|
5948
5952
|
if (decodedFrame) {
|
5949
5953
|
return controller.enqueue(decodedFrame);
|
5950
5954
|
}
|
@@ -5953,7 +5957,7 @@ class FrameCryptor extends BaseFrameCryptor {
|
|
5953
5957
|
// emit an error if the key handler thinks we have a valid key
|
5954
5958
|
if (this.keys.hasValidKey) {
|
5955
5959
|
this.emit(CryptorEvent.Error, error);
|
5956
|
-
this.keys.decryptionFailure();
|
5960
|
+
this.keys.decryptionFailure(keyIndex);
|
5957
5961
|
}
|
5958
5962
|
} else {
|
5959
5963
|
workerLogger.warn('decoding frame failed', {
|
@@ -5961,11 +5965,11 @@ class FrameCryptor extends BaseFrameCryptor {
|
|
5961
5965
|
});
|
5962
5966
|
}
|
5963
5967
|
}
|
5964
|
-
} else
|
5968
|
+
} else {
|
5965
5969
|
// emit an error if the key index is out of bounds but the key handler thinks we still have a valid key
|
5966
5970
|
workerLogger.warn("skipping decryption due to missing key at index ".concat(keyIndex));
|
5967
5971
|
this.emit(CryptorEvent.Error, new CryptorError("missing key at index ".concat(keyIndex, " for participant ").concat(this.participantIdentity), CryptorErrorReason.MissingKey, this.participantIdentity));
|
5968
|
-
this.keys.decryptionFailure();
|
5972
|
+
this.keys.decryptionFailure(keyIndex);
|
5969
5973
|
}
|
5970
5974
|
});
|
5971
5975
|
}
|
@@ -6259,43 +6263,68 @@ function isFrameServerInjected(frameData, trailerBytes) {
|
|
6259
6263
|
*
|
6260
6264
|
*/
|
6261
6265
|
class ParticipantKeyHandler extends eventsExports.EventEmitter {
|
6266
|
+
/**
|
6267
|
+
* true if the current key has not been marked as invalid
|
6268
|
+
*/
|
6262
6269
|
get hasValidKey() {
|
6263
|
-
return this.
|
6270
|
+
return !this.hasInvalidKeyAtIndex(this.currentKeyIndex);
|
6264
6271
|
}
|
6265
6272
|
constructor(participantIdentity, keyProviderOptions) {
|
6266
6273
|
super();
|
6267
|
-
this.decryptionFailureCount = 0;
|
6268
|
-
this._hasValidKey = true;
|
6269
6274
|
this.currentKeyIndex = 0;
|
6270
6275
|
if (keyProviderOptions.keyringSize < 1 || keyProviderOptions.keyringSize > 256) {
|
6271
6276
|
throw new TypeError('Keyring size needs to be between 1 and 256');
|
6272
6277
|
}
|
6273
6278
|
this.cryptoKeyRing = new Array(keyProviderOptions.keyringSize).fill(undefined);
|
6279
|
+
this.decryptionFailureCounts = new Array(keyProviderOptions.keyringSize).fill(0);
|
6274
6280
|
this.keyProviderOptions = keyProviderOptions;
|
6275
6281
|
this.ratchetPromiseMap = new Map();
|
6276
6282
|
this.participantIdentity = participantIdentity;
|
6277
|
-
this.resetKeyStatus();
|
6278
6283
|
}
|
6284
|
+
/**
|
6285
|
+
* Returns true if the key at the given index is marked as invalid.
|
6286
|
+
*
|
6287
|
+
* @param keyIndex the index of the key
|
6288
|
+
*/
|
6289
|
+
hasInvalidKeyAtIndex(keyIndex) {
|
6290
|
+
return this.keyProviderOptions.failureTolerance >= 0 && this.decryptionFailureCounts[keyIndex] > this.keyProviderOptions.failureTolerance;
|
6291
|
+
}
|
6292
|
+
/**
|
6293
|
+
* Informs the key handler that a decryption failure occurred for an encryption key.
|
6294
|
+
* @internal
|
6295
|
+
* @param keyIndex the key index for which the failure occurred. Defaults to the current key index.
|
6296
|
+
*/
|
6279
6297
|
decryptionFailure() {
|
6298
|
+
let keyIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.currentKeyIndex;
|
6280
6299
|
if (this.keyProviderOptions.failureTolerance < 0) {
|
6281
6300
|
return;
|
6282
6301
|
}
|
6283
|
-
this.
|
6284
|
-
if (this.
|
6285
|
-
workerLogger.warn("key for ".concat(this.participantIdentity, " is being marked as invalid"));
|
6286
|
-
this._hasValidKey = false;
|
6302
|
+
this.decryptionFailureCounts[keyIndex] += 1;
|
6303
|
+
if (this.decryptionFailureCounts[keyIndex] > this.keyProviderOptions.failureTolerance) {
|
6304
|
+
workerLogger.warn("key for ".concat(this.participantIdentity, " at index ").concat(keyIndex, " is being marked as invalid"));
|
6287
6305
|
}
|
6288
6306
|
}
|
6307
|
+
/**
|
6308
|
+
* Informs the key handler that a frame was successfully decrypted using an encryption key.
|
6309
|
+
* @internal
|
6310
|
+
* @param keyIndex the key index for which the success occurred. Defaults to the current key index.
|
6311
|
+
*/
|
6289
6312
|
decryptionSuccess() {
|
6290
|
-
this.
|
6313
|
+
let keyIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.currentKeyIndex;
|
6314
|
+
this.resetKeyStatus(keyIndex);
|
6291
6315
|
}
|
6292
6316
|
/**
|
6293
6317
|
* Call this after user initiated ratchet or a new key has been set in order to make sure to mark potentially
|
6294
6318
|
* invalid keys as valid again
|
6319
|
+
*
|
6320
|
+
* @param keyIndex the index of the key. Defaults to the current key index.
|
6295
6321
|
*/
|
6296
|
-
resetKeyStatus() {
|
6297
|
-
|
6298
|
-
|
6322
|
+
resetKeyStatus(keyIndex) {
|
6323
|
+
if (keyIndex === undefined) {
|
6324
|
+
this.decryptionFailureCounts.fill(0);
|
6325
|
+
} else {
|
6326
|
+
this.decryptionFailureCounts[keyIndex] = 0;
|
6327
|
+
}
|
6299
6328
|
}
|
6300
6329
|
/**
|
6301
6330
|
* Ratchets the current key (or the one at keyIndex if provided) and
|
@@ -6320,7 +6349,7 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
|
|
6320
6349
|
const currentMaterial = keySet.material;
|
6321
6350
|
const newMaterial = yield importKey(yield ratchet(currentMaterial, this.keyProviderOptions.ratchetSalt), currentMaterial.algorithm.name, 'derive');
|
6322
6351
|
if (setKey) {
|
6323
|
-
this.setKeyFromMaterial(newMaterial, currentKeyIndex, true);
|
6352
|
+
yield this.setKeyFromMaterial(newMaterial, currentKeyIndex, true);
|
6324
6353
|
this.emit(KeyHandlerEvent.KeyRatcheted, newMaterial, this.participantIdentity, currentKeyIndex);
|
6325
6354
|
}
|
6326
6355
|
resolve(newMaterial);
|
@@ -6345,7 +6374,7 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
|
|
6345
6374
|
let keyIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
6346
6375
|
return function* () {
|
6347
6376
|
yield _this.setKeyFromMaterial(material, keyIndex);
|
6348
|
-
_this.resetKeyStatus();
|
6377
|
+
_this.resetKeyStatus(keyIndex);
|
6349
6378
|
}();
|
6350
6379
|
});
|
6351
6380
|
}
|
@@ -6382,7 +6411,7 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
|
|
6382
6411
|
setCurrentKeyIndex(index) {
|
6383
6412
|
return __awaiter(this, void 0, void 0, function* () {
|
6384
6413
|
this.currentKeyIndex = index % this.cryptoKeyRing.length;
|
6385
|
-
this.resetKeyStatus();
|
6414
|
+
this.resetKeyStatus(index);
|
6386
6415
|
});
|
6387
6416
|
}
|
6388
6417
|
getCurrentKeyIndex() {
|