mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 11:22:31 +00:00
e2ee: stage 2
Adapt to E2EE changes in lib-jitsi-meet. Notably:
---
e2ee: introduce per-participant randomly generated keys
This the second stage in our E2EE journey.
Instead of using a single pre-shared passphrase for deriving the key used for
E2EE, we now establish a secure E2EE communication channel amongst peers.
This channel is implemented using libolm, using XMPP groupchat or JVB channels
as the transport.
Once the secure E2EE channel has been established each participant will generate
a random 32 byte key and exchange it over this channel.
Keys are rotated (well, just re-created at the moment) when a participant joins
or leaves.
---
This commit is contained in:
committed by
Saúl Ibarra Corretgé
parent
2b4f33bef8
commit
7cafa205ee
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* The type of the action which signals the E2EE key has changed.
|
||||
* The type of the action which signals that E2EE needs to be enabled / disabled.
|
||||
*
|
||||
* {
|
||||
* type: SET_E2EE_KEY
|
||||
* type: TOGGLE_E2EE
|
||||
* }
|
||||
*/
|
||||
export const SET_E2EE_KEY = 'SET_E2EE_KEY';
|
||||
export const TOGGLE_E2EE = 'TOGGLE_E2EE';
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
// @flow
|
||||
|
||||
import { SET_E2EE_KEY } from './actionTypes';
|
||||
import { TOGGLE_E2EE } from './actionTypes';
|
||||
|
||||
/**
|
||||
* Dispatches an action to set the E2EE key.
|
||||
* Dispatches an action to enable / disable E2EE.
|
||||
*
|
||||
* @param {string|undefined} key - The new key to be used for E2EE.
|
||||
* @param {boolean} enabled - Whether E2EE is to be enabled or not.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function setE2EEKey(key: ?string) {
|
||||
export function toggleE2EE(enabled: boolean) {
|
||||
return {
|
||||
type: SET_E2EE_KEY,
|
||||
key
|
||||
type: TOGGLE_E2EE,
|
||||
enabled
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,22 +6,23 @@ import type { Dispatch } from 'redux';
|
||||
import { createE2EEEvent, sendAnalytics } from '../../analytics';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { getParticipants } from '../../base/participants';
|
||||
import { Switch } from '../../base/react';
|
||||
import { connect } from '../../base/redux';
|
||||
import { setE2EEKey } from '../actions';
|
||||
import { toggleE2EE } from '../actions';
|
||||
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether E2EE is currently enabled or not.
|
||||
*/
|
||||
_enabled: boolean,
|
||||
|
||||
/**
|
||||
* Indicates whether all participants in the conference currently support E2EE.
|
||||
*/
|
||||
_everyoneSupportsE2EE: boolean,
|
||||
|
||||
/**
|
||||
* The current E2EE key.
|
||||
*/
|
||||
_key: string,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
*/
|
||||
@@ -36,19 +37,14 @@ type Props = {
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* True if the key is being edited.
|
||||
* True if the switch is toggled on.
|
||||
*/
|
||||
editing: boolean,
|
||||
enabled: boolean,
|
||||
|
||||
/**
|
||||
* True if the section description should be expanded, false otherwise.
|
||||
*/
|
||||
expand: boolean,
|
||||
|
||||
/**
|
||||
* The current E2EE key.
|
||||
*/
|
||||
key: string
|
||||
expand: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -58,30 +54,38 @@ type State = {
|
||||
* @extends Component
|
||||
*/
|
||||
class E2EESection extends Component<Props, State> {
|
||||
fieldRef: Object;
|
||||
/**
|
||||
* Implements React's {@link Component#getDerivedStateFromProps()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static getDerivedStateFromProps(props: Props, state: Object) {
|
||||
if (props._enabled !== state.enabled) {
|
||||
|
||||
return {
|
||||
enabled: props._enabled
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new {@code E2EEDialog } instance.
|
||||
* Instantiates a new component.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.fieldRef = React.createRef();
|
||||
|
||||
this.state = {
|
||||
editing: false,
|
||||
expand: false,
|
||||
key: this.props._key
|
||||
enabled: false,
|
||||
expand: false
|
||||
};
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onExpand = this._onExpand.bind(this);
|
||||
this._onKeyChange = this._onKeyChange.bind(this);
|
||||
this._onSet = this._onSet.bind(this);
|
||||
this._onToggleSetKey = this._onToggleSetKey.bind(this);
|
||||
this._onToggle = this._onToggle.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +96,7 @@ class E2EESection extends Component<Props, State> {
|
||||
*/
|
||||
render() {
|
||||
const { _everyoneSupportsE2EE, t } = this.props;
|
||||
const { editing, expand } = this.state;
|
||||
const { enabled, expand } = this.state;
|
||||
const description = t('dialog.e2eeDescription');
|
||||
|
||||
return (
|
||||
@@ -112,25 +116,13 @@ class E2EESection extends Component<Props, State> {
|
||||
{ t('dialog.e2eeWarning') }
|
||||
</span>
|
||||
}
|
||||
<div className = 'key-field'>
|
||||
<div className = 'control-row'>
|
||||
<label>
|
||||
{ t('dialog.e2eeLabel') }:
|
||||
{ t('dialog.e2eeLabel') }
|
||||
</label>
|
||||
<input
|
||||
disabled = { !editing }
|
||||
name = 'e2eeKey'
|
||||
onChange = { this._onKeyChange }
|
||||
onKeyDown = { this._onKeyDown }
|
||||
placeholder = { t('dialog.e2eeNoKey') }
|
||||
ref = { this.fieldRef }
|
||||
type = 'password'
|
||||
value = { this.state.key } />
|
||||
{ editing && <a onClick = { this._onSet }>
|
||||
{ t('dialog.e2eeSet') }
|
||||
</a> }
|
||||
{ !editing && <a onClick = { this._onToggleSetKey }>
|
||||
{ t('dialog.e2eeToggleSet') }
|
||||
</a> }
|
||||
<Switch
|
||||
onValueChange = { this._onToggle }
|
||||
value = { enabled } />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -149,65 +141,23 @@ class E2EESection extends Component<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
_onKeyChange: (Object) => void;
|
||||
_onToggle: () => void;
|
||||
|
||||
/**
|
||||
* Updates the entered key.
|
||||
*
|
||||
* @param {Object} event - The DOM event triggered from the entered value having changed.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onKeyChange(event) {
|
||||
this.setState({ key: event.target.value.trim() });
|
||||
}
|
||||
|
||||
_onKeyDown: (Object) => void;
|
||||
|
||||
/**
|
||||
* Handler for the keydown event on the form, preventing the closing of the dialog.
|
||||
*
|
||||
* @param {Object} event - The DOM event triggered by keydown events.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onKeyDown(event) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
_onSet: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action to set/unset the E2EE key.
|
||||
* Callback to be invoked when the user toggles E2EE on or off.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onSet() {
|
||||
const { key } = this.state;
|
||||
|
||||
sendAnalytics(createE2EEEvent(`key.${key ? 'set' : 'unset'}`));
|
||||
this.props.dispatch(setE2EEKey(key));
|
||||
_onToggle() {
|
||||
const newValue = !this.state.enabled;
|
||||
|
||||
this.setState({
|
||||
editing: false
|
||||
enabled: newValue
|
||||
});
|
||||
}
|
||||
|
||||
_onToggleSetKey: () => void;
|
||||
|
||||
/**
|
||||
* Sets the section into edit mode so then the user can set the key.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onToggleSetKey() {
|
||||
this.setState({
|
||||
editing: true
|
||||
}, () => {
|
||||
this.fieldRef.current.focus();
|
||||
});
|
||||
sendAnalytics(createE2EEEvent(`enabled.${String(newValue)}`));
|
||||
this.props.dispatch(toggleE2EE(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,12 +169,12 @@ class E2EESection extends Component<Props, State> {
|
||||
* @returns {Props}
|
||||
*/
|
||||
function mapStateToProps(state) {
|
||||
const { e2eeKey } = state['features/e2ee'];
|
||||
const { enabled } = state['features/e2ee'];
|
||||
const participants = getParticipants(state).filter(p => !p.local);
|
||||
|
||||
return {
|
||||
_everyoneSupportsE2EE: participants.every(p => Boolean(p.e2eeSupported)),
|
||||
_key: e2eeKey || ''
|
||||
_enabled: enabled,
|
||||
_everyoneSupportsE2EE: participants.every(p => Boolean(p.e2eeSupported))
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import { getCurrentConference } from '../base/conference';
|
||||
import { getLocalParticipant, participantUpdated } from '../base/participants';
|
||||
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
|
||||
|
||||
import { SET_E2EE_KEY } from './actionTypes';
|
||||
import { setE2EEKey } from './actions';
|
||||
import { TOGGLE_E2EE } from './actionTypes';
|
||||
import { toggleE2EE } from './actions';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
@@ -16,18 +16,18 @@ import logger from './logger';
|
||||
*/
|
||||
MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
||||
switch (action.type) {
|
||||
case SET_E2EE_KEY: {
|
||||
case TOGGLE_E2EE: {
|
||||
const conference = getCurrentConference(getState);
|
||||
|
||||
if (conference) {
|
||||
logger.debug(`New E2EE key: ${action.key}`);
|
||||
conference.setE2EEKey(action.key);
|
||||
logger.debug(`E2EE will be ${action.enabled ? 'enabled' : 'disabled'}`);
|
||||
conference.toggleE2EE(action.enabled);
|
||||
|
||||
// Broadccast that we enabled / disabled E2EE.
|
||||
const participant = getLocalParticipant(getState);
|
||||
|
||||
dispatch(participantUpdated({
|
||||
e2eeEnabled: Boolean(action.key),
|
||||
e2eeEnabled: action.enabled,
|
||||
id: participant.id,
|
||||
local: true
|
||||
}));
|
||||
@@ -48,6 +48,6 @@ StateListenerRegistry.register(
|
||||
state => getCurrentConference(state),
|
||||
(conference, { dispatch }, previousConference) => {
|
||||
if (previousConference) {
|
||||
dispatch(setE2EEKey(undefined));
|
||||
dispatch(toggleE2EE(false));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,14 +2,10 @@
|
||||
|
||||
import { ReducerRegistry } from '../base/redux';
|
||||
|
||||
import { SET_E2EE_KEY } from './actionTypes';
|
||||
import { TOGGLE_E2EE } from './actionTypes';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
|
||||
/**
|
||||
* E2EE key.
|
||||
*/
|
||||
e2eeKey: undefined
|
||||
enabled: false
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -17,10 +13,10 @@ const DEFAULT_STATE = {
|
||||
*/
|
||||
ReducerRegistry.register('features/e2ee', (state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case SET_E2EE_KEY:
|
||||
case TOGGLE_E2EE:
|
||||
return {
|
||||
...state,
|
||||
e2eeKey: action.key
|
||||
enabled: action.enabled
|
||||
};
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user