您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

ManagedKeyHandler.js 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. import { getLogger } from '@jitsi/logger';
  2. import debounce from 'lodash.debounce';
  3. import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
  4. import { KeyHandler } from './KeyHandler';
  5. import { OlmAdapter } from './OlmAdapter';
  6. import { importKey, ratchet } from './crypto-utils';
  7. const logger = getLogger(__filename);
  8. // Period which we'll wait before updating / rotating our keys when a participant
  9. // joins or leaves.
  10. const DEBOUNCE_PERIOD = 5000;
  11. /**
  12. * This module integrates {@link E2EEContext} with {@link OlmAdapter} in order to distribute the keys for encryption.
  13. */
  14. export class ManagedKeyHandler extends KeyHandler {
  15. /**
  16. * Build a new AutomaticKeyHandler instance, which will be used in a given conference.
  17. */
  18. constructor(conference) {
  19. super(conference);
  20. if (glob_rx?.ljm?.i){
  21. glob_rx.ljm.i.mkh_inst = this
  22. clog("ManagedKeyHandler ljm constructed,")
  23. }
  24. this._key = undefined;
  25. this._conferenceJoined = false;
  26. this._olmAdapter = new OlmAdapter(conference);
  27. this._rotateKey = debounce(this._rotateKeyImpl, DEBOUNCE_PERIOD);
  28. this._ratchetKey = debounce(this._ratchetKeyImpl, DEBOUNCE_PERIOD);
  29. // Olm signalling events.
  30. this._olmAdapter.on(
  31. OlmAdapter.events.PARTICIPANT_KEY_UPDATED,
  32. this._onParticipantKeyUpdated.bind(this));
  33. this._olmAdapter.on(
  34. OlmAdapter.events.PARTICIPANT_SAS_READY,
  35. this._onParticipantSasReady.bind(this));
  36. this._olmAdapter.on(
  37. OlmAdapter.events.PARTICIPANT_SAS_AVAILABLE,
  38. this._onParticipantSasAvailable.bind(this));
  39. this._olmAdapter.on(
  40. OlmAdapter.events.PARTICIPANT_VERIFICATION_COMPLETED,
  41. this._onParticipantVerificationCompleted.bind(this));
  42. this.conference.on(
  43. JitsiConferenceEvents.PARTICIPANT_PROPERTY_CHANGED,
  44. this._onParticipantPropertyChanged.bind(this));
  45. this.conference.on(
  46. JitsiConferenceEvents.USER_JOINED,
  47. this._onParticipantJoined.bind(this));
  48. this.conference.on(
  49. JitsiConferenceEvents.USER_LEFT,
  50. this._onParticipantLeft.bind(this));
  51. this.conference.on(
  52. JitsiConferenceEvents.CONFERENCE_JOINED,
  53. () => {
  54. this._conferenceJoined = true;
  55. });
  56. }
  57. /**
  58. * Returns the sasVerficiation object.
  59. *
  60. * @returns {Object}
  61. */
  62. get sasVerification() {
  63. return this._olmAdapter;
  64. }
  65. /**
  66. * When E2EE is enabled it initializes sessions and sets the key.
  67. * Cleans up the sessions when disabled.
  68. *
  69. * @param {boolean} enabled - whether E2EE should be enabled or not.
  70. * @returns {void}
  71. */
  72. async _setEnabled(enabled) {
  73. if (enabled) {
  74. await this._olmAdapter.initSessions();
  75. } else {
  76. this._olmAdapter.clearAllParticipantsSessions();
  77. }
  78. // Generate a random key in case we are enabling.
  79. this._key = enabled ? this._generateKey() : false;
  80. // Send it to others using the E2EE olm channel.
  81. const index = await this._olmAdapter.updateKey(this._key);
  82. // Set our key so we begin encrypting.
  83. this.e2eeCtx.setKey(this.conference.myUserId(), this._key, index);
  84. }
  85. /**
  86. * Handles an update in a participant's presence property.
  87. *
  88. * @param {JitsiParticipant} participant - The participant.
  89. * @param {string} name - The name of the property that changed.
  90. * @param {*} oldValue - The property's previous value.
  91. * @param {*} newValue - The property's new value.
  92. * @private
  93. */
  94. async _onParticipantPropertyChanged(participant, name, oldValue, newValue) {
  95. switch (name) {
  96. case 'e2ee.idKey':
  97. logger.debug(`Participant ${participant.getId()} updated their id key: ${newValue}`);
  98. break;
  99. case 'e2ee.enabled':
  100. if (!newValue && this.enabled) {
  101. this._olmAdapter.clearParticipantSession(participant);
  102. }
  103. break;
  104. }
  105. }
  106. /**
  107. * Advances (using ratcheting) the current key when a new participant joins the conference.
  108. * @private
  109. */
  110. _onParticipantJoined() {
  111. if (this._conferenceJoined && this.enabled) {
  112. this._ratchetKey();
  113. }
  114. }
  115. /**
  116. * Rotates the current key when a participant leaves the conference.
  117. * @private
  118. */
  119. _onParticipantLeft(id) {
  120. this.e2eeCtx.cleanup(id);
  121. if (this.enabled) {
  122. this._rotateKey();
  123. }
  124. }
  125. /**
  126. * Rotates the local key. Rotating the key implies creating a new one, then distributing it
  127. * to all participants and once they all received it, start using it.
  128. *
  129. * @private
  130. */
  131. async _rotateKeyImpl() {
  132. console.log("ljm_dbg _rotateKeyImpl")
  133. logger.debug('Rotating key');
  134. this._key = this._generateKey();
  135. const index = await this._olmAdapter.updateKey(this._key);
  136. this.e2eeCtx.setKey(this.conference.myUserId(), this._key, index);
  137. }
  138. /**
  139. * Advances the current key by using ratcheting.
  140. *
  141. * @private
  142. */
  143. async _ratchetKeyImpl() {
  144. console.log("ljm_dbg _ratchetKeyImpl")
  145. logger.debug('Ratchetting key');
  146. const material = await importKey(this._key);
  147. const newKey = await ratchet(material);
  148. this._key = new Uint8Array(newKey);
  149. const index = this._olmAdapter.updateCurrentKey(this._key);
  150. this.e2eeCtx.setKey(this.conference.myUserId(), this._key, index);
  151. }
  152. /**
  153. * Handles an update in a participant's key.
  154. *
  155. * @param {string} id - The participant ID.
  156. * @param {Uint8Array | boolean} key - The new key for the participant.
  157. * @param {Number} index - The new key's index.
  158. * @private
  159. */
  160. _onParticipantKeyUpdated(id, key, index) {
  161. logger.debug(`Participant ${id} updated their key`);
  162. this.e2eeCtx.setKey(id, key, index);
  163. }
  164. /**
  165. * Handles the SAS ready event.
  166. *
  167. * @param {string} pId - The participant ID.
  168. * @param {Uint8Array} sas - The bytes from sas.generate_bytes..
  169. * @private
  170. */
  171. _onParticipantSasReady(pId, sas) {
  172. this.conference.eventEmitter.emit(JitsiConferenceEvents.E2EE_VERIFICATION_READY, pId, sas);
  173. }
  174. /**
  175. * Handles the sas available event.
  176. *
  177. * @param {string} pId - The participant ID.
  178. * @private
  179. */
  180. _onParticipantSasAvailable(pId) {
  181. this.conference.eventEmitter.emit(JitsiConferenceEvents.E2EE_VERIFICATION_AVAILABLE, pId);
  182. }
  183. /**
  184. * Handles the SAS completed event.
  185. *
  186. * @param {string} pId - The participant ID.
  187. * @param {boolean} success - Wheter the verification was succesfull.
  188. * @private
  189. */
  190. _onParticipantVerificationCompleted(pId, success, message) {
  191. this.conference.eventEmitter.emit(JitsiConferenceEvents.E2EE_VERIFICATION_COMPLETED, pId, success, message);
  192. }
  193. /**
  194. * Generates a new 256 bit random key.
  195. *
  196. * @returns {Uint8Array}
  197. * @private
  198. */
  199. _generateKey() {
  200. return window.crypto.getRandomValues(new Uint8Array(32));
  201. }
  202. }
  203. if (window?.glob_rx?.ljm?.j){
  204. glob_rx.ljm.j.mkh = {KeyHandler,OlmAdapter,importKey, ratchet,debounce,JitsiConferenceEvents,ManagedKeyHandler,}
  205. }