;
-}
-
-export interface ICapability {
- enabled: boolean;
-}
-
-export interface IChangePasswordCapability extends ICapability {}
-
-export interface IThreadsCapability extends ICapability {}
-
-export interface IGetLoginTokenCapability extends ICapability {}
-
export const GET_LOGIN_TOKEN_CAPABILITY = new NamespacedValue(
"m.get_login_token",
"org.matrix.msc3882.get_login_token",
@@ -547,18 +542,7 @@ export const UNSTABLE_MSC2666_SHARED_ROOMS = "uk.half-shot.msc2666";
export const UNSTABLE_MSC2666_MUTUAL_ROOMS = "uk.half-shot.msc2666.mutual_rooms";
export const UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS = "uk.half-shot.msc2666.query_mutual_rooms";
-/**
- * A representation of the capabilities advertised by a homeserver as defined by
- * [Capabilities negotiation](https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3capabilities).
- */
-export interface Capabilities {
- [key: string]: any;
- "m.change_password"?: IChangePasswordCapability;
- "m.room_versions"?: IRoomVersionsCapability;
- "io.element.thread"?: IThreadsCapability;
- "m.get_login_token"?: IGetLoginTokenCapability;
- "org.matrix.msc3882.get_login_token"?: IGetLoginTokenCapability;
-}
+export const UNSTABLE_MSC4140_DELAYED_EVENTS = "org.matrix.msc4140";
enum CrossSigningKeyType {
MasterKey = "master_key",
@@ -1108,7 +1092,7 @@ export type ClientEventHandlerMap = {
* });
* ```
*/
- [ClientEvent.Sync]: (state: SyncState, lastState: SyncState | null, data?: ISyncStateData) => void;
+ [ClientEvent.Sync]: (state: SyncState, prevState: SyncState | null, data?: ISyncStateData) => void;
/**
* Fires whenever the SDK receives a new event.
*
@@ -1293,10 +1277,6 @@ export class MatrixClient extends TypedEventEmitter;
- public cachedCapabilities?: {
- capabilities: Capabilities;
- expiration: number;
- };
protected clientWellKnown?: IClientWellKnown;
protected clientWellKnownPromise?: Promise;
protected turnServers: ITurnServer[] = [];
@@ -1325,6 +1305,8 @@ export class MatrixClient extends TypedEventEmitter {
- const now = new Date().getTime();
-
- if (this.cachedCapabilities && !fresh) {
- if (now < this.cachedCapabilities.expiration) {
- this.logger.debug("Returning cached capabilities");
- return Promise.resolve(this.cachedCapabilities.capabilities);
- }
- }
-
- type Response = {
- capabilities?: Capabilities;
- };
- return this.http
- .authedRequest(Method.Get, "/capabilities")
- .catch((e: Error): Response => {
- // We swallow errors because we need a default object anyhow
- this.logger.error(e);
- return {};
- })
- .then((r = {}) => {
- const capabilities = r["capabilities"] || {};
-
- // If the capabilities missed the cache, cache it for a shorter amount
- // of time to try and refresh them later.
- const cacheMs = Object.keys(capabilities).length ? CAPABILITIES_CACHE_MS : 60000 + Math.random() * 5000;
+ public async getCapabilities(): Promise {
+ const caps = this.serverCapabilitiesService.getCachedCapabilities();
+ if (caps) return caps;
+ return this.serverCapabilitiesService.fetchCapabilities();
+ }
- this.cachedCapabilities = {
- capabilities,
- expiration: now + cacheMs,
- };
+ /**
+ * Gets the cached capabilities of the homeserver. If none have been fetched yet,
+ * return undefined.
+ *
+ * @returns The capabilities of the homeserver
+ */
+ public getCachedCapabilities(): Capabilities | undefined {
+ return this.serverCapabilitiesService.getCachedCapabilities();
+ }
- this.logger.debug("Caching capabilities: ", capabilities);
- return capabilities;
- });
+ /**
+ * Fetches the latest capabilities from the homeserver, ignoring any cached
+ * versions. The newly returned version is cached.
+ *
+ * @returns A promise which resolves to the capabilities of the homeserver
+ */
+ public fetchCapabilities(): Promise {
+ return this.serverCapabilitiesService.fetchCapabilities();
}
/**
@@ -2274,9 +2249,7 @@ export class MatrixClient extends TypedEventEmitter(Method.Post, url);
}
- const queryString: Record = {};
+ let queryParams: QueryDict = {};
if (opts.viaServers) {
- queryString["server_name"] = opts.viaServers;
+ queryParams.server_name = opts.viaServers;
+ queryParams.via = opts.viaServers;
+ if (this.canSupport.get(Feature.MigrateServerNameToVia) === ServerSupport.Unstable) {
+ queryParams = replaceParam("via", "org.matrix.msc4156.via", queryParams);
+ }
}
const data: IJoinRequestBody = {};
@@ -4331,7 +4308,7 @@ export class MatrixClient extends TypedEventEmitter(Method.Post, path, queryString, data);
+ const res = await this.http.authedRequest<{ room_id: string }>(Method.Post, path, queryParams, data);
const roomId = res.room_id;
// In case we were originally given an alias, check the room cache again
@@ -4364,9 +4341,13 @@ export class MatrixClient extends TypedEventEmitter = {};
+ let queryParams: QueryDict = {};
if (opts.viaServers) {
queryParams.server_name = opts.viaServers;
+ queryParams.via = opts.viaServers;
+ if (this.canSupport.get(Feature.MigrateServerNameToVia) === ServerSupport.Unstable) {
+ queryParams = replaceParam("via", "org.matrix.msc4156.via", queryParams);
+ }
}
const body: Record = {};
@@ -4606,12 +4587,19 @@ export class MatrixClient extends TypedEventEmitter {
@@ -4629,8 +4617,6 @@ export class MatrixClient extends TypedEventEmitter,
txnId?: string,
- ): Promise {
+ ): Promise;
+ /**
+ * Sends a delayed event (MSC4140).
+ * @param eventObject - An object with the partial structure of an event, to which event_id, user_id, room_id and origin_server_ts will be added.
+ * @param delayOpts - Properties of the delay for this event.
+ * @param txnId - Optional.
+ * @returns Promise which resolves: to an empty object `{}`
+ * @returns Rejects: with an error response.
+ */
+ private sendCompleteEvent(
+ roomId: string,
+ threadId: string | null,
+ eventObject: Partial,
+ delayOpts: SendDelayedEventRequestOpts,
+ txnId?: string,
+ ): Promise;
+ private sendCompleteEvent(
+ roomId: string,
+ threadId: string | null,
+ eventObject: Partial,
+ delayOptsOrTxnId?: SendDelayedEventRequestOpts | string,
+ txnIdOrVoid?: string,
+ ): Promise {
+ let delayOpts: SendDelayedEventRequestOpts | undefined;
+ let txnId: string | undefined;
+ if (typeof delayOptsOrTxnId === "string") {
+ txnId = delayOptsOrTxnId;
+ } else {
+ delayOpts = delayOptsOrTxnId;
+ txnId = txnIdOrVoid;
+ }
+
if (!txnId) {
txnId = this.makeTxnId();
}
@@ -4667,9 +4684,11 @@ export class MatrixClient extends TypedEventEmitter {
+ protected async encryptAndSendEvent(room: Room | null, event: MatrixEvent): Promise;
+ /**
+ * Simply sends a delayed event without encrypting it.
+ * TODO: Allow encrypted delayed events, and encrypt them properly
+ * @param delayOpts - Properties of the delay for this event.
+ * @returns returns a promise which resolves with the result of the delayed send request
+ */
+ protected async encryptAndSendEvent(
+ room: Room | null,
+ event: MatrixEvent,
+ delayOpts: SendDelayedEventRequestOpts,
+ ): Promise;
+ protected async encryptAndSendEvent(
+ room: Room | null,
+ event: MatrixEvent,
+ delayOpts?: SendDelayedEventRequestOpts,
+ ): Promise {
+ if (delayOpts) {
+ return this.sendEventHttpRequest(event, delayOpts);
+ }
+
try {
let cancelled: boolean;
this.eventsBeingEncrypted.add(event.getId()!);
@@ -4857,7 +4903,15 @@ export class MatrixClient extends TypedEventEmitter {
+ private sendEventHttpRequest(event: MatrixEvent): Promise;
+ private sendEventHttpRequest(
+ event: MatrixEvent,
+ delayOpts: SendDelayedEventRequestOpts,
+ ): Promise;
+ private sendEventHttpRequest(
+ event: MatrixEvent,
+ delayOpts?: SendDelayedEventRequestOpts,
+ ): Promise {
let txnId = event.getTxnId();
if (!txnId) {
txnId = this.makeTxnId();
@@ -4889,12 +4943,20 @@ export class MatrixClient extends TypedEventEmitter(Method.Put, path, undefined, event.getWireContent())
- .then((res) => {
+ const content = event.getWireContent();
+ if (!delayOpts) {
+ return this.http.authedRequest(Method.Put, path, undefined, content).then((res) => {
this.logger.debug(`Event sent to ${event.getRoomId()} with event id ${res.event_id}`);
return res;
});
+ } else {
+ return this.http.authedRequest(
+ Method.Put,
+ path,
+ getUnstableDelayQueryOpts(delayOpts),
+ content,
+ );
+ }
}
/**
@@ -5224,6 +5286,101 @@ export class MatrixClient extends TypedEventEmitter(
+ roomId: string,
+ delayOpts: SendDelayedEventRequestOpts,
+ threadId: string | null,
+ eventType: K,
+ content: TimelineEvents[K],
+ txnId?: string,
+ ): Promise {
+ if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
+ throw Error("Server does not support the delayed events API");
+ }
+
+ this.addThreadRelationIfNeeded(content, threadId, roomId);
+ return this.sendCompleteEvent(roomId, threadId, { type: eventType, content }, delayOpts, txnId);
+ }
+
+ /**
+ * Send a delayed state event.
+ *
+ * Note: This endpoint is unstable, and can throw an `Error`.
+ * Check progress on [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for more details.
+ */
+ // eslint-disable-next-line
+ public async _unstable_sendDelayedStateEvent(
+ roomId: string,
+ delayOpts: SendDelayedEventRequestOpts,
+ eventType: K,
+ content: StateEvents[K],
+ stateKey = "",
+ opts: IRequestOpts = {},
+ ): Promise {
+ if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
+ throw Error("Server does not support the delayed events API");
+ }
+
+ const pathParams = {
+ $roomId: roomId,
+ $eventType: eventType,
+ $stateKey: stateKey,
+ };
+ let path = utils.encodeUri("/rooms/$roomId/state/$eventType", pathParams);
+ if (stateKey !== undefined) {
+ path = utils.encodeUri(path + "/$stateKey", pathParams);
+ }
+ return this.http.authedRequest(Method.Put, path, getUnstableDelayQueryOpts(delayOpts), content as Body, opts);
+ }
+
+ /**
+ * Get all pending delayed events for the calling user.
+ *
+ * Note: This endpoint is unstable, and can throw an `Error`.
+ * Check progress on [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for more details.
+ */
+ // eslint-disable-next-line
+ public async _unstable_getDelayedEvents(fromToken?: string): Promise {
+ if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
+ throw Error("Server does not support the delayed events API");
+ }
+
+ const queryDict = fromToken ? { from: fromToken } : undefined;
+ return await this.http.authedRequest(Method.Get, "/delayed_events", queryDict, undefined, {
+ prefix: `${ClientPrefix.Unstable}/${UNSTABLE_MSC4140_DELAYED_EVENTS}`,
+ });
+ }
+
+ /**
+ * Manage a delayed event associated with the given delay_id.
+ *
+ * Note: This endpoint is unstable, and can throw an `Error`.
+ * Check progress on [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for more details.
+ */
+ // eslint-disable-next-line
+ public async _unstable_updateDelayedEvent(delayId: string, action: UpdateDelayedEventAction): Promise<{}> {
+ if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
+ throw Error("Server does not support the delayed events API");
+ }
+
+ const path = utils.encodeUri("/delayed_events/$delayId", {
+ $delayId: delayId,
+ });
+ const data = {
+ action,
+ };
+ return await this.http.authedRequest(Method.Post, path, undefined, data, {
+ prefix: `${ClientPrefix.Unstable}/${UNSTABLE_MSC4140_DELAYED_EVENTS}`,
+ });
+ }
+
/**
* Send a receipt.
* @param event - The event being acknowledged
@@ -5437,10 +5594,15 @@ export class MatrixClient extends TypedEventEmitter([room.roomId]);
// Work backwards from newer to older rooms
let predecessorRoomId = room.findPredecessor(msc3946ProcessDynamicPredecessor)?.roomId;
while (predecessorRoomId !== null) {
+ if (predecessorRoomId) {
+ if (seenRoomIDs.has(predecessorRoomId)) break;
+ seenRoomIDs.add(predecessorRoomId);
+ }
const predecessorRoom = this.getRoom(predecessorRoomId);
if (predecessorRoom === null) {
break;
@@ -6639,13 +6801,14 @@ export class MatrixClient extends TypedEventEmitter {
+ public peekInRoom(roomId: string, limit: number = 20): Promise {
this.peekSync?.stopPeeking();
this.peekSync = new SyncApi(this, this.clientOpts, this.buildSyncApiOptions());
- return this.peekSync.peek(roomId);
+ return this.peekSync.peek(roomId, limit);
}
/**
@@ -7109,7 +7272,7 @@ export class MatrixClient extends TypedEventEmitter {
+ protected async fetchClientWellKnown(): Promise {
// `getRawClientConfig` does not throw or reject on network errors, instead
// it absorbs errors and returns `{}`.
this.clientWellKnownPromise = AutoDiscovery.getRawClientConfig(this.getDomain() ?? undefined);
@@ -9335,20 +9498,19 @@ export class MatrixClient extends TypedEventEmitter {
- const addr = p[0].toLowerCase(); // lowercase to get consistent hashes
- const med = p[1].toLowerCase();
- const hashed = olmutil
- .sha256(`${addr} ${med} ${params["pepper"]}`)
- .replace(/\+/g, "-")
- .replace(/\//g, "_"); // URL-safe base64
- // Map the hash to a known (case-sensitive) address. We use the case
- // sensitive version because the caller might be expecting that.
- localMapping[hashed] = p[0];
- return hashed;
- });
+ params["addresses"] = await Promise.all(
+ addressPairs.map(async (p) => {
+ const addr = p[0].toLowerCase(); // lowercase to get consistent hashes
+ const med = p[1].toLowerCase();
+ const hashBuffer = await sha256(`${addr} ${med} ${params["pepper"]}`);
+ const hashed = encodeUnpaddedBase64Url(hashBuffer);
+
+ // Map the hash to a known (case-sensitive) address. We use the case
+ // sensitive version because the caller might be expecting that.
+ localMapping[hashed] = p[0];
+ return hashed;
+ }),
+ );
params["algorithm"] = "sha256";
} else if (hashes["algorithms"].includes("none")) {
params["addresses"] = addressPairs.map((p) => {
@@ -9925,6 +10087,12 @@ export class MatrixClient extends TypedEventEmitter [`${UNSTABLE_MSC4140_DELAYED_EVENTS}.${k}`, v]),
+ );
+}
+
/**
* recalculates an accurate notifications count on event decryption.
* Servers do not have enough knowledge about encrypted events to calculate an
diff --git a/src/common-crypto/CryptoBackend.ts b/src/common-crypto/CryptoBackend.ts
index 7a36dc560e9..bbd6e5ec682 100644
--- a/src/common-crypto/CryptoBackend.ts
+++ b/src/common-crypto/CryptoBackend.ts
@@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
-import { IClearEvent, MatrixEvent } from "../models/event";
-import { Room } from "../models/room";
-import { CryptoApi, DecryptionFailureCode, ImportRoomKeysOpts } from "../crypto-api";
-import { CrossSigningInfo, UserTrustLevel } from "../crypto/CrossSigning";
-import { IEncryptedEventInfo } from "../crypto/api";
-import { KeyBackupInfo, KeyBackupSession } from "../crypto-api/keybackup";
-import { IMegolmSessionData } from "../@types/crypto";
+import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator.ts";
+import { IClearEvent, MatrixEvent } from "../models/event.ts";
+import { Room } from "../models/room.ts";
+import { CryptoApi, DecryptionFailureCode, ImportRoomKeysOpts } from "../crypto-api/index.ts";
+import { CrossSigningInfo, UserTrustLevel } from "../crypto/CrossSigning.ts";
+import { IEncryptedEventInfo } from "../crypto/api.ts";
+import { KeyBackupInfo, KeyBackupSession } from "../crypto-api/keybackup.ts";
+import { IMegolmSessionData } from "../@types/crypto.ts";
/**
* Common interface for the crypto implementations
diff --git a/src/content-helpers.ts b/src/content-helpers.ts
index 3f611e36901..ce8b373d93e 100644
--- a/src/content-helpers.ts
+++ b/src/content-helpers.ts
@@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { MBeaconEventContent, MBeaconInfoContent, MBeaconInfoEventContent } from "./@types/beacon";
-import { MsgType } from "./@types/event";
-import { M_TEXT, REFERENCE_RELATION } from "./@types/extensible_events";
-import { isProvided } from "./extensible_events_v1/utilities";
+import { MBeaconEventContent, MBeaconInfoContent, MBeaconInfoEventContent } from "./@types/beacon.ts";
+import { MsgType } from "./@types/event.ts";
+import { M_TEXT, REFERENCE_RELATION } from "./@types/extensible_events.ts";
+import { isProvided } from "./extensible_events_v1/utilities.ts";
import {
M_ASSET,
LocationAssetType,
@@ -28,9 +28,9 @@ import {
MLocationContent,
MAssetContent,
LegacyLocationEventContent,
-} from "./@types/location";
-import { MRoomTopicEventContent, MTopicContent, M_TOPIC } from "./@types/topic";
-import { RoomMessageEventContent } from "./@types/events";
+} from "./@types/location.ts";
+import { MRoomTopicEventContent, MTopicContent, M_TOPIC } from "./@types/topic.ts";
+import { RoomMessageEventContent } from "./@types/events.ts";
/**
* Generates the content for a HTML Message event
diff --git a/src/content-repo.ts b/src/content-repo.ts
index eaa119f97cd..b6174b6d8d9 100644
--- a/src/content-repo.ts
+++ b/src/content-repo.ts
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { encodeParams } from "./utils";
+import { encodeParams } from "./utils.ts";
/**
* Get the HTTP URL for an MXC URI.
@@ -62,7 +62,7 @@ export function getHttpUriForMxc(
if (useAuthentication) {
allowRedirects = true; // per docs (MSC3916 always expects redirects)
- // Dev note: MSC3916 (as of writing) removes `allow_redirect` entirely, but
+ // Dev note: MSC3916 removes `allow_redirect` entirely, but
// for explicitness we set it here. This makes it slightly more obvious to
// callers, hopefully.
}
@@ -70,8 +70,7 @@ export function getHttpUriForMxc(
let serverAndMediaId = mxc.slice(6); // strips mxc://
let prefix: string;
if (useAuthentication) {
- // TODO: Use stable once available (requires FCP on MSC3916).
- prefix = "/_matrix/client/unstable/org.matrix.msc3916/media/download/";
+ prefix = "/_matrix/client/v1/media/download/";
} else {
prefix = "/_matrix/media/v3/download/";
}
@@ -90,8 +89,7 @@ export function getHttpUriForMxc(
// these are thumbnailing params so they probably want the
// thumbnailing API...
if (useAuthentication) {
- // TODO: Use stable once available (requires FCP on MSC3916).
- prefix = "/_matrix/client/unstable/org.matrix.msc3916/media/thumbnail/";
+ prefix = "/_matrix/client/v1/media/thumbnail/";
} else {
prefix = "/_matrix/media/v3/thumbnail/";
}
diff --git a/src/crypto-api.ts b/src/crypto-api/index.ts
similarity index 94%
rename from src/crypto-api.ts
rename to src/crypto-api/index.ts
index 7dfdfbfcf08..6b9db3811dc 100644
--- a/src/crypto-api.ts
+++ b/src/crypto-api/index.ts
@@ -14,15 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import type { IMegolmSessionData } from "./@types/crypto";
-import { Room } from "./models/room";
-import { DeviceMap } from "./models/device";
-import { UIAuthCallback } from "./interactive-auth";
-import { PassphraseInfo, SecretStorageCallbacks, SecretStorageKeyDescription } from "./secret-storage";
-import { VerificationRequest } from "./crypto-api/verification";
-import { BackupTrustInfo, KeyBackupCheck, KeyBackupInfo } from "./crypto-api/keybackup";
-import { ISignatures } from "./@types/signed";
-import { MatrixEvent } from "./models/event";
+import type { SecretsBundle } from "@matrix-org/matrix-sdk-crypto-wasm";
+import type { IMegolmSessionData } from "../@types/crypto.ts";
+import { Room } from "../models/room.ts";
+import { DeviceMap } from "../models/device.ts";
+import { UIAuthCallback } from "../interactive-auth.ts";
+import { PassphraseInfo, SecretStorageCallbacks, SecretStorageKeyDescription } from "../secret-storage.ts";
+import { VerificationRequest } from "./verification.ts";
+import { BackupTrustInfo, KeyBackupCheck, KeyBackupInfo } from "./keybackup.ts";
+import { ISignatures } from "../@types/signed.ts";
+import { MatrixEvent } from "../models/event.ts";
/**
* Public interface to the cryptography parts of the js-sdk
@@ -532,6 +533,23 @@ export interface CryptoApi {
* to false.
*/
startDehydration(createNewKey?: boolean): Promise;
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Import/export of secret keys
+ //
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Export secrets bundle for transmitting to another device as part of OIDC QR login
+ */
+ exportSecretsBundle?(): Promise>>;
+
+ /**
+ * Import secrets bundle transmitted from another device.
+ * @param secrets - The secrets bundle received from the other device
+ */
+ importSecretsBundle?(secrets: Awaited>): Promise;
}
/** A reason code for a failure to decrypt an event. */
@@ -539,6 +557,12 @@ export enum DecryptionFailureCode {
/** Message was encrypted with a Megolm session whose keys have not been shared with us. */
MEGOLM_UNKNOWN_INBOUND_SESSION_ID = "MEGOLM_UNKNOWN_INBOUND_SESSION_ID",
+ /** A special case of {@link MEGOLM_UNKNOWN_INBOUND_SESSION_ID}: the sender has told us it is withholding the key. */
+ MEGOLM_KEY_WITHHELD = "MEGOLM_KEY_WITHHELD",
+
+ /** A special case of {@link MEGOLM_KEY_WITHHELD}: the sender has told us it is withholding the key, because the current device is unverified. */
+ MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE = "MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE",
+
/** Message was encrypted with a Megolm session which has been shared with us, but in a later ratchet state. */
OLM_UNKNOWN_MESSAGE_INDEX = "OLM_UNKNOWN_MESSAGE_INDEX",
@@ -785,6 +809,8 @@ export interface CryptoCallbacks extends SecretStorageCallbacks {
* @param key - private key to store
*/
cacheSecretStorageKey?: (keyId: string, keyInfo: SecretStorageKeyDescription, key: Uint8Array) => void;
+
+ /** @deprecated: unused with the Rust crypto stack. */
onSecretRequested?: (
userId: string,
deviceId: string,
@@ -792,10 +818,13 @@ export interface CryptoCallbacks extends SecretStorageCallbacks {
secretName: string,
deviceTrust: DeviceVerificationStatus,
) => Promise;
+
+ /** @deprecated: unused with the Rust crypto stack. */
getDehydrationKey?: (
keyInfo: SecretStorageKeyDescription,
checkFunc: (key: Uint8Array) => void,
) => Promise;
+
getBackupKey?: () => Promise;
}
@@ -830,9 +859,14 @@ export interface CreateSecretStorageOpts {
setupNewSecretStorage?: boolean;
/**
- * Function called to get the user's
- * current key backup passphrase. Should return a promise that resolves with a Uint8Array
+ * Function called to get the user's current key backup passphrase.
+ *
+ * Should return a promise that resolves with a Uint8Array
* containing the key, or rejects if the key cannot be obtained.
+ *
+ * Only used when the client has existing key backup, but no secret storage.
+ *
+ * @deprecated Not used by the Rust crypto stack.
*/
getKeyBackupPassphrase?: () => Promise;
}
@@ -931,5 +965,5 @@ export interface OwnDeviceKeys {
curve25519: string;
}
-export * from "./crypto-api/verification";
-export * from "./crypto-api/keybackup";
+export * from "./verification.ts";
+export * from "./keybackup.ts";
diff --git a/src/crypto-api/keybackup.ts b/src/crypto-api/keybackup.ts
index 71c47d6834f..3209de6c320 100644
--- a/src/crypto-api/keybackup.ts
+++ b/src/crypto-api/keybackup.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { ISigned } from "../@types/signed";
-import { IEncryptedPayload } from "../crypto/aes";
+import { ISigned } from "../@types/signed.ts";
+import { IEncryptedPayload } from "../crypto/aes.ts";
export interface Curve25519AuthData {
public_key: string;
diff --git a/src/crypto-api/verification.ts b/src/crypto-api/verification.ts
index dd42dc35c9b..daa7bdbceed 100644
--- a/src/crypto-api/verification.ts
+++ b/src/crypto-api/verification.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { MatrixEvent } from "../models/event";
-import { TypedEventEmitter } from "../models/typed-event-emitter";
+import { MatrixEvent } from "../models/event.ts";
+import { TypedEventEmitter } from "../models/typed-event-emitter.ts";
/**
* An incoming, or outgoing, request to verify a user or a device via cross-signing.
diff --git a/src/crypto/CrossSigning.ts b/src/crypto/CrossSigning.ts
index 95d20da052e..a4caf1c53a1 100644
--- a/src/crypto/CrossSigning.ts
+++ b/src/crypto/CrossSigning.ts
@@ -19,19 +19,23 @@ limitations under the License.
*/
import type { PkSigning } from "@matrix-org/olm";
-import { IObject, pkSign, pkVerify } from "./olmlib";
-import { logger } from "../logger";
-import { IndexedDBCryptoStore } from "../crypto/store/indexeddb-crypto-store";
-import { decryptAES, encryptAES } from "./aes";
-import { DeviceInfo } from "./deviceinfo";
-import { ISignedKey, MatrixClient } from "../client";
-import { OlmDevice } from "./OlmDevice";
-import { ICryptoCallbacks } from ".";
-import { ISignatures } from "../@types/signed";
-import { CryptoStore, SecretStorePrivateKeys } from "./store/base";
-import { ServerSideSecretStorage, SecretStorageKeyDescription } from "../secret-storage";
-import { CrossSigningKeyInfo, DeviceVerificationStatus, UserVerificationStatus as UserTrustLevel } from "../crypto-api";
-import { decodeBase64, encodeBase64 } from "../base64";
+import { IObject, pkSign, pkVerify } from "./olmlib.ts";
+import { logger } from "../logger.ts";
+import { IndexedDBCryptoStore } from "../crypto/store/indexeddb-crypto-store.ts";
+import { decryptAES, encryptAES } from "./aes.ts";
+import { DeviceInfo } from "./deviceinfo.ts";
+import { ISignedKey, MatrixClient } from "../client.ts";
+import { OlmDevice } from "./OlmDevice.ts";
+import { ICryptoCallbacks } from "./index.ts";
+import { ISignatures } from "../@types/signed.ts";
+import { CryptoStore, SecretStorePrivateKeys } from "./store/base.ts";
+import { ServerSideSecretStorage, SecretStorageKeyDescription } from "../secret-storage.ts";
+import {
+ CrossSigningKeyInfo,
+ DeviceVerificationStatus,
+ UserVerificationStatus as UserTrustLevel,
+} from "../crypto-api/index.ts";
+import { decodeBase64, encodeBase64 } from "../base64.ts";
// backwards-compatibility re-exports
export { UserTrustLevel };
diff --git a/src/crypto/DeviceList.ts b/src/crypto/DeviceList.ts
index 8ad3831893a..320ea6a2653 100644
--- a/src/crypto/DeviceList.ts
+++ b/src/crypto/DeviceList.ts
@@ -18,17 +18,17 @@ limitations under the License.
* Manages the list of other users' devices
*/
-import { logger } from "../logger";
-import { DeviceInfo, IDevice } from "./deviceinfo";
-import { CrossSigningInfo, ICrossSigningInfo } from "./CrossSigning";
-import * as olmlib from "./olmlib";
-import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store";
-import { chunkPromises, defer, IDeferred, sleep } from "../utils";
-import { DeviceKeys, IDownloadKeyResult, Keys, MatrixClient, SigningKeys } from "../client";
-import { OlmDevice } from "./OlmDevice";
-import { CryptoStore } from "./store/base";
-import { TypedEventEmitter } from "../models/typed-event-emitter";
-import { CryptoEvent, CryptoEventHandlerMap } from "./index";
+import { logger } from "../logger.ts";
+import { DeviceInfo, IDevice } from "./deviceinfo.ts";
+import { CrossSigningInfo, ICrossSigningInfo } from "./CrossSigning.ts";
+import * as olmlib from "./olmlib.ts";
+import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store.ts";
+import { chunkPromises, defer, IDeferred, sleep } from "../utils.ts";
+import { DeviceKeys, IDownloadKeyResult, Keys, MatrixClient, SigningKeys } from "../client.ts";
+import { OlmDevice } from "./OlmDevice.ts";
+import { CryptoStore } from "./store/base.ts";
+import { TypedEventEmitter } from "../models/typed-event-emitter.ts";
+import { CryptoEvent, CryptoEventHandlerMap } from "./index.ts";
/* State transition diagram for DeviceList.deviceTrackingStatus
*
diff --git a/src/crypto/EncryptionSetup.ts b/src/crypto/EncryptionSetup.ts
index b7015b5a0ba..dab5d560693 100644
--- a/src/crypto/EncryptionSetup.ts
+++ b/src/crypto/EncryptionSetup.ts
@@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { logger } from "../logger";
-import { MatrixEvent } from "../models/event";
-import { createCryptoStoreCacheCallbacks, ICacheCallbacks } from "./CrossSigning";
-import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store";
-import { Method, ClientPrefix } from "../http-api";
-import { Crypto, ICryptoCallbacks } from "./index";
-import { ClientEvent, ClientEventHandlerMap, CrossSigningKeys, ISignedKey, KeySignatures } from "../client";
-import { IKeyBackupInfo } from "./keybackup";
-import { TypedEventEmitter } from "../models/typed-event-emitter";
-import { AccountDataClient, SecretStorageKeyDescription } from "../secret-storage";
-import { BootstrapCrossSigningOpts, CrossSigningKeyInfo } from "../crypto-api";
+import { logger } from "../logger.ts";
+import { MatrixEvent } from "../models/event.ts";
+import { createCryptoStoreCacheCallbacks, ICacheCallbacks } from "./CrossSigning.ts";
+import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store.ts";
+import { Method, ClientPrefix } from "../http-api/index.ts";
+import { Crypto, ICryptoCallbacks } from "./index.ts";
+import { ClientEvent, ClientEventHandlerMap, CrossSigningKeys, ISignedKey, KeySignatures } from "../client.ts";
+import { IKeyBackupInfo } from "./keybackup.ts";
+import { TypedEventEmitter } from "../models/typed-event-emitter.ts";
+import { AccountDataClient, SecretStorageKeyDescription } from "../secret-storage.ts";
+import { BootstrapCrossSigningOpts, CrossSigningKeyInfo } from "../crypto-api/index.ts";
interface ICrossSigningKeys {
authUpload: BootstrapCrossSigningOpts["authUploadDeviceSigningKeys"];
diff --git a/src/crypto/OlmDevice.ts b/src/crypto/OlmDevice.ts
index 6e645b72b97..1006bf0de47 100644
--- a/src/crypto/OlmDevice.ts
+++ b/src/crypto/OlmDevice.ts
@@ -16,14 +16,14 @@ limitations under the License.
import { Account, InboundGroupSession, OutboundGroupSession, Session, Utility } from "@matrix-org/olm";
-import { logger, Logger } from "../logger";
-import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store";
-import { CryptoStore, IProblem, ISessionInfo, IWithheld } from "./store/base";
-import { IOlmDevice, IOutboundGroupSessionKey } from "./algorithms/megolm";
-import { IMegolmSessionData, OlmGroupSessionExtraData } from "../@types/crypto";
-import { IMessage } from "./algorithms/olm";
-import { DecryptionFailureCode } from "../crypto-api";
-import { DecryptionError } from "../common-crypto/CryptoBackend";
+import { logger, Logger } from "../logger.ts";
+import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store.ts";
+import { CryptoStore, IProblem, ISessionInfo, IWithheld } from "./store/base.ts";
+import { IOlmDevice, IOutboundGroupSessionKey } from "./algorithms/megolm.ts";
+import { IMegolmSessionData, OlmGroupSessionExtraData } from "../@types/crypto.ts";
+import { IMessage } from "./algorithms/olm.ts";
+import { DecryptionFailureCode } from "../crypto-api/index.ts";
+import { DecryptionError } from "../common-crypto/CryptoBackend.ts";
// The maximum size of an event is 65K, and we base64 the content, so this is a
// reasonable approximation to the biggest plaintext we can encrypt.
@@ -1221,13 +1221,13 @@ export class OlmDevice {
this.getInboundGroupSession(roomId, senderKey, sessionId, txn, (session, sessionData, withheld) => {
if (session === null || sessionData === null) {
if (withheld) {
- error = new DecryptionError(
- DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID,
- calculateWithheldMessage(withheld),
- {
- session: senderKey + "|" + sessionId,
- },
- );
+ const failureCode =
+ withheld.code === "m.unverified"
+ ? DecryptionFailureCode.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE
+ : DecryptionFailureCode.MEGOLM_KEY_WITHHELD;
+ error = new DecryptionError(failureCode, calculateWithheldMessage(withheld), {
+ session: senderKey + "|" + sessionId,
+ });
}
result = null;
return;
@@ -1237,13 +1237,13 @@ export class OlmDevice {
res = session.decrypt(body);
} catch (e) {
if ((e)?.message === "OLM.UNKNOWN_MESSAGE_INDEX" && withheld) {
- error = new DecryptionError(
- DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID,
- calculateWithheldMessage(withheld),
- {
- session: senderKey + "|" + sessionId,
- },
- );
+ const failureCode =
+ withheld.code === "m.unverified"
+ ? DecryptionFailureCode.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE
+ : DecryptionFailureCode.MEGOLM_KEY_WITHHELD;
+ error = new DecryptionError(failureCode, calculateWithheldMessage(withheld), {
+ session: senderKey + "|" + sessionId,
+ });
} else {
error = e;
}
diff --git a/src/crypto/OutgoingRoomKeyRequestManager.ts b/src/crypto/OutgoingRoomKeyRequestManager.ts
index 4628b3e8dd9..4f3cf2534ae 100644
--- a/src/crypto/OutgoingRoomKeyRequestManager.ts
+++ b/src/crypto/OutgoingRoomKeyRequestManager.ts
@@ -16,12 +16,12 @@ limitations under the License.
import { v4 as uuidv4 } from "uuid";
-import { logger } from "../logger";
-import { MatrixClient } from "../client";
-import { IRoomKeyRequestBody, IRoomKeyRequestRecipient } from "./index";
-import { CryptoStore, OutgoingRoomKeyRequest } from "./store/base";
-import { EventType, ToDeviceMessageId } from "../@types/event";
-import { MapWithDefault } from "../utils";
+import { logger } from "../logger.ts";
+import { MatrixClient } from "../client.ts";
+import { IRoomKeyRequestBody, IRoomKeyRequestRecipient } from "./index.ts";
+import { CryptoStore, OutgoingRoomKeyRequest } from "./store/base.ts";
+import { EventType, ToDeviceMessageId } from "../@types/event.ts";
+import { MapWithDefault } from "../utils.ts";
/**
* Internal module. Management of outgoing room key requests.
diff --git a/src/crypto/RoomList.ts b/src/crypto/RoomList.ts
index b100bd30218..75573d64022 100644
--- a/src/crypto/RoomList.ts
+++ b/src/crypto/RoomList.ts
@@ -18,8 +18,8 @@ limitations under the License.
* Manages the list of encrypted rooms
*/
-import { CryptoStore } from "./store/base";
-import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store";
+import { CryptoStore } from "./store/base.ts";
+import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store.ts";
/* eslint-disable camelcase */
export interface IRoomEncryption {
diff --git a/src/crypto/SecretSharing.ts b/src/crypto/SecretSharing.ts
index 5083a8c243b..11def73715e 100644
--- a/src/crypto/SecretSharing.ts
+++ b/src/crypto/SecretSharing.ts
@@ -15,13 +15,13 @@ limitations under the License.
*/
import { v4 as uuidv4 } from "uuid";
-import { MatrixClient } from "../client";
-import { ICryptoCallbacks, IEncryptedContent } from "./index";
-import { defer, IDeferred } from "../utils";
-import { ToDeviceMessageId } from "../@types/event";
-import { logger } from "../logger";
-import { MatrixEvent } from "../models/event";
-import * as olmlib from "./olmlib";
+import { MatrixClient } from "../client.ts";
+import { ICryptoCallbacks, IEncryptedContent } from "./index.ts";
+import { defer, IDeferred } from "../utils.ts";
+import { ToDeviceMessageId } from "../@types/event.ts";
+import { logger } from "../logger.ts";
+import { MatrixEvent } from "../models/event.ts";
+import * as olmlib from "./olmlib.ts";
export interface ISecretRequest {
requestId: string;
diff --git a/src/crypto/SecretStorage.ts b/src/crypto/SecretStorage.ts
index 452d1fde99f..6bd653dd0c0 100644
--- a/src/crypto/SecretStorage.ts
+++ b/src/crypto/SecretStorage.ts
@@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { ICryptoCallbacks } from ".";
-import { MatrixEvent } from "../models/event";
-import { MatrixClient } from "../client";
+import { ICryptoCallbacks } from "./index.ts";
+import { MatrixEvent } from "../models/event.ts";
+import { MatrixClient } from "../client.ts";
import {
SecretStorageKeyDescription,
SecretStorageKeyTuple,
@@ -25,8 +25,8 @@ import {
AccountDataClient,
ServerSideSecretStorage,
ServerSideSecretStorageImpl,
-} from "../secret-storage";
-import { ISecretRequest, SecretSharing } from "./SecretSharing";
+} from "../secret-storage.ts";
+import { ISecretRequest, SecretSharing } from "./SecretSharing.ts";
/* re-exports for backwards compatibility */
export type {
@@ -34,9 +34,9 @@ export type {
SecretStorageKeyTuple,
SecretStorageKeyObject,
SECRET_STORAGE_ALGORITHM_V1_AES,
-} from "../secret-storage";
+} from "../secret-storage.ts";
-export type { ISecretRequest } from "./SecretSharing";
+export type { ISecretRequest } from "./SecretSharing.ts";
/**
* Implements Secure Secret Storage and Sharing (MSC1946)
diff --git a/src/crypto/aes.ts b/src/crypto/aes.ts
index 389e2ff6ac3..6c6779d0611 100644
--- a/src/crypto/aes.ts
+++ b/src/crypto/aes.ts
@@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { decodeBase64, encodeBase64 } from "../base64";
-import { subtleCrypto, crypto, TextEncoder } from "./crypto";
+import { decodeBase64, encodeBase64 } from "../base64.ts";
// salt for HKDF, with 8 bytes of zeros
const zeroSalt = new Uint8Array(8);
@@ -49,7 +48,7 @@ export async function encryptAES(
iv = decodeBase64(ivStr);
} else {
iv = new Uint8Array(16);
- crypto.getRandomValues(iv);
+ globalThis.crypto.getRandomValues(iv);
// clear bit 63 of the IV to stop us hitting the 64-bit counter boundary
// (which would mean we wouldn't be able to decrypt on Android). The loss
@@ -60,7 +59,7 @@ export async function encryptAES(
const [aesKey, hmacKey] = await deriveKeys(key, name);
const encodedData = new TextEncoder().encode(data);
- const ciphertext = await subtleCrypto.encrypt(
+ const ciphertext = await globalThis.crypto.subtle.encrypt(
{
name: "AES-CTR",
counter: iv,
@@ -70,7 +69,7 @@ export async function encryptAES(
encodedData,
);
- const hmac = await subtleCrypto.sign({ name: "HMAC" }, hmacKey, ciphertext);
+ const hmac = await globalThis.crypto.subtle.sign({ name: "HMAC" }, hmacKey, ciphertext);
return {
iv: encodeBase64(iv),
@@ -91,11 +90,11 @@ export async function decryptAES(data: IEncryptedPayload, key: Uint8Array, name:
const ciphertext = decodeBase64(data.ciphertext);
- if (!(await subtleCrypto.verify({ name: "HMAC" }, hmacKey, decodeBase64(data.mac), ciphertext))) {
+ if (!(await globalThis.crypto.subtle.verify({ name: "HMAC" }, hmacKey, decodeBase64(data.mac), ciphertext))) {
throw new Error(`Error decrypting secret ${name}: bad MAC`);
}
- const plaintext = await subtleCrypto.decrypt(
+ const plaintext = await globalThis.crypto.subtle.decrypt(
{
name: "AES-CTR",
counter: decodeBase64(data.iv),
@@ -109,8 +108,8 @@ export async function decryptAES(data: IEncryptedPayload, key: Uint8Array, name:
}
async function deriveKeys(key: Uint8Array, name: string): Promise<[CryptoKey, CryptoKey]> {
- const hkdfkey = await subtleCrypto.importKey("raw", key, { name: "HKDF" }, false, ["deriveBits"]);
- const keybits = await subtleCrypto.deriveBits(
+ const hkdfkey = await globalThis.crypto.subtle.importKey("raw", key, { name: "HKDF" }, false, ["deriveBits"]);
+ const keybits = await globalThis.crypto.subtle.deriveBits(
{
name: "HKDF",
salt: zeroSalt,
@@ -126,9 +125,12 @@ async function deriveKeys(key: Uint8Array, name: string): Promise<[CryptoKey, Cr
const aesKey = keybits.slice(0, 32);
const hmacKey = keybits.slice(32);
- const aesProm = subtleCrypto.importKey("raw", aesKey, { name: "AES-CTR" }, false, ["encrypt", "decrypt"]);
+ const aesProm = globalThis.crypto.subtle.importKey("raw", aesKey, { name: "AES-CTR" }, false, [
+ "encrypt",
+ "decrypt",
+ ]);
- const hmacProm = subtleCrypto.importKey(
+ const hmacProm = globalThis.crypto.subtle.importKey(
"raw",
hmacKey,
{
diff --git a/src/crypto/algorithms/base.ts b/src/crypto/algorithms/base.ts
index 37dae34bd77..9b038426147 100644
--- a/src/crypto/algorithms/base.ts
+++ b/src/crypto/algorithms/base.ts
@@ -18,15 +18,15 @@ limitations under the License.
* Internal module. Defines the base classes of the encryption implementations
*/
-import type { IMegolmSessionData } from "../../@types/crypto";
-import { MatrixClient } from "../../client";
-import { Room } from "../../models/room";
-import { OlmDevice } from "../OlmDevice";
-import { IContent, MatrixEvent, RoomMember } from "../../matrix";
-import { Crypto, IEncryptedContent, IEventDecryptionResult, IncomingRoomKeyRequest } from "..";
-import { DeviceInfo } from "../deviceinfo";
-import { IRoomEncryption } from "../RoomList";
-import { DeviceInfoMap } from "../DeviceList";
+import type { IMegolmSessionData } from "../../@types/crypto.ts";
+import { MatrixClient } from "../../client.ts";
+import { Room } from "../../models/room.ts";
+import { OlmDevice } from "../OlmDevice.ts";
+import { IContent, MatrixEvent, RoomMember } from "../../matrix.ts";
+import { Crypto, IEncryptedContent, IEventDecryptionResult, IncomingRoomKeyRequest } from "../index.ts";
+import { DeviceInfo } from "../deviceinfo.ts";
+import { IRoomEncryption } from "../RoomList.ts";
+import { DeviceInfoMap } from "../DeviceList.ts";
/**
* Map of registered encryption algorithm classes. A map from string to {@link EncryptionAlgorithm} class
@@ -66,7 +66,6 @@ export abstract class EncryptionAlgorithm {
protected readonly crypto: Crypto;
protected readonly olmDevice: OlmDevice;
protected readonly baseApis: MatrixClient;
- protected readonly roomId?: string;
/**
* @param params - parameters
@@ -77,7 +76,6 @@ export abstract class EncryptionAlgorithm {
this.crypto = params.crypto;
this.olmDevice = params.olmDevice;
this.baseApis = params.baseApis;
- this.roomId = params.roomId;
}
/**
@@ -127,14 +125,12 @@ export abstract class DecryptionAlgorithm {
protected readonly crypto: Crypto;
protected readonly olmDevice: OlmDevice;
protected readonly baseApis: MatrixClient;
- protected readonly roomId?: string;
public constructor(params: DecryptionClassParams) {
this.userId = params.userId;
this.crypto = params.crypto;
this.olmDevice = params.olmDevice;
this.baseApis = params.baseApis;
- this.roomId = params.roomId;
}
/**
@@ -237,4 +233,4 @@ export function registerAlgorithm(
}
/* Re-export for backwards compatibility. Deprecated: this is an internal class. */
-export { DecryptionError } from "../../common-crypto/CryptoBackend";
+export { DecryptionError } from "../../common-crypto/CryptoBackend.ts";
diff --git a/src/crypto/algorithms/index.ts b/src/crypto/algorithms/index.ts
index b3c5b0ede84..947c6e0ea2b 100644
--- a/src/crypto/algorithms/index.ts
+++ b/src/crypto/algorithms/index.ts
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import "./olm";
-import "./megolm";
+import "./olm.ts";
+import "./megolm.ts";
-export * from "./base";
+export * from "./base.ts";
diff --git a/src/crypto/algorithms/megolm.ts b/src/crypto/algorithms/megolm.ts
index 5fa4a1b757e..9fde8e5bc9c 100644
--- a/src/crypto/algorithms/megolm.ts
+++ b/src/crypto/algorithms/megolm.ts
@@ -20,9 +20,9 @@ limitations under the License.
import { v4 as uuidv4 } from "uuid";
-import type { IEventDecryptionResult, IMegolmSessionData } from "../../@types/crypto";
-import { logger, Logger } from "../../logger";
-import * as olmlib from "../olmlib";
+import type { IEventDecryptionResult, IMegolmSessionData } from "../../@types/crypto.ts";
+import { logger, Logger } from "../../logger.ts";
+import * as olmlib from "../olmlib.ts";
import {
DecryptionAlgorithm,
DecryptionClassParams,
@@ -30,22 +30,22 @@ import {
IParams,
registerAlgorithm,
UnknownDeviceError,
-} from "./base";
-import { IDecryptedGroupMessage, WITHHELD_MESSAGES } from "../OlmDevice";
-import { Room } from "../../models/room";
-import { DeviceInfo } from "../deviceinfo";
-import { IOlmSessionResult } from "../olmlib";
-import { DeviceInfoMap } from "../DeviceList";
-import { IContent, MatrixEvent } from "../../models/event";
-import { EventType, MsgType, ToDeviceMessageId } from "../../@types/event";
-import { IMegolmEncryptedContent, IncomingRoomKeyRequest, IEncryptedContent } from "../index";
-import { RoomKeyRequestState } from "../OutgoingRoomKeyRequestManager";
-import { OlmGroupSessionExtraData } from "../../@types/crypto";
-import { MatrixError } from "../../http-api";
-import { immediate, MapWithDefault } from "../../utils";
-import { KnownMembership } from "../../@types/membership";
-import { DecryptionFailureCode } from "../../crypto-api";
-import { DecryptionError } from "../../common-crypto/CryptoBackend";
+} from "./base.ts";
+import { IDecryptedGroupMessage, WITHHELD_MESSAGES } from "../OlmDevice.ts";
+import { Room } from "../../models/room.ts";
+import { DeviceInfo } from "../deviceinfo.ts";
+import { IOlmSessionResult } from "../olmlib.ts";
+import { DeviceInfoMap } from "../DeviceList.ts";
+import { IContent, MatrixEvent } from "../../models/event.ts";
+import { EventType, MsgType, ToDeviceMessageId } from "../../@types/event.ts";
+import { IMegolmEncryptedContent, IncomingRoomKeyRequest, IEncryptedContent } from "../index.ts";
+import { RoomKeyRequestState } from "../OutgoingRoomKeyRequestManager.ts";
+import { OlmGroupSessionExtraData } from "../../@types/crypto.ts";
+import { MatrixError } from "../../http-api/index.ts";
+import { immediate, MapWithDefault } from "../../utils.ts";
+import { KnownMembership } from "../../@types/membership.ts";
+import { DecryptionFailureCode } from "../../crypto-api/index.ts";
+import { DecryptionError } from "../../common-crypto/CryptoBackend.ts";
// determine whether the key can be shared with invitees
export function isRoomSharedHistory(room: Room): boolean {
diff --git a/src/crypto/algorithms/olm.ts b/src/crypto/algorithms/olm.ts
index 3bcff5872b0..eb93a06a171 100644
--- a/src/crypto/algorithms/olm.ts
+++ b/src/crypto/algorithms/olm.ts
@@ -18,17 +18,17 @@ limitations under the License.
* Defines m.olm encryption/decryption
*/
-import type { IEventDecryptionResult } from "../../@types/crypto";
-import { logger } from "../../logger";
-import * as olmlib from "../olmlib";
-import { DeviceInfo } from "../deviceinfo";
-import { DecryptionAlgorithm, EncryptionAlgorithm, registerAlgorithm } from "./base";
-import { Room } from "../../models/room";
-import { IContent, MatrixEvent } from "../../models/event";
-import { IEncryptedContent, IOlmEncryptedContent } from "../index";
-import { IInboundSession } from "../OlmDevice";
-import { DecryptionFailureCode } from "../../crypto-api";
-import { DecryptionError } from "../../common-crypto/CryptoBackend";
+import type { IEventDecryptionResult } from "../../@types/crypto.ts";
+import { logger } from "../../logger.ts";
+import * as olmlib from "../olmlib.ts";
+import { DeviceInfo } from "../deviceinfo.ts";
+import { DecryptionAlgorithm, EncryptionAlgorithm, registerAlgorithm } from "./base.ts";
+import { Room } from "../../models/room.ts";
+import { IContent, MatrixEvent } from "../../models/event.ts";
+import { IEncryptedContent, IOlmEncryptedContent } from "../index.ts";
+import { IInboundSession } from "../OlmDevice.ts";
+import { DecryptionFailureCode } from "../../crypto-api/index.ts";
+import { DecryptionError } from "../../common-crypto/CryptoBackend.ts";
const DeviceVerification = DeviceInfo.DeviceVerification;
diff --git a/src/crypto/api.ts b/src/crypto/api.ts
index a0e11a415be..0b520277772 100644
--- a/src/crypto/api.ts
+++ b/src/crypto/api.ts
@@ -14,26 +14,26 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { DeviceInfo } from "./deviceinfo";
+import { DeviceInfo } from "./deviceinfo.ts";
/* re-exports for backwards compatibility. */
// CrossSigningKey is used as a value in `client.ts`, we can't export it as a type
-export { CrossSigningKey } from "../crypto-api";
+export { CrossSigningKey } from "../crypto-api/index.ts";
export type {
GeneratedSecretStorageKey as IRecoveryKey,
CreateSecretStorageOpts as ICreateSecretStorageOpts,
-} from "../crypto-api";
+} from "../crypto-api/index.ts";
export type {
ImportRoomKeyProgressData as IImportOpts,
ImportRoomKeysOpts as IImportRoomKeysOpts,
-} from "../crypto-api";
+} from "../crypto-api/index.ts";
export type {
AddSecretStorageKeyOpts as IAddSecretStorageKeyOpts,
PassphraseInfo as IPassphraseInfo,
SecretStorageKeyDescription as ISecretStorageKeyInfo,
-} from "../secret-storage";
+} from "../secret-storage.ts";
// TODO: Merge this with crypto.js once converted
diff --git a/src/crypto/backup.ts b/src/crypto/backup.ts
index d51fa641c26..3ac6a3ddc0b 100644
--- a/src/crypto/backup.ts
+++ b/src/crypto/backup.ts
@@ -18,30 +18,29 @@ limitations under the License.
* Classes for dealing with key backup.
*/
-import type { IMegolmSessionData } from "../@types/crypto";
-import { MatrixClient } from "../client";
-import { logger } from "../logger";
-import { MEGOLM_ALGORITHM, verifySignature } from "./olmlib";
-import { DeviceInfo } from "./deviceinfo";
-import { DeviceTrustLevel } from "./CrossSigning";
-import { keyFromPassphrase } from "./key_passphrase";
-import { encodeUri, safeSet, sleep } from "../utils";
-import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store";
-import { encodeRecoveryKey } from "./recoverykey";
-import { calculateKeyCheck, decryptAES, encryptAES, IEncryptedPayload } from "./aes";
+import type { IMegolmSessionData } from "../@types/crypto.ts";
+import { MatrixClient } from "../client.ts";
+import { logger } from "../logger.ts";
+import { MEGOLM_ALGORITHM, verifySignature } from "./olmlib.ts";
+import { DeviceInfo } from "./deviceinfo.ts";
+import { DeviceTrustLevel } from "./CrossSigning.ts";
+import { keyFromPassphrase } from "./key_passphrase.ts";
+import { encodeUri, safeSet, sleep } from "../utils.ts";
+import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store.ts";
+import { encodeRecoveryKey } from "./recoverykey.ts";
+import { calculateKeyCheck, decryptAES, encryptAES, IEncryptedPayload } from "./aes.ts";
import {
Curve25519SessionData,
IAes256AuthData,
ICurve25519AuthData,
IKeyBackupInfo,
IKeyBackupSession,
-} from "./keybackup";
-import { UnstableValue } from "../NamespacedValue";
-import { CryptoEvent } from "./index";
-import { crypto } from "./crypto";
-import { ClientPrefix, HTTPError, MatrixError, Method } from "../http-api";
-import { BackupTrustInfo } from "../crypto-api/keybackup";
-import { BackupDecryptor } from "../common-crypto/CryptoBackend";
+} from "./keybackup.ts";
+import { UnstableValue } from "../NamespacedValue.ts";
+import { CryptoEvent } from "./index.ts";
+import { ClientPrefix, HTTPError, MatrixError, Method } from "../http-api/index.ts";
+import { BackupTrustInfo } from "../crypto-api/keybackup.ts";
+import { BackupDecryptor } from "../common-crypto/CryptoBackend.ts";
const KEY_BACKUP_KEYS_PER_REQUEST = 200;
const KEY_BACKUP_CHECK_RATE_LIMIT = 5000; // ms
@@ -764,7 +763,7 @@ export class Curve25519 implements BackupAlgorithm {
function randomBytes(size: number): Uint8Array {
const buf = new Uint8Array(size);
- crypto.getRandomValues(buf);
+ globalThis.crypto.getRandomValues(buf);
return buf;
}
diff --git a/src/crypto/crypto.ts b/src/crypto/crypto.ts
index 170dabb0937..4aea59de52b 100644
--- a/src/crypto/crypto.ts
+++ b/src/crypto/crypto.ts
@@ -14,37 +14,5 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { logger } from "../logger";
-
-export let crypto = globalThis.crypto;
-export let subtleCrypto = crypto?.subtle ?? crypto?.webkitSubtle; // TODO: Stop using webkitSubtle fallback
-export let TextEncoder = globalThis.TextEncoder;
-
-/* eslint-disable @typescript-eslint/no-var-requires */
-if (!crypto) {
- try {
- crypto = require("crypto").webcrypto;
- } catch (e) {
- logger.error("Failed to load webcrypto", e);
- }
-}
-if (!subtleCrypto) {
- subtleCrypto = crypto?.subtle;
-}
-if (!TextEncoder) {
- try {
- TextEncoder = require("util").TextEncoder;
- } catch (e) {
- logger.error("Failed to load TextEncoder util", e);
- }
-}
-/* eslint-enable @typescript-eslint/no-var-requires */
-
-export function setCrypto(_crypto: Crypto): void {
- crypto = _crypto;
- subtleCrypto = _crypto.subtle ?? _crypto.webkitSubtle;
-}
-
-export function setTextEncoder(_TextEncoder: typeof TextEncoder): void {
- TextEncoder = _TextEncoder;
-}
+/** @deprecated this is a no-op and should no longer be called. */
+export function setCrypto(_crypto: Crypto): void {}
diff --git a/src/crypto/dehydration.ts b/src/crypto/dehydration.ts
index a24e65e4537..01dafa83c71 100644
--- a/src/crypto/dehydration.ts
+++ b/src/crypto/dehydration.ts
@@ -16,14 +16,14 @@ limitations under the License.
import anotherjson from "another-json";
-import type { IDeviceKeys, IOneTimeKey } from "../@types/crypto";
-import { decodeBase64, encodeBase64 } from "../base64";
-import { IndexedDBCryptoStore } from "../crypto/store/indexeddb-crypto-store";
-import { decryptAES, encryptAES } from "./aes";
-import { logger } from "../logger";
-import { Crypto } from "./index";
-import { Method } from "../http-api";
-import { SecretStorageKeyDescription } from "../secret-storage";
+import type { IDeviceKeys, IOneTimeKey } from "../@types/crypto.ts";
+import { decodeBase64, encodeBase64 } from "../base64.ts";
+import { IndexedDBCryptoStore } from "../crypto/store/indexeddb-crypto-store.ts";
+import { decryptAES, encryptAES } from "./aes.ts";
+import { logger } from "../logger.ts";
+import { Crypto } from "./index.ts";
+import { Method } from "../http-api/index.ts";
+import { SecretStorageKeyDescription } from "../secret-storage.ts";
export interface IDehydratedDevice {
device_id: string; // eslint-disable-line camelcase
diff --git a/src/crypto/device-converter.ts b/src/crypto/device-converter.ts
index cf32ef6141e..a2591150cfc 100644
--- a/src/crypto/device-converter.ts
+++ b/src/crypto/device-converter.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { Device } from "../models/device";
-import { DeviceInfo } from "./deviceinfo";
+import { Device } from "../models/device.ts";
+import { DeviceInfo } from "./deviceinfo.ts";
/**
* Convert a {@link DeviceInfo} to a {@link Device}.
diff --git a/src/crypto/deviceinfo.ts b/src/crypto/deviceinfo.ts
index 8b41c3c6784..7641af31692 100644
--- a/src/crypto/deviceinfo.ts
+++ b/src/crypto/deviceinfo.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { ISignatures } from "../@types/signed";
-import { DeviceVerification } from "../models/device";
+import { ISignatures } from "../@types/signed.ts";
+import { DeviceVerification } from "../models/device.ts";
export interface IDevice {
keys: Record;
diff --git a/src/crypto/index.ts b/src/crypto/index.ts
index 4379c2e1272..420160c0de4 100644
--- a/src/crypto/index.ts
+++ b/src/crypto/index.ts
@@ -20,55 +20,60 @@ limitations under the License.
import anotherjson from "another-json";
import { v4 as uuidv4 } from "uuid";
-import type { IDeviceKeys, IEventDecryptionResult, IMegolmSessionData, IOneTimeKey } from "../@types/crypto";
+import type { IDeviceKeys, IEventDecryptionResult, IMegolmSessionData, IOneTimeKey } from "../@types/crypto.ts";
import type { PkDecryption, PkSigning } from "@matrix-org/olm";
-import { EventType, ToDeviceMessageId } from "../@types/event";
-import { TypedReEmitter } from "../ReEmitter";
-import { logger } from "../logger";
-import { IExportedDevice, OlmDevice } from "./OlmDevice";
-import { IOlmDevice } from "./algorithms/megolm";
-import * as olmlib from "./olmlib";
-import { DeviceInfoMap, DeviceList } from "./DeviceList";
-import { DeviceInfo, IDevice } from "./deviceinfo";
-import type { DecryptionAlgorithm, EncryptionAlgorithm } from "./algorithms";
-import * as algorithms from "./algorithms";
-import { createCryptoStoreCacheCallbacks, CrossSigningInfo, DeviceTrustLevel, UserTrustLevel } from "./CrossSigning";
-import { EncryptionSetupBuilder } from "./EncryptionSetup";
-import { SecretStorage as LegacySecretStorage } from "./SecretStorage";
-import { CrossSigningKey, ICreateSecretStorageOpts, IEncryptedEventInfo, IRecoveryKey } from "./api";
-import { OutgoingRoomKeyRequestManager } from "./OutgoingRoomKeyRequestManager";
-import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store";
-import { VerificationBase } from "./verification/Base";
-import { ReciprocateQRCode, SCAN_QR_CODE_METHOD, SHOW_QR_CODE_METHOD } from "./verification/QRCode";
-import { SAS as SASVerification } from "./verification/SAS";
-import { keyFromPassphrase } from "./key_passphrase";
-import { decodeRecoveryKey, encodeRecoveryKey } from "./recoverykey";
-import { VerificationRequest } from "./verification/request/VerificationRequest";
-import { InRoomChannel, InRoomRequests } from "./verification/request/InRoomChannel";
-import { Request, ToDeviceChannel, ToDeviceRequests } from "./verification/request/ToDeviceChannel";
-import { IllegalMethod } from "./verification/IllegalMethod";
-import { KeySignatureUploadError } from "../errors";
-import { calculateKeyCheck, decryptAES, encryptAES, IEncryptedPayload } from "./aes";
-import { DehydrationManager } from "./dehydration";
-import { BackupManager, LibOlmBackupDecryptor, backupTrustInfoFromLegacyTrustInfo } from "./backup";
-import { IStore } from "../store";
-import { Room, RoomEvent } from "../models/room";
-import { RoomMember, RoomMemberEvent } from "../models/room-member";
-import { EventStatus, IContent, IEvent, MatrixEvent, MatrixEventEvent } from "../models/event";
-import { ToDeviceBatch } from "../models/ToDeviceMessage";
-import { ClientEvent, IKeysUploadResponse, ISignedKey, IUploadKeySignaturesResponse, MatrixClient } from "../client";
-import { IRoomEncryption, RoomList } from "./RoomList";
-import { IKeyBackupInfo } from "./keybackup";
-import { ISyncStateData } from "../sync";
-import { CryptoStore } from "./store/base";
-import { IVerificationChannel } from "./verification/request/Channel";
-import { TypedEventEmitter } from "../models/typed-event-emitter";
-import { IDeviceLists, ISyncResponse, IToDeviceEvent } from "../sync-accumulator";
-import { ISignatures } from "../@types/signed";
-import { IMessage } from "./algorithms/olm";
-import { BackupDecryptor, CryptoBackend, DecryptionError, OnSyncCompletedData } from "../common-crypto/CryptoBackend";
-import { RoomState, RoomStateEvent } from "../models/room-state";
-import { MapWithDefault, recursiveMapToObject } from "../utils";
+import { EventType, ToDeviceMessageId } from "../@types/event.ts";
+import { TypedReEmitter } from "../ReEmitter.ts";
+import { logger } from "../logger.ts";
+import { IExportedDevice, OlmDevice } from "./OlmDevice.ts";
+import { IOlmDevice } from "./algorithms/megolm.ts";
+import * as olmlib from "./olmlib.ts";
+import { DeviceInfoMap, DeviceList } from "./DeviceList.ts";
+import { DeviceInfo, IDevice } from "./deviceinfo.ts";
+import type { DecryptionAlgorithm, EncryptionAlgorithm } from "./algorithms/index.ts";
+import * as algorithms from "./algorithms/index.ts";
+import { createCryptoStoreCacheCallbacks, CrossSigningInfo, DeviceTrustLevel, UserTrustLevel } from "./CrossSigning.ts";
+import { EncryptionSetupBuilder } from "./EncryptionSetup.ts";
+import { SecretStorage as LegacySecretStorage } from "./SecretStorage.ts";
+import { CrossSigningKey, ICreateSecretStorageOpts, IEncryptedEventInfo, IRecoveryKey } from "./api.ts";
+import { OutgoingRoomKeyRequestManager } from "./OutgoingRoomKeyRequestManager.ts";
+import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store.ts";
+import { VerificationBase } from "./verification/Base.ts";
+import { ReciprocateQRCode, SCAN_QR_CODE_METHOD, SHOW_QR_CODE_METHOD } from "./verification/QRCode.ts";
+import { SAS as SASVerification } from "./verification/SAS.ts";
+import { keyFromPassphrase } from "./key_passphrase.ts";
+import { decodeRecoveryKey, encodeRecoveryKey } from "./recoverykey.ts";
+import { VerificationRequest } from "./verification/request/VerificationRequest.ts";
+import { InRoomChannel, InRoomRequests } from "./verification/request/InRoomChannel.ts";
+import { Request, ToDeviceChannel, ToDeviceRequests } from "./verification/request/ToDeviceChannel.ts";
+import { IllegalMethod } from "./verification/IllegalMethod.ts";
+import { KeySignatureUploadError } from "../errors.ts";
+import { calculateKeyCheck, decryptAES, encryptAES, IEncryptedPayload } from "./aes.ts";
+import { DehydrationManager } from "./dehydration.ts";
+import { BackupManager, LibOlmBackupDecryptor, backupTrustInfoFromLegacyTrustInfo } from "./backup.ts";
+import { IStore } from "../store/index.ts";
+import { Room, RoomEvent } from "../models/room.ts";
+import { RoomMember, RoomMemberEvent } from "../models/room-member.ts";
+import { EventStatus, IContent, IEvent, MatrixEvent, MatrixEventEvent } from "../models/event.ts";
+import { ToDeviceBatch } from "../models/ToDeviceMessage.ts";
+import { ClientEvent, IKeysUploadResponse, ISignedKey, IUploadKeySignaturesResponse, MatrixClient } from "../client.ts";
+import { IRoomEncryption, RoomList } from "./RoomList.ts";
+import { IKeyBackupInfo } from "./keybackup.ts";
+import { ISyncStateData } from "../sync.ts";
+import { CryptoStore } from "./store/base.ts";
+import { IVerificationChannel } from "./verification/request/Channel.ts";
+import { TypedEventEmitter } from "../models/typed-event-emitter.ts";
+import { IDeviceLists, ISyncResponse, IToDeviceEvent } from "../sync-accumulator.ts";
+import { ISignatures } from "../@types/signed.ts";
+import { IMessage } from "./algorithms/olm.ts";
+import {
+ BackupDecryptor,
+ CryptoBackend,
+ DecryptionError,
+ OnSyncCompletedData,
+} from "../common-crypto/CryptoBackend.ts";
+import { RoomState, RoomStateEvent } from "../models/room-state.ts";
+import { MapWithDefault, recursiveMapToObject } from "../utils.ts";
import {
AccountDataClient,
AddSecretStorageKeyOpts,
@@ -77,8 +82,8 @@ import {
SecretStorageKeyObject,
SecretStorageKeyTuple,
ServerSideSecretStorageImpl,
-} from "../secret-storage";
-import { ISecretRequest } from "./SecretSharing";
+} from "../secret-storage.ts";
+import { ISecretRequest } from "./SecretSharing.ts";
import {
BackupTrustInfo,
BootstrapCrossSigningOpts,
@@ -94,18 +99,18 @@ import {
KeyBackupInfo,
OwnDeviceKeys,
VerificationRequest as CryptoApiVerificationRequest,
-} from "../crypto-api";
-import { Device, DeviceMap } from "../models/device";
-import { deviceInfoToDevice } from "./device-converter";
-import { ClientPrefix, MatrixError, Method } from "../http-api";
-import { decodeBase64, encodeBase64 } from "../base64";
-import { KnownMembership } from "../@types/membership";
+} from "../crypto-api/index.ts";
+import { Device, DeviceMap } from "../models/device.ts";
+import { deviceInfoToDevice } from "./device-converter.ts";
+import { ClientPrefix, MatrixError, Method } from "../http-api/index.ts";
+import { decodeBase64, encodeBase64 } from "../base64.ts";
+import { KnownMembership } from "../@types/membership.ts";
/* re-exports for backwards compatibility */
export type {
BootstrapCrossSigningOpts as IBootstrapCrossSigningOpts,
CryptoCallbacks as ICryptoCallbacks,
-} from "../crypto-api";
+} from "../crypto-api/index.ts";
const DeviceVerification = DeviceInfo.DeviceVerification;
@@ -276,7 +281,7 @@ export type CryptoEventHandlerMap = {
* @param deviceId - the id of the verified device
* @param deviceInfo - updated device information
*/
- [CryptoEvent.DeviceVerificationChanged]: (userId: string, deviceId: string, device: DeviceInfo) => void;
+ [CryptoEvent.DeviceVerificationChanged]: (userId: string, deviceId: string, deviceInfo: DeviceInfo) => void;
/**
* Fires when the trust status of a user changes
* If userId is the userId of the logged-in user, this indicated a change
@@ -292,7 +297,7 @@ export type CryptoEventHandlerMap = {
/**
* Fires when we receive a room key request
*
- * @param req - request details
+ * @param request - request details
*/
[CryptoEvent.RoomKeyRequest]: (request: IncomingRoomKeyRequest) => void;
/**
@@ -4374,4 +4379,4 @@ class IncomingRoomKeyRequestCancellation {
}
// a number of types are re-exported for backwards compatibility, in case any applications are referencing it.
-export type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto";
+export type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto.ts";
diff --git a/src/crypto/key_passphrase.ts b/src/crypto/key_passphrase.ts
index f6fe7b6b7d7..85b9c48fbcd 100644
--- a/src/crypto/key_passphrase.ts
+++ b/src/crypto/key_passphrase.ts
@@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { randomString } from "../randomstring";
-import { subtleCrypto, TextEncoder } from "./crypto";
+import { randomString } from "../randomstring.ts";
const DEFAULT_ITERATIONS = 500000;
@@ -36,10 +35,6 @@ interface IKey {
}
export function keyFromAuthData(authData: IAuthData, password: string): Promise {
- if (!global.Olm) {
- throw new Error("Olm is not available");
- }
-
if (!authData.private_key_salt || !authData.private_key_iterations) {
throw new Error("Salt and/or iterations not found: " + "this backup cannot be restored with a passphrase");
}
@@ -53,10 +48,6 @@ export function keyFromAuthData(authData: IAuthData, password: string): Promise<
}
export async function keyFromPassphrase(password: string): Promise {
- if (!global.Olm) {
- throw new Error("Olm is not available");
- }
-
const salt = randomString(32);
const key = await deriveKey(password, salt, DEFAULT_ITERATIONS, DEFAULT_BITSIZE);
@@ -70,15 +61,19 @@ export async function deriveKey(
iterations: number,
numBits = DEFAULT_BITSIZE,
): Promise {
- if (!subtleCrypto || !TextEncoder) {
+ if (!globalThis.crypto.subtle || !TextEncoder) {
throw new Error("Password-based backup is not available on this platform");
}
- const key = await subtleCrypto.importKey("raw", new TextEncoder().encode(password), { name: "PBKDF2" }, false, [
- "deriveBits",
- ]);
+ const key = await globalThis.crypto.subtle.importKey(
+ "raw",
+ new TextEncoder().encode(password),
+ { name: "PBKDF2" },
+ false,
+ ["deriveBits"],
+ );
- const keybits = await subtleCrypto.deriveBits(
+ const keybits = await globalThis.crypto.subtle.deriveBits(
{
name: "PBKDF2",
salt: new TextEncoder().encode(salt),
diff --git a/src/crypto/keybackup.ts b/src/crypto/keybackup.ts
index 8ef04176cb2..4399a38601f 100644
--- a/src/crypto/keybackup.ts
+++ b/src/crypto/keybackup.ts
@@ -15,7 +15,7 @@ limitations under the License.
*/
// Export for backward compatibility
-import { ImportRoomKeyProgressData } from "../crypto-api";
+import { ImportRoomKeyProgressData } from "../crypto-api/index.ts";
export type {
Curve25519AuthData as ICurve25519AuthData,
@@ -24,7 +24,7 @@ export type {
Curve25519SessionData,
KeyBackupSession as IKeyBackupSession,
KeyBackupRoomSessions as IKeyBackupRoomSessions,
-} from "../crypto-api/keybackup";
+} from "../crypto-api/keybackup.ts";
/* eslint-enable camelcase */
diff --git a/src/crypto/olmlib.ts b/src/crypto/olmlib.ts
index 7396ef47988..9eceaf48bc7 100644
--- a/src/crypto/olmlib.ts
+++ b/src/crypto/olmlib.ts
@@ -21,16 +21,16 @@ limitations under the License.
import anotherjson from "another-json";
import type { PkSigning } from "@matrix-org/olm";
-import type { IOneTimeKey } from "../@types/crypto";
-import { OlmDevice } from "./OlmDevice";
-import { DeviceInfo } from "./deviceinfo";
-import { Logger, logger } from "../logger";
-import { IClaimOTKsResult, MatrixClient } from "../client";
-import { ISignatures } from "../@types/signed";
-import { MatrixEvent } from "../models/event";
-import { EventType } from "../@types/event";
-import { IMessage } from "./algorithms/olm";
-import { MapWithDefault } from "../utils";
+import type { IOneTimeKey } from "../@types/crypto.ts";
+import { OlmDevice } from "./OlmDevice.ts";
+import { DeviceInfo } from "./deviceinfo.ts";
+import { Logger, logger } from "../logger.ts";
+import { IClaimOTKsResult, MatrixClient } from "../client.ts";
+import { ISignatures } from "../@types/signed.ts";
+import { MatrixEvent } from "../models/event.ts";
+import { EventType } from "../@types/event.ts";
+import { IMessage } from "./algorithms/olm.ts";
+import { MapWithDefault } from "../utils.ts";
enum Algorithm {
Olm = "m.olm.v1.curve25519-aes-sha2",
diff --git a/src/crypto/recoverykey.ts b/src/crypto/recoverykey.ts
index 8c6a7e33ed7..3d7c12d4acf 100644
--- a/src/crypto/recoverykey.ts
+++ b/src/crypto/recoverykey.ts
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import * as bs58 from "bs58";
+import bs58 from "bs58";
// picked arbitrarily but to try & avoid clashing with any bitcoin ones
// (which are also base58 encoded, but bitcoin's involve a lot more hashing)
diff --git a/src/crypto/store/base.ts b/src/crypto/store/base.ts
index 871804b7379..daf11b5b0b3 100644
--- a/src/crypto/store/base.ts
+++ b/src/crypto/store/base.ts
@@ -14,19 +14,19 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { IRoomKeyRequestBody, IRoomKeyRequestRecipient } from "../index";
-import { RoomKeyRequestState } from "../OutgoingRoomKeyRequestManager";
-import { IOlmDevice } from "../algorithms/megolm";
-import { TrackingStatus } from "../DeviceList";
-import { IRoomEncryption } from "../RoomList";
-import { IDevice } from "../deviceinfo";
-import { ICrossSigningInfo } from "../CrossSigning";
-import { Logger } from "../../logger";
-import { InboundGroupSessionData } from "../OlmDevice";
-import { MatrixEvent } from "../../models/event";
-import { DehydrationManager } from "../dehydration";
-import { IEncryptedPayload } from "../aes";
-import { CrossSigningKeyInfo } from "../../crypto-api";
+import { IRoomKeyRequestBody, IRoomKeyRequestRecipient } from "../index.ts";
+import { RoomKeyRequestState } from "../OutgoingRoomKeyRequestManager.ts";
+import { IOlmDevice } from "../algorithms/megolm.ts";
+import { TrackingStatus } from "../DeviceList.ts";
+import { IRoomEncryption } from "../RoomList.ts";
+import { IDevice } from "../deviceinfo.ts";
+import { ICrossSigningInfo } from "../CrossSigning.ts";
+import { Logger } from "../../logger.ts";
+import { InboundGroupSessionData } from "../OlmDevice.ts";
+import { MatrixEvent } from "../../models/event.ts";
+import { DehydrationManager } from "../dehydration.ts";
+import { IEncryptedPayload } from "../aes.ts";
+import { CrossSigningKeyInfo } from "../../crypto-api/index.ts";
/**
* Internal module. Definitions for storage for the crypto module
diff --git a/src/crypto/store/indexeddb-crypto-store-backend.ts b/src/crypto/store/indexeddb-crypto-store-backend.ts
index 08d4c0f6e98..1ef3dd120e2 100644
--- a/src/crypto/store/indexeddb-crypto-store-backend.ts
+++ b/src/crypto/store/indexeddb-crypto-store-backend.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { Logger, logger } from "../../logger";
-import { deepCompare } from "../../utils";
+import { Logger, logger } from "../../logger.ts";
+import { deepCompare } from "../../utils.ts";
import {
CryptoStore,
IDeviceData,
@@ -31,13 +31,13 @@ import {
SecretStorePrivateKeys,
SESSION_BATCH_SIZE,
ACCOUNT_OBJECT_KEY_MIGRATION_STATE,
-} from "./base";
-import { IRoomKeyRequestBody, IRoomKeyRequestRecipient } from "../index";
-import { IOlmDevice } from "../algorithms/megolm";
-import { IRoomEncryption } from "../RoomList";
-import { InboundGroupSessionData } from "../OlmDevice";
-import { IndexedDBCryptoStore } from "./indexeddb-crypto-store";
-import { CrossSigningKeyInfo } from "../../crypto-api";
+} from "./base.ts";
+import { IRoomKeyRequestBody, IRoomKeyRequestRecipient } from "../index.ts";
+import { IOlmDevice } from "../algorithms/megolm.ts";
+import { IRoomEncryption } from "../RoomList.ts";
+import { InboundGroupSessionData } from "../OlmDevice.ts";
+import { IndexedDBCryptoStore } from "./indexeddb-crypto-store.ts";
+import { CrossSigningKeyInfo } from "../../crypto-api/index.ts";
const PROFILE_TRANSACTIONS = false;
diff --git a/src/crypto/store/indexeddb-crypto-store.ts b/src/crypto/store/indexeddb-crypto-store.ts
index 8fe488e08d0..29d32b5e34c 100644
--- a/src/crypto/store/indexeddb-crypto-store.ts
+++ b/src/crypto/store/indexeddb-crypto-store.ts
@@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { logger, Logger } from "../../logger";
-import { LocalStorageCryptoStore } from "./localStorage-crypto-store";
-import { MemoryCryptoStore } from "./memory-crypto-store";
-import * as IndexedDBCryptoStoreBackend from "./indexeddb-crypto-store-backend";
-import { InvalidCryptoStoreError, InvalidCryptoStoreState } from "../../errors";
-import * as IndexedDBHelpers from "../../indexeddb-helpers";
+import { logger, Logger } from "../../logger.ts";
+import { LocalStorageCryptoStore } from "./localStorage-crypto-store.ts";
+import { MemoryCryptoStore } from "./memory-crypto-store.ts";
+import * as IndexedDBCryptoStoreBackend from "./indexeddb-crypto-store-backend.ts";
+import { InvalidCryptoStoreError, InvalidCryptoStoreState } from "../../errors.ts";
+import * as IndexedDBHelpers from "../../indexeddb-helpers.ts";
import {
CryptoStore,
IDeviceData,
@@ -34,12 +34,12 @@ import {
ParkedSharedHistory,
SecretStorePrivateKeys,
ACCOUNT_OBJECT_KEY_MIGRATION_STATE,
-} from "./base";
-import { IRoomKeyRequestBody } from "../index";
-import { IOlmDevice } from "../algorithms/megolm";
-import { IRoomEncryption } from "../RoomList";
-import { InboundGroupSessionData } from "../OlmDevice";
-import { CrossSigningKeyInfo } from "../../crypto-api";
+} from "./base.ts";
+import { IRoomKeyRequestBody } from "../index.ts";
+import { IOlmDevice } from "../algorithms/megolm.ts";
+import { IRoomEncryption } from "../RoomList.ts";
+import { InboundGroupSessionData } from "../OlmDevice.ts";
+import { CrossSigningKeyInfo } from "../../crypto-api/index.ts";
/*
* Internal module. indexeddb storage for e2e.
diff --git a/src/crypto/store/localStorage-crypto-store.ts b/src/crypto/store/localStorage-crypto-store.ts
index 41821ec62a5..d24e648d634 100644
--- a/src/crypto/store/localStorage-crypto-store.ts
+++ b/src/crypto/store/localStorage-crypto-store.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { logger } from "../../logger";
-import { MemoryCryptoStore } from "./memory-crypto-store";
+import { logger } from "../../logger.ts";
+import { MemoryCryptoStore } from "./memory-crypto-store.ts";
import {
CryptoStore,
IDeviceData,
@@ -28,12 +28,12 @@ import {
Mode,
SecretStorePrivateKeys,
SESSION_BATCH_SIZE,
-} from "./base";
-import { IOlmDevice } from "../algorithms/megolm";
-import { IRoomEncryption } from "../RoomList";
-import { InboundGroupSessionData } from "../OlmDevice";
-import { safeSet } from "../../utils";
-import { CrossSigningKeyInfo } from "../../crypto-api";
+} from "./base.ts";
+import { IOlmDevice } from "../algorithms/megolm.ts";
+import { IRoomEncryption } from "../RoomList.ts";
+import { InboundGroupSessionData } from "../OlmDevice.ts";
+import { safeSet } from "../../utils.ts";
+import { CrossSigningKeyInfo } from "../../crypto-api/index.ts";
/**
* Internal module. Partial localStorage backed storage for e2e.
diff --git a/src/crypto/store/memory-crypto-store.ts b/src/crypto/store/memory-crypto-store.ts
index 4fd8a57f85e..65fca29d7b7 100644
--- a/src/crypto/store/memory-crypto-store.ts
+++ b/src/crypto/store/memory-crypto-store.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { logger } from "../../logger";
-import { deepCompare, promiseTry, safeSet } from "../../utils";
+import { logger } from "../../logger.ts";
+import { deepCompare, promiseTry, safeSet } from "../../utils.ts";
import {
CryptoStore,
IDeviceData,
@@ -30,12 +30,12 @@ import {
ParkedSharedHistory,
SecretStorePrivateKeys,
SESSION_BATCH_SIZE,
-} from "./base";
-import { IRoomKeyRequestBody } from "../index";
-import { IOlmDevice } from "../algorithms/megolm";
-import { IRoomEncryption } from "../RoomList";
-import { InboundGroupSessionData } from "../OlmDevice";
-import { CrossSigningKeyInfo } from "../../crypto-api";
+} from "./base.ts";
+import { IRoomKeyRequestBody } from "../index.ts";
+import { IOlmDevice } from "../algorithms/megolm.ts";
+import { IRoomEncryption } from "../RoomList.ts";
+import { InboundGroupSessionData } from "../OlmDevice.ts";
+import { CrossSigningKeyInfo } from "../../crypto-api/index.ts";
function encodeSessionKey(senderCurve25519Key: string, sessionId: string): string {
return encodeURIComponent(senderCurve25519Key) + "/" + encodeURIComponent(sessionId);
diff --git a/src/crypto/verification/Base.ts b/src/crypto/verification/Base.ts
index 308ea4401d7..179c868b64b 100644
--- a/src/crypto/verification/Base.ts
+++ b/src/crypto/verification/Base.ts
@@ -19,23 +19,23 @@ limitations under the License.
* Base class for verification methods.
*/
-import { MatrixEvent } from "../../models/event";
-import { EventType } from "../../@types/event";
-import { logger } from "../../logger";
-import { DeviceInfo } from "../deviceinfo";
-import { newTimeoutError } from "./Error";
-import { KeysDuringVerification, requestKeysDuringVerification } from "../CrossSigning";
-import { IVerificationChannel } from "./request/Channel";
-import { MatrixClient } from "../../client";
-import { VerificationRequest } from "./request/VerificationRequest";
-import { TypedEventEmitter } from "../../models/typed-event-emitter";
+import { MatrixEvent } from "../../models/event.ts";
+import { EventType } from "../../@types/event.ts";
+import { logger } from "../../logger.ts";
+import { DeviceInfo } from "../deviceinfo.ts";
+import { newTimeoutError } from "./Error.ts";
+import { KeysDuringVerification, requestKeysDuringVerification } from "../CrossSigning.ts";
+import { IVerificationChannel } from "./request/Channel.ts";
+import { MatrixClient } from "../../client.ts";
+import { VerificationRequest } from "./request/VerificationRequest.ts";
+import { TypedEventEmitter } from "../../models/typed-event-emitter.ts";
import {
ShowQrCodeCallbacks,
ShowSasCallbacks,
Verifier,
VerifierEvent,
VerifierEventHandlerMap,
-} from "../../crypto-api/verification";
+} from "../../crypto-api/verification.ts";
const timeoutException = new Error("Verification timed out");
diff --git a/src/crypto/verification/Error.ts b/src/crypto/verification/Error.ts
index da73ebb847e..4f609db3a8e 100644
--- a/src/crypto/verification/Error.ts
+++ b/src/crypto/verification/Error.ts
@@ -18,8 +18,8 @@ limitations under the License.
* Error messages.
*/
-import { MatrixEvent } from "../../models/event";
-import { EventType } from "../../@types/event";
+import { MatrixEvent } from "../../models/event.ts";
+import { EventType } from "../../@types/event.ts";
export function newVerificationError(code: string, reason: string, extraData?: Record): MatrixEvent {
const content = Object.assign({}, { code, reason }, extraData);
diff --git a/src/crypto/verification/IllegalMethod.ts b/src/crypto/verification/IllegalMethod.ts
index c437e0cd2a9..c556be71785 100644
--- a/src/crypto/verification/IllegalMethod.ts
+++ b/src/crypto/verification/IllegalMethod.ts
@@ -19,11 +19,11 @@ limitations under the License.
* do verification with this method).
*/
-import { VerificationBase as Base, VerificationEvent, VerificationEventHandlerMap } from "./Base";
-import { IVerificationChannel } from "./request/Channel";
-import { MatrixClient } from "../../client";
-import { MatrixEvent } from "../../models/event";
-import { VerificationRequest } from "./request/VerificationRequest";
+import { VerificationBase as Base, VerificationEvent, VerificationEventHandlerMap } from "./Base.ts";
+import { IVerificationChannel } from "./request/Channel.ts";
+import { MatrixClient } from "../../client.ts";
+import { MatrixEvent } from "../../models/event.ts";
+import { VerificationRequest } from "./request/VerificationRequest.ts";
export class IllegalMethod extends Base {
public static factory(
diff --git a/src/crypto/verification/QRCode.ts b/src/crypto/verification/QRCode.ts
index 7ccd4986d53..4caaf42b672 100644
--- a/src/crypto/verification/QRCode.ts
+++ b/src/crypto/verification/QRCode.ts
@@ -18,17 +18,16 @@ limitations under the License.
* QR code key verification.
*/
-import { crypto } from "../crypto";
-import { VerificationBase as Base } from "./Base";
-import { newKeyMismatchError, newUserCancelledError } from "./Error";
-import { decodeBase64, encodeUnpaddedBase64 } from "../../base64";
-import { logger } from "../../logger";
-import { VerificationRequest } from "./request/VerificationRequest";
-import { MatrixClient } from "../../client";
-import { IVerificationChannel } from "./request/Channel";
-import { MatrixEvent } from "../../models/event";
-import { ShowQrCodeCallbacks, VerifierEvent } from "../../crypto-api/verification";
-import { VerificationMethod } from "../../types";
+import { VerificationBase as Base } from "./Base.ts";
+import { newKeyMismatchError, newUserCancelledError } from "./Error.ts";
+import { decodeBase64, encodeUnpaddedBase64 } from "../../base64.ts";
+import { logger } from "../../logger.ts";
+import { VerificationRequest } from "./request/VerificationRequest.ts";
+import { MatrixClient } from "../../client.ts";
+import { IVerificationChannel } from "./request/Channel.ts";
+import { MatrixEvent } from "../../models/event.ts";
+import { ShowQrCodeCallbacks, VerifierEvent } from "../../crypto-api/verification.ts";
+import { VerificationMethod } from "../../types.ts";
export const SHOW_QR_CODE_METHOD = VerificationMethod.ShowQrCode;
export const SCAN_QR_CODE_METHOD = VerificationMethod.ScanQrCode;
@@ -202,7 +201,7 @@ export class QRCodeData {
private static generateSharedSecret(): string {
const secretBytes = new Uint8Array(11);
- crypto.getRandomValues(secretBytes);
+ globalThis.crypto.getRandomValues(secretBytes);
return encodeUnpaddedBase64(secretBytes);
}
diff --git a/src/crypto/verification/SAS.ts b/src/crypto/verification/SAS.ts
index f161278bc43..31e96753728 100644
--- a/src/crypto/verification/SAS.ts
+++ b/src/crypto/verification/SAS.ts
@@ -21,27 +21,27 @@ limitations under the License.
import anotherjson from "another-json";
import { Utility, SAS as OlmSAS } from "@matrix-org/olm";
-import { VerificationBase as Base, SwitchStartEventError } from "./Base";
+import { VerificationBase as Base, SwitchStartEventError } from "./Base.ts";
import {
errorFactory,
newInvalidMessageError,
newKeyMismatchError,
newUnknownMethodError,
newUserCancelledError,
-} from "./Error";
-import { logger } from "../../logger";
-import { IContent, MatrixEvent } from "../../models/event";
-import { generateDecimalSas } from "./SASDecimal";
-import { EventType } from "../../@types/event";
-import { EmojiMapping, GeneratedSas, ShowSasCallbacks, VerifierEvent } from "../../crypto-api/verification";
-import { VerificationMethod } from "../../types";
+} from "./Error.ts";
+import { logger } from "../../logger.ts";
+import { IContent, MatrixEvent } from "../../models/event.ts";
+import { generateDecimalSas } from "./SASDecimal.ts";
+import { EventType } from "../../@types/event.ts";
+import { EmojiMapping, GeneratedSas, ShowSasCallbacks, VerifierEvent } from "../../crypto-api/verification.ts";
+import { VerificationMethod } from "../../types.ts";
// backwards-compatibility exports
export type {
ShowSasCallbacks as ISasEvent,
GeneratedSas as IGeneratedSas,
EmojiMapping,
-} from "../../crypto-api/verification";
+} from "../../crypto-api/verification.ts";
const START_TYPE = EventType.KeyVerificationStart;
diff --git a/src/crypto/verification/request/Channel.ts b/src/crypto/verification/request/Channel.ts
index 48415f977e1..cb45c7b76c7 100644
--- a/src/crypto/verification/request/Channel.ts
+++ b/src/crypto/verification/request/Channel.ts
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { MatrixEvent } from "../../../models/event";
-import { VerificationRequest } from "./VerificationRequest";
+import { MatrixEvent } from "../../../models/event.ts";
+import { VerificationRequest } from "./VerificationRequest.ts";
export interface IVerificationChannel {
request?: VerificationRequest;
diff --git a/src/crypto/verification/request/InRoomChannel.ts b/src/crypto/verification/request/InRoomChannel.ts
index 59df11d7884..05dcce872d6 100644
--- a/src/crypto/verification/request/InRoomChannel.ts
+++ b/src/crypto/verification/request/InRoomChannel.ts
@@ -15,13 +15,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { VerificationRequest, REQUEST_TYPE, READY_TYPE, START_TYPE } from "./VerificationRequest";
-import { logger } from "../../../logger";
-import { IVerificationChannel } from "./Channel";
-import { EventType, TimelineEvents } from "../../../@types/event";
-import { MatrixClient } from "../../../client";
-import { MatrixEvent } from "../../../models/event";
-import { IRequestsMap } from "../..";
+import { VerificationRequest, REQUEST_TYPE, READY_TYPE, START_TYPE } from "./VerificationRequest.ts";
+import { logger } from "../../../logger.ts";
+import { IVerificationChannel } from "./Channel.ts";
+import { EventType, TimelineEvents } from "../../../@types/event.ts";
+import { MatrixClient } from "../../../client.ts";
+import { MatrixEvent } from "../../../models/event.ts";
+import { IRequestsMap } from "../../index.ts";
const MESSAGE_TYPE = EventType.RoomMessage;
const M_REFERENCE = "m.reference";
diff --git a/src/crypto/verification/request/ToDeviceChannel.ts b/src/crypto/verification/request/ToDeviceChannel.ts
index d51b85ac75f..34bf6f51ab5 100644
--- a/src/crypto/verification/request/ToDeviceChannel.ts
+++ b/src/crypto/verification/request/ToDeviceChannel.ts
@@ -15,8 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { randomString } from "../../../randomstring";
-import { logger } from "../../../logger";
+import { randomString } from "../../../randomstring.ts";
+import { logger } from "../../../logger.ts";
import {
CANCEL_TYPE,
PHASE_STARTED,
@@ -25,12 +25,12 @@ import {
READY_TYPE,
START_TYPE,
VerificationRequest,
-} from "./VerificationRequest";
-import { errorFromEvent, newUnexpectedMessageError } from "../Error";
-import { MatrixEvent } from "../../../models/event";
-import { IVerificationChannel } from "./Channel";
-import { MatrixClient } from "../../../client";
-import { IRequestsMap } from "../..";
+} from "./VerificationRequest.ts";
+import { errorFromEvent, newUnexpectedMessageError } from "../Error.ts";
+import { MatrixEvent } from "../../../models/event.ts";
+import { IVerificationChannel } from "./Channel.ts";
+import { MatrixClient } from "../../../client.ts";
+import { IRequestsMap } from "../../index.ts";
export type Request = VerificationRequest;
diff --git a/src/crypto/verification/request/VerificationRequest.ts b/src/crypto/verification/request/VerificationRequest.ts
index 5c544f131e2..8a3aca9a287 100644
--- a/src/crypto/verification/request/VerificationRequest.ts
+++ b/src/crypto/verification/request/VerificationRequest.ts
@@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { logger } from "../../../logger";
-import { errorFactory, errorFromEvent, newUnexpectedMessageError, newUnknownMethodError } from "../Error";
-import { QRCodeData, SCAN_QR_CODE_METHOD } from "../QRCode";
-import { IVerificationChannel } from "./Channel";
-import { MatrixClient } from "../../../client";
-import { MatrixEvent } from "../../../models/event";
-import { EventType } from "../../../@types/event";
-import { VerificationBase } from "../Base";
-import { VerificationMethod } from "../../index";
-import { TypedEventEmitter } from "../../../models/typed-event-emitter";
+import { logger } from "../../../logger.ts";
+import { errorFactory, errorFromEvent, newUnexpectedMessageError, newUnknownMethodError } from "../Error.ts";
+import { QRCodeData, SCAN_QR_CODE_METHOD } from "../QRCode.ts";
+import { IVerificationChannel } from "./Channel.ts";
+import { MatrixClient } from "../../../client.ts";
+import { MatrixEvent } from "../../../models/event.ts";
+import { EventType } from "../../../@types/event.ts";
+import { VerificationBase } from "../Base.ts";
+import { VerificationMethod } from "../../index.ts";
+import { TypedEventEmitter } from "../../../models/typed-event-emitter.ts";
import {
canAcceptVerificationRequest,
VerificationPhase as Phase,
@@ -31,10 +31,10 @@ import {
VerificationRequestEvent,
VerificationRequestEventHandlerMap,
Verifier,
-} from "../../../crypto-api/verification";
+} from "../../../crypto-api/verification.ts";
// backwards-compatibility exports
-export { VerificationPhase as Phase, VerificationRequestEvent } from "../../../crypto-api/verification";
+export { VerificationPhase as Phase, VerificationRequestEvent } from "../../../crypto-api/verification.ts";
// How long after the event's timestamp that the request times out
const TIMEOUT_FROM_EVENT_TS = 10 * 60 * 1000; // 10 minutes
diff --git a/src/digest.ts b/src/digest.ts
new file mode 100644
index 00000000000..85b5be9643b
--- /dev/null
+++ b/src/digest.ts
@@ -0,0 +1,34 @@
+/*
+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.
+*/
+
+/**
+ * Computes a SHA-256 hash of a string (after utf-8 encoding) and returns it as an ArrayBuffer.
+ *
+ * @param plaintext The string to hash
+ * @returns An ArrayBuffer containing the SHA-256 hash of the input string
+ * @throws If the subtle crypto API is not available, for example if the code is running
+ * in a web page with an insecure context (eg. served over plain HTTP).
+ */
+export async function sha256(plaintext: string): Promise {
+ if (!globalThis.crypto.subtle) {
+ throw new Error("Crypto.subtle is not available: insecure context?");
+ }
+ const utf8 = new TextEncoder().encode(plaintext);
+
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", utf8);
+
+ return digest;
+}
diff --git a/src/embedded.ts b/src/embedded.ts
index 8730c22ee3f..1974ea9f98e 100644
--- a/src/embedded.ts
+++ b/src/embedded.ts
@@ -25,10 +25,15 @@ import {
ISendEventFromWidgetResponseData,
} from "matrix-widget-api";
-import { MatrixEvent, IEvent, IContent, EventStatus } from "./models/event";
-import { ISendEventResponse } from "./@types/requests";
-import { EventType } from "./@types/event";
-import { logger } from "./logger";
+import { MatrixEvent, IEvent, IContent, EventStatus } from "./models/event.ts";
+import {
+ ISendEventResponse,
+ SendDelayedEventRequestOpts,
+ SendDelayedEventResponse,
+ UpdateDelayedEventAction,
+} from "./@types/requests.ts";
+import { EventType, StateEvents } from "./@types/event.ts";
+import { logger } from "./logger.ts";
import {
MatrixClient,
ClientEvent,
@@ -36,15 +41,16 @@ import {
IStartClientOpts,
SendToDeviceContentMap,
IOpenIDToken,
-} from "./client";
-import { SyncApi, SyncState } from "./sync";
-import { SlidingSyncSdk } from "./sliding-sync-sdk";
-import { User } from "./models/user";
-import { Room } from "./models/room";
-import { ToDeviceBatch, ToDevicePayload } from "./models/ToDeviceMessage";
-import { DeviceInfo } from "./crypto/deviceinfo";
-import { IOlmDevice } from "./crypto/algorithms/megolm";
-import { MapWithDefault, recursiveMapToObject } from "./utils";
+ UNSTABLE_MSC4140_DELAYED_EVENTS,
+} from "./client.ts";
+import { SyncApi, SyncState } from "./sync.ts";
+import { SlidingSyncSdk } from "./sliding-sync-sdk.ts";
+import { User } from "./models/user.ts";
+import { Room } from "./models/room.ts";
+import { ToDeviceBatch, ToDevicePayload } from "./models/ToDeviceMessage.ts";
+import { DeviceInfo } from "./crypto/deviceinfo.ts";
+import { IOlmDevice } from "./crypto/algorithms/megolm.ts";
+import { MapWithDefault, recursiveMapToObject } from "./utils.ts";
interface IStateEventRequest {
eventType: string;
@@ -95,6 +101,20 @@ export interface ICapabilities {
* @defaultValue false
*/
turnServers?: boolean;
+
+ /**
+ * Whether this client needs to be able to send delayed events.
+ * @experimental Part of MSC4140 & MSC4157
+ * @defaultValue false
+ */
+ sendDelayedEvents?: boolean;
+
+ /**
+ * Whether this client needs to be able to update delayed events.
+ * @experimental Part of MSC4140 & MSC4157
+ * @defaultValue false
+ */
+ updateDelayedEvents?: boolean;
}
/**
@@ -162,6 +182,18 @@ export class RoomWidgetClient extends MatrixClient {
);
capabilities.sendToDevice?.forEach((eventType) => widgetApi.requestCapabilityToSendToDevice(eventType));
capabilities.receiveToDevice?.forEach((eventType) => widgetApi.requestCapabilityToReceiveToDevice(eventType));
+ if (
+ capabilities.sendDelayedEvents &&
+ (capabilities.sendEvent?.length ||
+ capabilities.sendMessage === true ||
+ (Array.isArray(capabilities.sendMessage) && capabilities.sendMessage.length) ||
+ capabilities.sendState?.length)
+ ) {
+ widgetApi.requestCapability(MatrixCapabilities.MSC4157SendDelayedEvent);
+ }
+ if (capabilities.updateDelayedEvents) {
+ widgetApi.requestCapability(MatrixCapabilities.MSC4157UpdateDelayedEvent);
+ }
if (capabilities.turnServers) {
widgetApi.requestCapability(MatrixCapabilities.MSC3846TurnServers);
}
@@ -218,6 +250,14 @@ export class RoomWidgetClient extends MatrixClient {
});
}) ?? [],
);
+
+ if (opts.clientWellKnownPollPeriod !== undefined) {
+ this.clientWellKnownIntervalID = setInterval(() => {
+ this.fetchClientWellKnown();
+ }, 1000 * opts.clientWellKnownPollPeriod);
+ this.fetchClientWellKnown();
+ }
+
this.setSyncState(SyncState.Syncing);
logger.info("Finished backfilling events");
@@ -240,7 +280,29 @@ export class RoomWidgetClient extends MatrixClient {
throw new Error(`Unknown room: ${roomIdOrAlias}`);
}
- protected async encryptAndSendEvent(room: Room, event: MatrixEvent): Promise {
+ protected async encryptAndSendEvent(room: Room, event: MatrixEvent): Promise;
+ protected async encryptAndSendEvent(
+ room: Room,
+ event: MatrixEvent,
+ delayOpts: SendDelayedEventRequestOpts,
+ ): Promise;
+ protected async encryptAndSendEvent(
+ room: Room,
+ event: MatrixEvent,
+ delayOpts?: SendDelayedEventRequestOpts,
+ ): Promise {
+ if (delayOpts) {
+ // TODO: updatePendingEvent for delayed events?
+ const response = await this.widgetApi.sendRoomEvent(
+ event.getType(),
+ event.getContent(),
+ room.roomId,
+ "delay" in delayOpts ? delayOpts.delay : undefined,
+ "parent_delay_id" in delayOpts ? delayOpts.parent_delay_id : undefined,
+ );
+ return this.validateSendDelayedEventResponse(response);
+ }
+
let response: ISendEventFromWidgetResponseData;
try {
response = await this.widgetApi.sendRoomEvent(event.getType(), event.getContent(), room.roomId);
@@ -249,8 +311,9 @@ export class RoomWidgetClient extends MatrixClient {
throw e;
}
+ // This also checks for an event id on the response
room.updatePendingEvent(event, EventStatus.SENT, response.event_id);
- return { event_id: response.event_id };
+ return { event_id: response.event_id! };
}
public async sendStateEvent(
@@ -259,7 +322,56 @@ export class RoomWidgetClient extends MatrixClient {
content: any,
stateKey = "",
): Promise {
- return await this.widgetApi.sendStateEvent(eventType, stateKey, content, roomId);
+ const response = await this.widgetApi.sendStateEvent(eventType, stateKey, content, roomId);
+ if (response.event_id === undefined) {
+ throw new Error("'event_id' absent from response to an event request");
+ }
+ return { event_id: response.event_id };
+ }
+
+ /**
+ * @experimental This currently relies on an unstable MSC (MSC4140).
+ */
+ // eslint-disable-next-line
+ public async _unstable_sendDelayedStateEvent(
+ roomId: string,
+ delayOpts: SendDelayedEventRequestOpts,
+ eventType: K,
+ content: StateEvents[K],
+ stateKey = "",
+ ): Promise {
+ if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
+ throw Error("Server does not support the delayed events API");
+ }
+
+ const response = await this.widgetApi.sendStateEvent(
+ eventType,
+ stateKey,
+ content,
+ roomId,
+ "delay" in delayOpts ? delayOpts.delay : undefined,
+ "parent_delay_id" in delayOpts ? delayOpts.parent_delay_id : undefined,
+ );
+ return this.validateSendDelayedEventResponse(response);
+ }
+
+ private validateSendDelayedEventResponse(response: ISendEventFromWidgetResponseData): SendDelayedEventResponse {
+ if (response.delay_id === undefined) {
+ throw new Error("'delay_id' absent from response to a delayed event request");
+ }
+ return { delay_id: response.delay_id };
+ }
+
+ /**
+ * @experimental This currently relies on an unstable MSC (MSC4140).
+ */
+ // eslint-disable-next-line
+ public async _unstable_updateDelayedEvent(delayId: string, action: UpdateDelayedEventAction): Promise<{}> {
+ if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {
+ throw Error("Server does not support the delayed events API");
+ }
+
+ return await this.widgetApi.updateDelayedEvent(delayId, action);
}
public async sendToDevice(eventType: string, contentMap: SendToDeviceContentMap): Promise<{}> {
diff --git a/src/event-mapper.ts b/src/event-mapper.ts
index 828d87e9510..7dbf6a3c167 100644
--- a/src/event-mapper.ts
+++ b/src/event-mapper.ts
@@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { MatrixClient } from "./client";
-import { IEvent, MatrixEvent, MatrixEventEvent } from "./models/event";
-import { RelationType } from "./@types/event";
+import { MatrixClient } from "./client.ts";
+import { IEvent, MatrixEvent, MatrixEventEvent } from "./models/event.ts";
+import { RelationType } from "./@types/event.ts";
export type EventMapper = (obj: Partial) => MatrixEvent;
diff --git a/src/extensible_events_v1/ExtensibleEvent.ts b/src/extensible_events_v1/ExtensibleEvent.ts
index 049659251b6..3bfa0632ee8 100644
--- a/src/extensible_events_v1/ExtensibleEvent.ts
+++ b/src/extensible_events_v1/ExtensibleEvent.ts
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { ExtensibleEventType, IPartialEvent } from "../@types/extensible_events";
+import { ExtensibleEventType, IPartialEvent } from "../@types/extensible_events.ts";
/**
* Represents an Extensible Event in Matrix.
diff --git a/src/extensible_events_v1/MessageEvent.ts b/src/extensible_events_v1/MessageEvent.ts
index 3d049f45809..17457f04972 100644
--- a/src/extensible_events_v1/MessageEvent.ts
+++ b/src/extensible_events_v1/MessageEvent.ts
@@ -16,7 +16,7 @@ limitations under the License.
import { Optional } from "matrix-events-sdk";
-import { ExtensibleEvent } from "./ExtensibleEvent";
+import { ExtensibleEvent } from "./ExtensibleEvent.ts";
import {
ExtensibleEventType,
IMessageRendering,
@@ -26,9 +26,9 @@ import {
M_MESSAGE,
ExtensibleAnyMessageEventContent,
M_TEXT,
-} from "../@types/extensible_events";
-import { isOptionalAString, isProvided } from "./utilities";
-import { InvalidEventError } from "./InvalidEventError";
+} from "../@types/extensible_events.ts";
+import { isOptionalAString, isProvided } from "./utilities.ts";
+import { InvalidEventError } from "./InvalidEventError.ts";
/**
* Represents a message event. Message events are the simplest form of event with
diff --git a/src/extensible_events_v1/PollEndEvent.ts b/src/extensible_events_v1/PollEndEvent.ts
index 243f1906acf..87cd49569ad 100644
--- a/src/extensible_events_v1/PollEndEvent.ts
+++ b/src/extensible_events_v1/PollEndEvent.ts
@@ -20,11 +20,11 @@ import {
isEventTypeSame,
M_TEXT,
REFERENCE_RELATION,
-} from "../@types/extensible_events";
-import { M_POLL_END, PollEndEventContent } from "../@types/polls";
-import { ExtensibleEvent } from "./ExtensibleEvent";
-import { InvalidEventError } from "./InvalidEventError";
-import { MessageEvent } from "./MessageEvent";
+} from "../@types/extensible_events.ts";
+import { M_POLL_END, PollEndEventContent } from "../@types/polls.ts";
+import { ExtensibleEvent } from "./ExtensibleEvent.ts";
+import { InvalidEventError } from "./InvalidEventError.ts";
+import { MessageEvent } from "./MessageEvent.ts";
/**
* Represents a poll end/closure event.
diff --git a/src/extensible_events_v1/PollResponseEvent.ts b/src/extensible_events_v1/PollResponseEvent.ts
index a61fc2e7cb6..9e7659ba731 100644
--- a/src/extensible_events_v1/PollResponseEvent.ts
+++ b/src/extensible_events_v1/PollResponseEvent.ts
@@ -14,11 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { ExtensibleEvent } from "./ExtensibleEvent";
-import { M_POLL_RESPONSE, PollResponseEventContent, PollResponseSubtype } from "../@types/polls";
-import { ExtensibleEventType, IPartialEvent, isEventTypeSame, REFERENCE_RELATION } from "../@types/extensible_events";
-import { InvalidEventError } from "./InvalidEventError";
-import { PollStartEvent } from "./PollStartEvent";
+import { ExtensibleEvent } from "./ExtensibleEvent.ts";
+import { M_POLL_RESPONSE, PollResponseEventContent, PollResponseSubtype } from "../@types/polls.ts";
+import {
+ ExtensibleEventType,
+ IPartialEvent,
+ isEventTypeSame,
+ REFERENCE_RELATION,
+} from "../@types/extensible_events.ts";
+import { InvalidEventError } from "./InvalidEventError.ts";
+import { PollStartEvent } from "./PollStartEvent.ts";
/**
* Represents a poll response event.
diff --git a/src/extensible_events_v1/PollStartEvent.ts b/src/extensible_events_v1/PollStartEvent.ts
index 8584bf9e1fc..98b15e2ada9 100644
--- a/src/extensible_events_v1/PollStartEvent.ts
+++ b/src/extensible_events_v1/PollStartEvent.ts
@@ -16,8 +16,8 @@ limitations under the License.
import { NamespacedValue } from "matrix-events-sdk";
-import { MessageEvent } from "./MessageEvent";
-import { ExtensibleEventType, IPartialEvent, isEventTypeSame, M_TEXT } from "../@types/extensible_events";
+import { MessageEvent } from "./MessageEvent.ts";
+import { ExtensibleEventType, IPartialEvent, isEventTypeSame, M_TEXT } from "../@types/extensible_events.ts";
import {
KnownPollKind,
M_POLL_KIND_DISCLOSED,
@@ -26,9 +26,9 @@ import {
PollStartEventContent,
PollStartSubtype,
PollAnswer,
-} from "../@types/polls";
-import { InvalidEventError } from "./InvalidEventError";
-import { ExtensibleEvent } from "./ExtensibleEvent";
+} from "../@types/polls.ts";
+import { InvalidEventError } from "./InvalidEventError.ts";
+import { ExtensibleEvent } from "./ExtensibleEvent.ts";
/**
* Represents a poll answer. Note that this is represented as a subtype and is
diff --git a/src/feature.ts b/src/feature.ts
index 01cadd8e87c..47c914353bb 100644
--- a/src/feature.ts
+++ b/src/feature.ts
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { IServerVersions } from "./client";
+import { IServerVersions } from "./client.ts";
export enum ServerSupport {
Stable,
@@ -33,6 +33,7 @@ export enum Feature {
AccountDataDeletion = "AccountDataDeletion",
RelationsRecursion = "RelationsRecursion",
IntentionalMentions = "IntentionalMentions",
+ MigrateServerNameToVia = "MigrateServerNameToVia",
}
type FeatureSupportCondition = {
@@ -65,6 +66,9 @@ const featureSupportResolver: Record = {
unstablePrefixes: ["org.matrix.msc3952_intentional_mentions"],
matrixVersion: "v1.7",
},
+ [Feature.MigrateServerNameToVia]: {
+ unstablePrefixes: ["org.matrix.msc4156"],
+ },
};
export async function buildFeatureSupportMap(versions: IServerVersions): Promise