diff --git a/.eslintrc.js b/.eslintrc.js index 327119f045..0f1335b586 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -115,13 +115,10 @@ module.exports = { "!matrix-js-sdk/src/extensible_events_v1/InvalidEventError", "!matrix-js-sdk/src/crypto", "!matrix-js-sdk/src/crypto/aes", - "!matrix-js-sdk/src/crypto/olmlib", "!matrix-js-sdk/src/crypto/crypto", "!matrix-js-sdk/src/crypto/keybackup", - "!matrix-js-sdk/src/crypto/RoomList", "!matrix-js-sdk/src/crypto/deviceinfo", "!matrix-js-sdk/src/crypto/key_passphrase", - "!matrix-js-sdk/src/crypto/CrossSigning", "!matrix-js-sdk/src/crypto/recoverykey", "!matrix-js-sdk/src/crypto/dehydration", "!matrix-js-sdk/src/oidc", diff --git a/src/DecryptionFailureTracker.ts b/src/DecryptionFailureTracker.ts index 548555cd1d..d16ddedbde 100644 --- a/src/DecryptionFailureTracker.ts +++ b/src/DecryptionFailureTracker.ts @@ -20,6 +20,7 @@ import { Error as ErrorEvent } from "@matrix-org/analytics-events/types/typescri import { DecryptionFailureCode } from "matrix-js-sdk/src/crypto-api"; import { PosthogAnalytics } from "./PosthogAnalytics"; +import { MEGOLM_ENCRYPTION_ALGORITHM } from "./utils/crypto"; /** The key that we use to store the `reportedEvents` bloom filter in localstorage */ const DECRYPTION_FAILURE_STORAGE_KEY = "mx_decryption_failure_event_ids"; @@ -207,7 +208,7 @@ export class DecryptionFailureTracker { */ private eventDecrypted(e: MatrixEvent, nowTs: number): void { // for now we only track megolm decryption failures - if (e.getWireContent().algorithm != "m.megolm.v1.aes-sha2") { + if (e.getWireContent().algorithm != MEGOLM_ENCRYPTION_ALGORITHM) { return; } const errCode = e.decryptionFailureReason; diff --git a/src/async-components/views/dialogs/security/NewRecoveryMethodDialog.tsx b/src/async-components/views/dialogs/security/NewRecoveryMethodDialog.tsx index 0778879976..cf5e7c61af 100644 --- a/src/async-components/views/dialogs/security/NewRecoveryMethodDialog.tsx +++ b/src/async-components/views/dialogs/security/NewRecoveryMethodDialog.tsx @@ -16,7 +16,7 @@ limitations under the License. */ import React from "react"; -import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup"; +import { KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import dis from "../../../../dispatcher/dispatcher"; @@ -28,7 +28,7 @@ import DialogButtons from "../../../../components/views/elements/DialogButtons"; import BaseDialog from "../../../../components/views/dialogs/BaseDialog"; interface IProps { - newVersionInfo: IKeyBackupInfo; + newVersionInfo: KeyBackupInfo; onFinished(): void; } diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 92e13786cf..d3bae478d8 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -31,7 +31,7 @@ import { defer, IDeferred, QueryDict } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; import { throttle } from "lodash"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; -import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup"; +import { KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; // what-input helps improve keyboard accessibility import "what-input"; @@ -1614,7 +1614,7 @@ export default class MatrixChat extends React.PureComponent { }); cli.on(CryptoEvent.KeyBackupFailed, async (errcode): Promise => { let haveNewVersion: boolean | undefined; - let newVersionInfo: IKeyBackupInfo | null = null; + let newVersionInfo: KeyBackupInfo | null = null; // if key backup is still enabled, there must be a new backup in place if (cli.getKeyBackupEnabled()) { haveNewVersion = true; diff --git a/src/components/structures/auth/SetupEncryptionBody.tsx b/src/components/structures/auth/SetupEncryptionBody.tsx index 684a7b5af4..d8b99b0aff 100644 --- a/src/components/structures/auth/SetupEncryptionBody.tsx +++ b/src/components/structures/auth/SetupEncryptionBody.tsx @@ -15,8 +15,7 @@ limitations under the License. */ import React from "react"; -import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup"; -import { VerificationRequest } from "matrix-js-sdk/src/crypto-api"; +import { KeyBackupInfo, VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; import { SecretStorageKeyDescription } from "matrix-js-sdk/src/secret-storage"; @@ -40,7 +39,7 @@ interface IProps { interface IState { phase?: Phase; verificationRequest: VerificationRequest | null; - backupInfo: IKeyBackupInfo | null; + backupInfo: KeyBackupInfo | null; lostKeys: boolean; } diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx b/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx index c535245e61..c9aade7b9e 100644 --- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx +++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx @@ -17,8 +17,9 @@ limitations under the License. import React, { ChangeEvent } from "react"; import { MatrixClient, MatrixError, SecretStorage } from "matrix-js-sdk/src/matrix"; -import { IKeyBackupInfo, IKeyBackupRestoreResult } from "matrix-js-sdk/src/crypto/keybackup"; +import { IKeyBackupRestoreResult } from "matrix-js-sdk/src/crypto/keybackup"; import { logger } from "matrix-js-sdk/src/logger"; +import { KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import { _t } from "../../../../languageHandler"; @@ -51,7 +52,7 @@ interface IProps { } interface IState { - backupInfo: IKeyBackupInfo | null; + backupInfo: KeyBackupInfo | null; backupKeyStored: Record | null; loading: boolean; loadError: boolean | null; @@ -246,7 +247,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { + private async restoreWithCachedKey(backupInfo: KeyBackupInfo | null): Promise { if (!backupInfo) return false; try { const recoverInfo = await MatrixClientPeg.safeGet().restoreKeyBackupWithCache( diff --git a/src/components/views/messages/EncryptionEvent.tsx b/src/components/views/messages/EncryptionEvent.tsx index df475d7de6..67ec020aa5 100644 --- a/src/components/views/messages/EncryptionEvent.tsx +++ b/src/components/views/messages/EncryptionEvent.tsx @@ -16,8 +16,8 @@ limitations under the License. import React, { forwardRef, useContext } from "react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; -import { IRoomEncryption } from "matrix-js-sdk/src/crypto/RoomList"; +import type { RoomEncryptionEventContent } from "matrix-js-sdk/src/types"; import { _t } from "../../../languageHandler"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import EventTileBubble from "./EventTileBubble"; @@ -25,30 +25,29 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext"; import DMRoomMap from "../../../utils/DMRoomMap"; import { objectHasDiff } from "../../../utils/objects"; import { isLocalRoom } from "../../../utils/localRoom/isLocalRoom"; +import { MEGOLM_ENCRYPTION_ALGORITHM } from "../../../utils/crypto"; interface IProps { mxEvent: MatrixEvent; timestamp?: JSX.Element; } -const ALGORITHM = "m.megolm.v1.aes-sha2"; - const EncryptionEvent = forwardRef(({ mxEvent, timestamp }, ref) => { const cli = useContext(MatrixClientContext); const roomId = mxEvent.getRoomId()!; const isRoomEncrypted = MatrixClientPeg.safeGet().isRoomEncrypted(roomId); - const prevContent = mxEvent.getPrevContent() as IRoomEncryption; - const content = mxEvent.getContent(); + const prevContent = mxEvent.getPrevContent() as RoomEncryptionEventContent; + const content = mxEvent.getContent(); // if no change happened then skip rendering this, a shallow check is enough as all known fields are top-level. if (!objectHasDiff(prevContent, content)) return null; // nop - if (content.algorithm === ALGORITHM && isRoomEncrypted) { + if (content.algorithm === MEGOLM_ENCRYPTION_ALGORITHM && isRoomEncrypted) { let subtitle: string; const dmPartner = DMRoomMap.shared().getUserIdForRoomId(roomId); const room = cli?.getRoom(roomId); - if (prevContent.algorithm === ALGORITHM) { + if (prevContent.algorithm === MEGOLM_ENCRYPTION_ALGORITHM) { subtitle = _t("timeline|m.room.encryption|parameters_changed"); } else if (dmPartner) { const displayName = room?.getMember(dmPartner)?.rawDisplayName || dmPartner; diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index d9839252f9..9d1de1f13d 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -34,7 +34,6 @@ import { KnownMembership } from "matrix-js-sdk/src/types"; import { UserVerificationStatus, VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; -import { UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning"; import dis from "../../../dispatcher/dispatcher"; import Modal from "../../../Modal"; @@ -1323,7 +1322,7 @@ export const useDevices = (userId: string): IDevice[] | undefined | null => { if (_userId !== userId) return; updateDevices(); }; - const onUserTrustStatusChanged = (_userId: string, trustLevel: UserTrustLevel): void => { + const onUserTrustStatusChanged = (_userId: string, trustLevel: UserVerificationStatus): void => { if (_userId !== userId) return; updateDevices(); }; diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 5682cce846..669e57a06a 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -35,8 +35,7 @@ import { import { logger } from "matrix-js-sdk/src/logger"; import { CallErrorCode } from "matrix-js-sdk/src/webrtc/call"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; -import { UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning"; -import { EventShieldColour, EventShieldReason } from "matrix-js-sdk/src/crypto-api"; +import { EventShieldColour, EventShieldReason, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api"; import { Tooltip } from "@vector-im/compound-web"; import ReplyChain from "../elements/ReplyChain"; @@ -577,7 +576,7 @@ export class UnwrappedEventTile extends React.Component } }; - private onUserVerificationChanged = (userId: string, _trustStatus: UserTrustLevel): void => { + private onUserVerificationChanged = (userId: string, _trustStatus: UserVerificationStatus): void => { if (userId === this.props.mxEvent.getSender()) { this.verifyEvent(); } diff --git a/src/components/views/rooms/MemberTile.tsx b/src/components/views/rooms/MemberTile.tsx index 03aa186281..92c26ddd19 100644 --- a/src/components/views/rooms/MemberTile.tsx +++ b/src/components/views/rooms/MemberTile.tsx @@ -19,7 +19,7 @@ import React from "react"; import { RoomMember, RoomStateEvent, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; -import { UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning"; +import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api"; import dis from "../../../dispatcher/dispatcher"; import { _t } from "../../../languageHandler"; @@ -103,7 +103,7 @@ export default class MemberTile extends React.Component { this.updateE2EStatus(); }; - private onUserTrustStatusChanged = (userId: string, trustStatus: UserTrustLevel): void => { + private onUserTrustStatusChanged = (userId: string, trustStatus: UserVerificationStatus): void => { if (userId !== this.props.member.userId) return; this.updateE2EStatus(); }; diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index 6ac686e063..01fcbd1abb 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -50,6 +50,7 @@ import SettingsTab from "../SettingsTab"; import SdkConfig from "../../../../../SdkConfig"; import { shouldForceDisableEncryption } from "../../../../../utils/crypto/shouldForceDisableEncryption"; import { Caption } from "../../../typography/Caption"; +import { MEGOLM_ENCRYPTION_ALGORITHM } from "../../../../../utils/crypto"; interface IProps { room: Room; @@ -176,7 +177,7 @@ export default class SecurityRoomSettingsTab extends React.Component { logger.error(e); diff --git a/src/createRoom.ts b/src/createRoom.ts index 93ef63383f..ddb19bbdd7 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -50,6 +50,7 @@ import { shouldForceDisableEncryption } from "./utils/crypto/shouldForceDisableE import { waitForMember } from "./utils/membership"; import { PreferredRoomVersions } from "./utils/PreferredRoomVersions"; import SettingsStore from "./settings/SettingsStore"; +import { MEGOLM_ENCRYPTION_ALGORITHM } from "./utils/crypto"; // we define a number of interfaces which take their names from the js-sdk /* eslint-disable camelcase */ @@ -220,7 +221,7 @@ export default async function createRoom(client: MatrixClient, opts: IOpts): Pro type: "m.room.encryption", state_key: "", content: { - algorithm: "m.megolm.v1.aes-sha2", + algorithm: MEGOLM_ENCRYPTION_ALGORITHM, }, }); } diff --git a/src/customisations/Security.ts b/src/customisations/Security.ts index 7c387ab225..a5fdf09fb1 100644 --- a/src/customisations/Security.ts +++ b/src/customisations/Security.ts @@ -13,8 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ - -import { ICryptoCallbacks } from "matrix-js-sdk/src/crypto"; +import { CryptoCallbacks } from "matrix-js-sdk/src/crypto-api"; import { IMatrixClientCreds } from "../MatrixClientPeg"; import { Kind as SetupEncryptionKind } from "../toasts/SetupEncryptionToast"; @@ -62,7 +61,7 @@ export interface ISecurityCustomisations { getSecretStorageKey?: typeof getSecretStorageKey; catchAccessSecretStorageError?: typeof catchAccessSecretStorageError; setupEncryptionNeeded?: typeof setupEncryptionNeeded; - getDehydrationKey?: ICryptoCallbacks["getDehydrationKey"]; + getDehydrationKey?: CryptoCallbacks["getDehydrationKey"]; /** * When false, disables the post-login UI from showing. If there's diff --git a/src/stores/SetupEncryptionStore.ts b/src/stores/SetupEncryptionStore.ts index e3069d4333..640ef2c7a4 100644 --- a/src/stores/SetupEncryptionStore.ts +++ b/src/stores/SetupEncryptionStore.ts @@ -15,8 +15,12 @@ limitations under the License. */ import EventEmitter from "events"; -import { VerificationPhase, VerificationRequest, VerificationRequestEvent } from "matrix-js-sdk/src/crypto-api"; -import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup"; +import { + KeyBackupInfo, + VerificationPhase, + VerificationRequest, + VerificationRequestEvent, +} from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; import { Device, SecretStorage } from "matrix-js-sdk/src/matrix"; @@ -44,7 +48,7 @@ export class SetupEncryptionStore extends EventEmitter { private started?: boolean; public phase?: Phase; public verificationRequest: VerificationRequest | null = null; - public backupInfo: IKeyBackupInfo | null = null; + public backupInfo: KeyBackupInfo | null = null; // ID of the key that the secrets we want are encrypted with public keyId: string | null = null; // Descriptor of the key that the secrets we want are encrypted with diff --git a/src/utils/crypto/index.ts b/src/utils/crypto/index.ts new file mode 100644 index 0000000000..5040a2f263 --- /dev/null +++ b/src/utils/crypto/index.ts @@ -0,0 +1,19 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** The `algorithm` property used in `m.room.encrypted` state events for encrypted rooms. + */ +export const MEGOLM_ENCRYPTION_ALGORITHM = "m.megolm.v1.aes-sha2"; diff --git a/src/utils/dm/createDmLocalRoom.ts b/src/utils/dm/createDmLocalRoom.ts index ffc76550c7..c6bff15af0 100644 --- a/src/utils/dm/createDmLocalRoom.ts +++ b/src/utils/dm/createDmLocalRoom.ts @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { MEGOLM_ALGORITHM } from "matrix-js-sdk/src/crypto/olmlib"; import { EventType, KNOWN_SAFE_ROOM_VERSION, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; -import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../../src/models/LocalRoom"; +import { LOCAL_ROOM_ID_PREFIX, LocalRoom } from "../../../src/models/LocalRoom"; import { determineCreateRoomEncryptionOption, Member } from "../../../src/utils/direct-messages"; +import { MEGOLM_ENCRYPTION_ALGORITHM } from "../crypto"; /** * Create a DM local room. This room will not be send to the server and only exists inside the client. @@ -59,7 +59,7 @@ export async function createDmLocalRoom(client: MatrixClient, targets: Member[]) event_id: `~${localRoom.roomId}:${client.makeTxnId()}`, type: EventType.RoomEncryption, content: { - algorithm: MEGOLM_ALGORITHM, + algorithm: MEGOLM_ENCRYPTION_ALGORITHM, }, sender: userId, state_key: "", diff --git a/test/DeviceListener-test.ts b/test/DeviceListener-test.ts index 6c1c059cdd..4a2df70e67 100644 --- a/test/DeviceListener-test.ts +++ b/test/DeviceListener-test.ts @@ -18,7 +18,6 @@ import { Mocked, mocked } from "jest-mock"; import { MatrixEvent, Room, MatrixClient, Device, ClientStoppedError } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; -import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup"; import { CryptoSessionStateChange } from "@matrix-org/analytics-events/types/typescript/CryptoSessionStateChange"; import { CrossSigningStatus, CryptoApi, DeviceVerificationStatus, KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; @@ -357,7 +356,7 @@ describe("DeviceListener", () => { it("shows upgrade encryption toast when user has a key backup available", async () => { // non falsy response - mockClient!.getKeyBackupVersion.mockResolvedValue({} as unknown as IKeyBackupInfo); + mockClient!.getKeyBackupVersion.mockResolvedValue({} as unknown as KeyBackupInfo); await createAndStart(); expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith( diff --git a/test/components/structures/RoomView-test.tsx b/test/components/structures/RoomView-test.tsx index 37351cc4e5..eb070b7afc 100644 --- a/test/components/structures/RoomView-test.tsx +++ b/test/components/structures/RoomView-test.tsx @@ -30,7 +30,6 @@ import { IEvent, } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; -import { MEGOLM_ALGORITHM } from "matrix-js-sdk/src/crypto/olmlib"; import { fireEvent, render, screen, RenderResult, waitForElementToBeRemoved, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; @@ -71,6 +70,7 @@ import { WidgetType } from "../../../src/widgets/WidgetType"; import WidgetStore from "../../../src/stores/WidgetStore"; import { ViewRoomErrorPayload } from "../../../src/dispatcher/payloads/ViewRoomErrorPayload"; import { SearchScope } from "../../../src/Searching"; +import { MEGOLM_ENCRYPTION_ALGORITHM } from "../../../src/utils/crypto"; const RoomView = wrapInMatrixClientContext(_RoomView); @@ -351,7 +351,7 @@ describe("RoomView", () => { event_id: `~${localRoom.roomId}:${cli.makeTxnId()}`, type: EventType.RoomEncryption, content: { - algorithm: MEGOLM_ALGORITHM, + algorithm: MEGOLM_ENCRYPTION_ALGORITHM, }, sender: cli.getUserId()!, state_key: "",