Skip to content

Commit

Permalink
Remove manual device verification which is not supported by the new c…
Browse files Browse the repository at this point in the history
…ryptography stack (element-hq#28588)

* Remove call of `MatrixClient.setDeviceVerified`

* Replace usage of deprecated crypto events

* Replace deprecated imports

* Remove legacy button in `UntrustedDeviceDialog`

* Review fixes

* Add tests

* Fix doc
  • Loading branch information
florianduros authored Dec 3, 2024
1 parent b72c053 commit d2acce1
Show file tree
Hide file tree
Showing 15 changed files with 237 additions and 527 deletions.
6 changes: 3 additions & 3 deletions src/SecurityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Please see LICENSE files in the repository root for full details.
*/

import { lazy } from "react";
import { ICryptoCallbacks, SecretStorage } from "matrix-js-sdk/src/matrix";
import { deriveRecoveryKeyFromPassphrase, decodeRecoveryKey } from "matrix-js-sdk/src/crypto-api";
import { SecretStorage } from "matrix-js-sdk/src/matrix";
import { deriveRecoveryKeyFromPassphrase, decodeRecoveryKey, CryptoCallbacks } from "matrix-js-sdk/src/crypto-api";
import { logger } from "matrix-js-sdk/src/logger";

import Modal from "./Modal";
Expand Down Expand Up @@ -159,7 +159,7 @@ function cacheSecretStorageKey(
}
}

export const crossSigningCallbacks: ICryptoCallbacks = {
export const crossSigningCallbacks: CryptoCallbacks = {
getSecretStorageKey,
cacheSecretStorageKey,
};
Expand Down
64 changes: 0 additions & 64 deletions src/SlashCommands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import VoipUserMapper from "./VoipUserMapper";
import { htmlSerializeFromMdIfNeeded } from "./editor/serialize";
import { leaveRoomBehaviour } from "./utils/leave-behaviour";
import { MatrixClientPeg } from "./MatrixClientPeg";
import { getDeviceCryptoInfo } from "./utils/crypto/deviceInfo";
import { isCurrentLocalRoom, reject, singleMxcUpload, success, successSync } from "./slash-commands/utils";
import { deop, op } from "./slash-commands/op";
import { CommandCategories } from "./slash-commands/interface";
Expand Down Expand Up @@ -658,69 +657,6 @@ export const Commands = [
category: CommandCategories.admin,
renderingTypes: [TimelineRenderingType.Room],
}),
new Command({
command: "verify",
args: "<user-id> <device-id> <device-signing-key>",
description: _td("slash_command|verify"),
runFn: function (cli, roomId, threadId, args) {
if (args) {
const matches = args.match(/^(\S+) +(\S+) +(\S+)$/);
if (matches) {
const userId = matches[1];
const deviceId = matches[2];
const fingerprint = matches[3];

return success(
(async (): Promise<void> => {
const device = await getDeviceCryptoInfo(cli, userId, deviceId);
if (!device) {
throw new UserFriendlyError("slash_command|verify_unknown_pair", {
userId,
deviceId,
cause: undefined,
});
}
const deviceTrust = await cli.getCrypto()?.getDeviceVerificationStatus(userId, deviceId);

if (deviceTrust?.isVerified()) {
if (device.getFingerprint() === fingerprint) {
throw new UserFriendlyError("slash_command|verify_nop");
} else {
throw new UserFriendlyError("slash_command|verify_nop_warning_mismatch");
}
}

if (device.getFingerprint() !== fingerprint) {
const fprint = device.getFingerprint();
throw new UserFriendlyError("slash_command|verify_mismatch", {
fprint,
userId,
deviceId,
fingerprint,
cause: undefined,
});
}

await cli.setDeviceVerified(userId, deviceId, true);

// Tell the user we verified everything
Modal.createDialog(InfoDialog, {
title: _t("slash_command|verify_success_title"),
description: (
<div>
<p>{_t("slash_command|verify_success_description", { userId, deviceId })}</p>
</div>
),
});
})(),
);
}
}
return reject(this.getUsage());
},
category: CommandCategories.advanced,
renderingTypes: [TimelineRenderingType.Room],
}),
new Command({
command: "discardsession",
description: _td("slash_command|discardsession"),
Expand Down
90 changes: 0 additions & 90 deletions src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx

This file was deleted.

18 changes: 13 additions & 5 deletions src/components/views/dialogs/UntrustedDeviceDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@ import BaseDialog from "./BaseDialog";
import { IDevice } from "../right_panel/UserInfo";

interface IProps {
/**
* The user whose device is untrusted.
*/
user: User;
/**
* The device that is untrusted.
*/
device: IDevice;
onFinished(mode?: "legacy" | "sas" | false): void;
/**
* Callback for when the dialog is dismissed.
* If mode is "sas", the user wants to verify the device with SAS. Otherwise, the dialog was dismissed normally.
* @param mode The mode of dismissal.
*/
onFinished(mode?: "sas"): void;
}

const UntrustedDeviceDialog: React.FC<IProps> = ({ device, user, onFinished }) => {
Expand Down Expand Up @@ -56,13 +67,10 @@ const UntrustedDeviceDialog: React.FC<IProps> = ({ device, user, onFinished }) =
<p>{askToVerifyText}</p>
</div>
<div className="mx_Dialog_buttons">
<AccessibleButton kind="primary_outline" onClick={() => onFinished("legacy")}>
{_t("encryption|udd|manual_verification_button")}
</AccessibleButton>
<AccessibleButton kind="primary_outline" onClick={() => onFinished("sas")}>
{_t("encryption|udd|interactive_verification_button")}
</AccessibleButton>
<AccessibleButton kind="primary" onClick={() => onFinished(false)}>
<AccessibleButton kind="primary" onClick={() => onFinished()}>
{_t("action|done")}
</AccessibleButton>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/useEncryptionStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

import { CryptoEvent, MatrixClient, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix";
import { MatrixClient, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix";
import { useEffect, useMemo, useState } from "react";
import { throttle } from "lodash";
import { CryptoEvent } from "matrix-js-sdk/src/crypto-api";

import { E2EStatus, shieldStatusForRoom } from "../utils/ShieldUtils";
import { useTypedEventEmitter } from "./useEventEmitter";
Expand Down
14 changes: 0 additions & 14 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,6 @@
},
"udd": {
"interactive_verification_button": "Interactively verify by emoji",
"manual_verification_button": "Manually verify by text",
"other_ask_verify_text": "Ask this user to verify their session, or manually verify it below.",
"other_new_session_text": "%(name)s (%(userId)s) signed in to a new session without verifying it:",
"own_ask_verify_text": "Verify your other session using one of the options below.",
Expand Down Expand Up @@ -957,12 +956,6 @@
"incoming_sas_dialog_waiting": "Waiting for partner to confirm…",
"incoming_sas_user_dialog_text_1": "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.",
"incoming_sas_user_dialog_text_2": "Verifying this user will mark their session as trusted, and also mark your session as trusted to them.",
"manual_device_verification_device_id_label": "Session ID",
"manual_device_verification_device_key_label": "Session key",
"manual_device_verification_device_name_label": "Session name",
"manual_device_verification_footer": "If they don't match, the security of your communication may be compromised.",
"manual_device_verification_self_text": "Confirm by comparing the following with the User Settings in your other session:",
"manual_device_verification_user_text": "Confirm this user's session by comparing the following with their User Settings:",
"no_key_or_device": "It looks like you don't have a Security Key or any other devices you can verify against. This device will not be able to access old encrypted messages. In order to verify your identity on this device, you'll need to reset your verification keys.",
"no_support_qr_emoji": "The device you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.",
"other_party_cancelled": "The other party cancelled the verification.",
Expand Down Expand Up @@ -3036,13 +3029,6 @@
"upgraderoom": "Upgrades a room to a new version",
"upgraderoom_permission_error": "You do not have the required permissions to use this command.",
"usage": "Usage",
"verify": "Verifies a user, session, and pubkey tuple",
"verify_mismatch": "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!",
"verify_nop": "Session already verified!",
"verify_nop_warning_mismatch": "WARNING: session already verified, but keys do NOT MATCH!",
"verify_success_description": "The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.",
"verify_success_title": "Verified key",
"verify_unknown_pair": "Unknown (user, session) pair: (%(userId)s, %(deviceId)s)",
"view": "Views room with given address",
"whois": "Displays information about a user"
},
Expand Down
7 changes: 4 additions & 3 deletions src/rageshake/submit-rageshake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Please see LICENSE files in the repository root for full details.
*/

import { logger } from "matrix-js-sdk/src/logger";
import { Method, MatrixClient, Crypto } from "matrix-js-sdk/src/matrix";
import { Method, MatrixClient } from "matrix-js-sdk/src/matrix";
import { CryptoApi } from "matrix-js-sdk/src/crypto-api";

import type * as Pako from "pako";
import { MatrixClientPeg } from "../MatrixClientPeg";
Expand Down Expand Up @@ -169,7 +170,7 @@ async function collectSynapseSpecific(client: MatrixClient, body: FormData): Pro
/**
* Collects crypto related information.
*/
async function collectCryptoInfo(cryptoApi: Crypto.CryptoApi, body: FormData): Promise<void> {
async function collectCryptoInfo(cryptoApi: CryptoApi, body: FormData): Promise<void> {
body.append("crypto_version", cryptoApi.getVersion());

const ownDeviceKeys = await cryptoApi.getOwnDeviceKeys();
Expand Down Expand Up @@ -198,7 +199,7 @@ async function collectCryptoInfo(cryptoApi: Crypto.CryptoApi, body: FormData): P
/**
* Collects information about secret storage and backup.
*/
async function collectRecoveryInfo(client: MatrixClient, cryptoApi: Crypto.CryptoApi, body: FormData): Promise<void> {
async function collectRecoveryInfo(client: MatrixClient, cryptoApi: CryptoApi, body: FormData): Promise<void> {
const secretStorage = client.secretStorage;
body.append("secret_storage_ready", String(await cryptoApi.isSecretStorageReady()));
body.append("secret_storage_key_in_account", String(await secretStorage.hasKey()));
Expand Down
4 changes: 2 additions & 2 deletions src/utils/device/dehydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/

import { logger } from "matrix-js-sdk/src/logger";
import { Crypto } from "matrix-js-sdk/src/matrix";
import { CryptoApi } from "matrix-js-sdk/src/crypto-api";

import { MatrixClientPeg } from "../../MatrixClientPeg";

Expand All @@ -21,7 +21,7 @@ import { MatrixClientPeg } from "../../MatrixClientPeg";
*
* Dehydration can currently only be enabled by setting a flag in the .well-known file.
*/
async function deviceDehydrationEnabled(crypto: Crypto.CryptoApi | undefined): Promise<boolean> {
async function deviceDehydrationEnabled(crypto: CryptoApi | undefined): Promise<boolean> {
if (!crypto) {
return false;
}
Expand Down
6 changes: 0 additions & 6 deletions src/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { RightPanelPhases } from "./stores/right-panel/RightPanelStorePhases";
import { accessSecretStorage } from "./SecurityManager";
import UntrustedDeviceDialog from "./components/views/dialogs/UntrustedDeviceDialog";
import { IDevice } from "./components/views/right_panel/UserInfo";
import { ManualDeviceKeyVerificationDialog } from "./components/views/dialogs/ManualDeviceKeyVerificationDialog";
import RightPanelStore from "./stores/right-panel/RightPanelStore";
import { IRightPanelCardState } from "./stores/right-panel/RightPanelStoreIPanelState";
import { findDMForUser } from "./utils/dm/findDMForUser";
Expand Down Expand Up @@ -53,11 +52,6 @@ export async function verifyDevice(matrixClient: MatrixClient, user: User, devic
.getCrypto()
?.requestDeviceVerification(user.userId, device.deviceId);
setRightPanel({ member: user, verificationRequestPromise });
} else if (action === "legacy") {
Modal.createDialog(ManualDeviceKeyVerificationDialog, {
userId: user.userId,
device,
});
}
},
});
Expand Down
Loading

0 comments on commit d2acce1

Please sign in to comment.