livekit-client 2.11.3 → 2.12.0

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.
Files changed (60) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +30 -23
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +126 -27
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/api/SignalClient.d.ts +2 -1
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  12. package/dist/src/e2ee/KeyProvider.d.ts +8 -5
  13. package/dist/src/e2ee/KeyProvider.d.ts.map +1 -1
  14. package/dist/src/e2ee/constants.d.ts.map +1 -1
  15. package/dist/src/e2ee/events.d.ts +8 -3
  16. package/dist/src/e2ee/events.d.ts.map +1 -1
  17. package/dist/src/e2ee/types.d.ts +5 -3
  18. package/dist/src/e2ee/types.d.ts.map +1 -1
  19. package/dist/src/e2ee/utils.d.ts +1 -1
  20. package/dist/src/e2ee/utils.d.ts.map +1 -1
  21. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  22. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts +5 -6
  23. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts.map +1 -1
  24. package/dist/src/room/RTCEngine.d.ts +2 -1
  25. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  26. package/dist/src/room/Room.d.ts +1 -0
  27. package/dist/src/room/Room.d.ts.map +1 -1
  28. package/dist/src/room/events.d.ts +11 -1
  29. package/dist/src/room/events.d.ts.map +1 -1
  30. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  31. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  32. package/dist/src/version.d.ts +1 -1
  33. package/dist/ts4.2/src/api/SignalClient.d.ts +2 -1
  34. package/dist/ts4.2/src/e2ee/KeyProvider.d.ts +8 -5
  35. package/dist/ts4.2/src/e2ee/events.d.ts +8 -3
  36. package/dist/ts4.2/src/e2ee/types.d.ts +5 -3
  37. package/dist/ts4.2/src/e2ee/utils.d.ts +1 -1
  38. package/dist/ts4.2/src/e2ee/worker/ParticipantKeyHandler.d.ts +5 -6
  39. package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -1
  40. package/dist/ts4.2/src/room/Room.d.ts +1 -0
  41. package/dist/ts4.2/src/room/events.d.ts +11 -1
  42. package/dist/ts4.2/src/version.d.ts +1 -1
  43. package/package.json +2 -2
  44. package/src/api/SignalClient.ts +10 -0
  45. package/src/e2ee/E2eeManager.ts +8 -12
  46. package/src/e2ee/KeyProvider.ts +13 -6
  47. package/src/e2ee/constants.ts +0 -1
  48. package/src/e2ee/events.ts +12 -3
  49. package/src/e2ee/types.ts +8 -3
  50. package/src/e2ee/utils.ts +1 -2
  51. package/src/e2ee/worker/FrameCryptor.ts +8 -4
  52. package/src/e2ee/worker/ParticipantKeyHandler.test.ts +104 -4
  53. package/src/e2ee/worker/ParticipantKeyHandler.ts +23 -26
  54. package/src/e2ee/worker/e2ee.worker.ts +9 -4
  55. package/src/room/RTCEngine.ts +7 -0
  56. package/src/room/Room.ts +27 -2
  57. package/src/room/events.ts +11 -0
  58. package/src/room/participant/LocalParticipant.ts +0 -5
  59. package/src/room/track/RemoteAudioTrack.ts +3 -2
  60. package/src/version.ts +1 -1
@@ -482,8 +482,7 @@ const KEY_PROVIDER_DEFAULTS = {
482
482
  ratchetSalt: SALT,
483
483
  ratchetWindowSize: 8,
484
484
  failureTolerance: DECRYPTION_FAILURE_TOLERANCE,
485
- keyringSize: 16,
486
- allowKeyExtraction: false
485
+ keyringSize: 16
487
486
  };
488
487
  const MAX_SIF_COUNT = 100;
489
488
  const MAX_SIF_DURATION = 2000;
@@ -550,11 +549,16 @@ class CryptorError extends LivekitError {
550
549
  var KeyProviderEvent;
551
550
  (function (KeyProviderEvent) {
552
551
  KeyProviderEvent["SetKey"] = "setKey";
552
+ /** Event for requesting to ratchet the key used to encrypt the stream */
553
553
  KeyProviderEvent["RatchetRequest"] = "ratchetRequest";
554
+ /** Emitted when a key is ratcheted. Could be after auto-ratcheting on decryption failure or
555
+ * following a `RatchetRequest`, will contain the ratcheted key material */
554
556
  KeyProviderEvent["KeyRatcheted"] = "keyRatcheted";
555
557
  })(KeyProviderEvent || (KeyProviderEvent = {}));
556
558
  var KeyHandlerEvent;
557
559
  (function (KeyHandlerEvent) {
560
+ /** Emitted when a key has been ratcheted. Is emitted when any key has been ratcheted
561
+ * i.e. when the FrameCryptor tried to ratchet when decryption is failing */
558
562
  KeyHandlerEvent["KeyRatcheted"] = "keyRatcheted";
559
563
  })(KeyHandlerEvent || (KeyHandlerEvent = {}));
560
564
  var EncryptionEvent;
@@ -963,10 +967,9 @@ function importKey(keyBytes_1) {
963
967
  name: ENCRYPTION_ALGORITHM
964
968
  };
965
969
  let usage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'encrypt';
966
- let extractable = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
967
970
  return function* () {
968
971
  // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey
969
- return crypto.subtle.importKey('raw', keyBytes, algorithm, extractable, usage === 'derive' ? ['deriveBits', 'deriveKey'] : ['encrypt', 'decrypt']);
972
+ return crypto.subtle.importKey('raw', keyBytes, algorithm, false, usage === 'derive' ? ['deriveBits', 'deriveKey'] : ['encrypt', 'decrypt']);
970
973
  }();
971
974
  });
972
975
  }
@@ -1418,11 +1421,12 @@ class FrameCryptor extends BaseFrameCryptor {
1418
1421
  if (ratchetOpts.ratchetCount < _this.keyProviderOptions.ratchetWindowSize) {
1419
1422
  workerLogger.debug("ratcheting key attempt ".concat(ratchetOpts.ratchetCount, " of ").concat(_this.keyProviderOptions.ratchetWindowSize, ", for kind ").concat(encodedFrame instanceof RTCEncodedAudioFrame ? 'audio' : 'video'));
1420
1423
  let ratchetedKeySet;
1424
+ let ratchetResult;
1421
1425
  if ((initialMaterial !== null && initialMaterial !== void 0 ? initialMaterial : keySet) === _this.keys.getKeySet(keyIndex)) {
1422
1426
  // only ratchet if the currently set key is still the same as the one used to decrypt this frame
1423
1427
  // if not, it might be that a different frame has already ratcheted and we try with that one first
1424
- const newMaterial = yield _this.keys.ratchetKey(keyIndex, false);
1425
- ratchetedKeySet = yield deriveKeys(newMaterial, _this.keyProviderOptions.ratchetSalt);
1428
+ ratchetResult = yield _this.keys.ratchetKey(keyIndex, false);
1429
+ ratchetedKeySet = yield deriveKeys(ratchetResult.cryptoKey, _this.keyProviderOptions.ratchetSalt);
1426
1430
  }
1427
1431
  const frame = yield _this.decryptFrame(encodedFrame, keyIndex, initialMaterial || keySet, {
1428
1432
  ratchetCount: ratchetOpts.ratchetCount + 1,
@@ -1432,7 +1436,7 @@ class FrameCryptor extends BaseFrameCryptor {
1432
1436
  // before updating the keys, make sure that the keySet used for this frame is still the same as the currently set key
1433
1437
  // if it's not, a new key might have been set already, which we don't want to override
1434
1438
  if ((initialMaterial !== null && initialMaterial !== void 0 ? initialMaterial : keySet) === _this.keys.getKeySet(keyIndex)) {
1435
- _this.keys.setKeySet(ratchetedKeySet, keyIndex, true);
1439
+ _this.keys.setKeySet(ratchetedKeySet, keyIndex, ratchetResult);
1436
1440
  // decryption was successful, set the new key index to reflect the ratcheted key set
1437
1441
  _this.keys.setCurrentKeyIndex(keyIndex);
1438
1442
  }
@@ -1720,12 +1724,10 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1720
1724
  * returns the ratcheted material
1721
1725
  * if `setKey` is true (default), it will also set the ratcheted key directly on the crypto key ring
1722
1726
  * @param keyIndex
1723
- * @param setKey set the new key. Will emit KeyHandlerEvent.KeyRatcheted after key generation (default: true)
1724
- * @param extractable allow key extraction (get the key in plaintext) on the ratcheted new key (default: false)
1727
+ * @param setKey
1725
1728
  */
1726
1729
  ratchetKey(keyIndex) {
1727
1730
  let setKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
1728
- let extractable = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1729
1731
  const currentKeyIndex = keyIndex !== null && keyIndex !== void 0 ? keyIndex : this.getCurrentKeyIndex();
1730
1732
  const existingPromise = this.ratchetPromiseMap.get(currentKeyIndex);
1731
1733
  if (typeof existingPromise !== 'undefined') {
@@ -1738,12 +1740,17 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1738
1740
  throw new TypeError("Cannot ratchet key without a valid keyset of participant ".concat(this.participantIdentity));
1739
1741
  }
1740
1742
  const currentMaterial = keySet.material;
1741
- const newMaterial = yield importKey(yield ratchet(currentMaterial, this.keyProviderOptions.ratchetSalt), currentMaterial.algorithm.name, 'derive', extractable);
1743
+ const chainKey = yield ratchet(currentMaterial, this.keyProviderOptions.ratchetSalt);
1744
+ const newMaterial = yield importKey(chainKey, currentMaterial.algorithm.name, 'derive');
1745
+ const ratchetResult = {
1746
+ chainKey,
1747
+ cryptoKey: newMaterial
1748
+ };
1742
1749
  if (setKey) {
1743
- yield this.setKeyFromMaterial(newMaterial, currentKeyIndex, true);
1744
- this.emit(KeyHandlerEvent.KeyRatcheted, newMaterial, this.participantIdentity, currentKeyIndex);
1750
+ // Set the new key and emit a ratchet event with the ratcheted chain key
1751
+ yield this.setKeyFromMaterial(newMaterial, currentKeyIndex, ratchetResult);
1745
1752
  }
1746
- resolve(newMaterial);
1753
+ resolve(ratchetResult);
1747
1754
  } catch (e) {
1748
1755
  reject(e);
1749
1756
  } finally {
@@ -1778,7 +1785,7 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1778
1785
  setKeyFromMaterial(material_1, keyIndex_1) {
1779
1786
  return __awaiter(this, arguments, void 0, function (material, keyIndex) {
1780
1787
  var _this2 = this;
1781
- let emitRatchetEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1788
+ let ratchetedResult = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
1782
1789
  return function* () {
1783
1790
  const keySet = yield deriveKeys(material, _this2.keyProviderOptions.ratchetSalt);
1784
1791
  const newIndex = keyIndex >= 0 ? keyIndex % _this2.cryptoKeyRing.length : _this2.currentKeyIndex;
@@ -1787,16 +1794,16 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1787
1794
  algorithm: material.algorithm,
1788
1795
  ratchetSalt: _this2.keyProviderOptions.ratchetSalt
1789
1796
  });
1790
- _this2.setKeySet(keySet, newIndex, emitRatchetEvent);
1797
+ _this2.setKeySet(keySet, newIndex, ratchetedResult);
1791
1798
  if (newIndex >= 0) _this2.currentKeyIndex = newIndex;
1792
1799
  }();
1793
1800
  });
1794
1801
  }
1795
1802
  setKeySet(keySet, keyIndex) {
1796
- let emitRatchetEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1803
+ let ratchetedResult = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
1797
1804
  this.cryptoKeyRing[keyIndex % this.cryptoKeyRing.length] = keySet;
1798
- if (emitRatchetEvent) {
1799
- this.emit(KeyHandlerEvent.KeyRatcheted, keySet.material, this.participantIdentity, keyIndex);
1805
+ if (ratchetedResult) {
1806
+ this.emit(KeyHandlerEvent.KeyRatcheted, ratchetedResult, this.participantIdentity, keyIndex);
1800
1807
  }
1801
1808
  }
1802
1809
  setCurrentKeyIndex(index) {
@@ -1901,11 +1908,11 @@ function handleRatchetRequest(data) {
1901
1908
  return __awaiter(this, void 0, void 0, function* () {
1902
1909
  if (useSharedKey) {
1903
1910
  const keyHandler = getSharedKeyHandler();
1904
- yield keyHandler.ratchetKey(data.keyIndex, true, data.extractable);
1911
+ yield keyHandler.ratchetKey(data.keyIndex);
1905
1912
  keyHandler.resetKeyStatus();
1906
1913
  } else if (data.participantIdentity) {
1907
1914
  const keyHandler = getParticipantKeyHandler(data.participantIdentity);
1908
- yield keyHandler.ratchetKey(data.keyIndex, true, data.extractable);
1915
+ yield keyHandler.ratchetKey(data.keyIndex);
1909
1916
  keyHandler.resetKeyStatus();
1910
1917
  } else {
1911
1918
  workerLogger.error('no participant Id was provided for ratchet request and shared key usage is disabled');
@@ -2009,13 +2016,13 @@ function setupCryptorErrorEvents(cryptor) {
2009
2016
  postMessage(msg);
2010
2017
  });
2011
2018
  }
2012
- function emitRatchetedKeys(material, participantIdentity, keyIndex) {
2019
+ function emitRatchetedKeys(ratchetResult, participantIdentity, keyIndex) {
2013
2020
  const msg = {
2014
2021
  kind: "ratchetKey",
2015
2022
  data: {
2016
2023
  participantIdentity,
2017
2024
  keyIndex,
2018
- material
2025
+ ratchetResult
2019
2026
  }
2020
2027
  };
2021
2028
  postMessage(msg);