Compare commits
10 Commits
v34.8.0
...
v34.9.0-rc.0
| Author | SHA1 | Date | |
|---|---|---|---|
| b240c44128 | |||
| 5508993d79 | |||
| b842192a34 | |||
| 860161bdd2 | |||
| 0c9d82e40a | |||
| 73ab7c342a | |||
| 3386c66b98 | |||
| da044820d7 | |||
| 9f40f32b3e | |||
| f679942584 |
@@ -31,5 +31,22 @@ module.exports = {
|
||||
"@babel/plugin-transform-object-rest-spread",
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-transform-runtime",
|
||||
[
|
||||
"search-and-replace",
|
||||
{
|
||||
// Since rewriteImportExtensions doesn't work on dynamic imports (yet), we need to manually replace
|
||||
// the dynamic rust-crypto import.
|
||||
// (see https://github.com/babel/babel/issues/16750)
|
||||
rules:
|
||||
process.env.NODE_ENV !== "test"
|
||||
? [
|
||||
{
|
||||
search: "./rust-crypto/index.ts",
|
||||
replace: "./rust-crypto/index.js",
|
||||
},
|
||||
]
|
||||
: [],
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "matrix-js-sdk",
|
||||
"version": "34.8.0",
|
||||
"version": "34.9.0-rc.0",
|
||||
"description": "Matrix Client-Server SDK for Javascript",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
@@ -91,6 +91,7 @@
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^7.0.0",
|
||||
"babel-jest": "^29.0.0",
|
||||
"babel-plugin-search-and-replace": "^1.1.1",
|
||||
"debug": "^4.3.4",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
@@ -104,7 +105,7 @@
|
||||
"eslint-plugin-tsdoc": "^0.3.0",
|
||||
"eslint-plugin-unicorn": "^55.0.0",
|
||||
"fake-indexeddb": "^5.0.2",
|
||||
"fetch-mock": "11.1.3",
|
||||
"fetch-mock": "11.1.5",
|
||||
"fetch-mock-jest": "^1.5.1",
|
||||
"husky": "^9.0.0",
|
||||
"jest": "^29.0.0",
|
||||
|
||||
@@ -1010,6 +1010,48 @@ describe("MatrixRTCSession", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("Wraps key index around to 0 when it reaches the maximum", async () => {
|
||||
// this should give us keys with index [0...255, 0, 1]
|
||||
const membersToTest = 258;
|
||||
const members: CallMembershipData[] = [];
|
||||
for (let i = 0; i < membersToTest; i++) {
|
||||
members.push(Object.assign({}, membershipTemplate, { device_id: `DEVICE${i}` }));
|
||||
}
|
||||
jest.useFakeTimers();
|
||||
try {
|
||||
// start with a single member
|
||||
const mockRoom = makeMockRoom(members.slice(0, 1));
|
||||
|
||||
for (let i = 0; i < membersToTest; i++) {
|
||||
const keysSentPromise = new Promise<EncryptionKeysEventContent>((resolve) => {
|
||||
sendEventMock.mockImplementation((_roomId, _evType, payload) => resolve(payload));
|
||||
});
|
||||
|
||||
if (i === 0) {
|
||||
// if first time around then set up the session
|
||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||
sess.joinRoomSession([mockFocus], mockFocus, { manageMediaKeys: true });
|
||||
} else {
|
||||
// otherwise update the state
|
||||
mockRoom.getLiveTimeline().getState = jest
|
||||
.fn()
|
||||
.mockReturnValue(makeMockRoomState(members.slice(0, i + 1), mockRoom.roomId));
|
||||
}
|
||||
|
||||
sess!.onMembershipUpdate();
|
||||
|
||||
// advance time to avoid key throttling
|
||||
jest.advanceTimersByTime(10000);
|
||||
|
||||
const keysPayload = await keysSentPromise;
|
||||
expect(keysPayload.keys).toHaveLength(1);
|
||||
expect(keysPayload.keys[0].index).toEqual(i % 256);
|
||||
}
|
||||
} finally {
|
||||
jest.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it("Doesn't re-send key immediately", async () => {
|
||||
const realSetTimeout = setTimeout;
|
||||
jest.useFakeTimers();
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Mocked } from "jest-mock";
|
||||
|
||||
import {
|
||||
AccountDataClient,
|
||||
calculateKeyCheck,
|
||||
PassphraseInfo,
|
||||
SecretStorageCallbacks,
|
||||
SecretStorageKeyDescriptionAesV1,
|
||||
@@ -26,7 +27,6 @@ import {
|
||||
trimTrailingEquals,
|
||||
} from "../../src/secret-storage";
|
||||
import { randomString } from "../../src/randomstring";
|
||||
import { calculateKeyCheck } from "../../src/calculateKeyCheck.ts";
|
||||
|
||||
describe("ServerSideSecretStorageImpl", function () {
|
||||
describe(".addKey", function () {
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// string of zeroes, for calculating the key check
|
||||
import encryptAESSecretStorageItem from "./utils/encryptAESSecretStorageItem.ts";
|
||||
import { AESEncryptedSecretStoragePayload } from "./@types/AESEncryptedSecretStoragePayload.ts";
|
||||
|
||||
const ZERO_STR = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
|
||||
/**
|
||||
* Calculate the MAC for checking the key.
|
||||
* See https://spec.matrix.org/v1.11/client-server-api/#msecret_storagev1aes-hmac-sha2, steps 3 and 4.
|
||||
*
|
||||
* @param key - the key to use
|
||||
* @param iv - The initialization vector as a base64-encoded string.
|
||||
* If omitted, a random initialization vector will be created.
|
||||
* @returns An object that contains, `mac` and `iv` properties.
|
||||
*/
|
||||
export function calculateKeyCheck(key: Uint8Array, iv?: string): Promise<AESEncryptedSecretStoragePayload> {
|
||||
return encryptAESSecretStorageItem(ZERO_STR, key, "", iv);
|
||||
}
|
||||
+1
-3
@@ -2254,9 +2254,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
// importing rust-crypto will download the webassembly, so we delay it until we know it will be
|
||||
// needed.
|
||||
this.logger.debug("Downloading Rust crypto library");
|
||||
// blocked on https://github.com/matrix-org/matrix-js-sdk/issues/4392 / https://github.com/babel/babel/issues/16750
|
||||
// eslint-disable-next-line node/file-extension-in-import
|
||||
const RustCrypto = await import("./rust-crypto");
|
||||
const RustCrypto = await import("./rust-crypto/index.ts");
|
||||
|
||||
const rustCrypto = await RustCrypto.initRustCrypto({
|
||||
logger: this.logger,
|
||||
|
||||
+21
-12
@@ -25,6 +25,15 @@ import { BackupTrustInfo, KeyBackupCheck, KeyBackupInfo } from "./keybackup.ts";
|
||||
import { ISignatures } from "../@types/signed.ts";
|
||||
import { MatrixEvent } from "../models/event.ts";
|
||||
|
||||
/**
|
||||
* `matrix-js-sdk/lib/crypto-api`: End-to-end encryption support.
|
||||
*
|
||||
* The most important type is {@link CryptoApi}, an instance of which can be retrieved via
|
||||
* {@link MatrixClient.getCrypto}.
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Public interface to the cryptography parts of the js-sdk
|
||||
*
|
||||
@@ -181,7 +190,7 @@ export interface CryptoApi {
|
||||
/**
|
||||
* Return whether we trust other user's signatures of their devices.
|
||||
*
|
||||
* @see {@link Crypto.CryptoApi#setTrustCrossSignedDevices}
|
||||
* @see {@link CryptoApi.setTrustCrossSignedDevices}
|
||||
*
|
||||
* @returns `true` if we trust cross-signed devices, otherwise `false`.
|
||||
*/
|
||||
@@ -228,7 +237,7 @@ export interface CryptoApi {
|
||||
*
|
||||
* @throws an error if the device is unknown, or has not published any encryption keys.
|
||||
*
|
||||
* @remarks Fires {@link CryptoEvent#DeviceVerificationChanged}
|
||||
* @remarks Fires {@link matrix.CryptoEvent.DeviceVerificationChanged}
|
||||
*/
|
||||
setDeviceVerified(userId: string, deviceId: string, verified?: boolean): Promise<void>;
|
||||
|
||||
@@ -259,7 +268,7 @@ export interface CryptoApi {
|
||||
*
|
||||
* @returns True if cross-signing is ready to be used on this device
|
||||
*
|
||||
* @throws May throw {@link ClientStoppedError} if the `MatrixClient` is stopped before or during the call.
|
||||
* @throws May throw {@link matrix.ClientStoppedError} if the `MatrixClient` is stopped before or during the call.
|
||||
*/
|
||||
isCrossSigningReady(): Promise<boolean>;
|
||||
|
||||
@@ -327,7 +336,7 @@ export interface CryptoApi {
|
||||
* @returns The current status of cross-signing keys: whether we have public and private keys cached locally, and
|
||||
* whether the private keys are in secret storage.
|
||||
*
|
||||
* @throws May throw {@link ClientStoppedError} if the `MatrixClient` is stopped before or during the call.
|
||||
* @throws May throw {@link matrix.ClientStoppedError} if the `MatrixClient` is stopped before or during the call.
|
||||
*/
|
||||
getCrossSigningStatus(): Promise<CrossSigningStatus>;
|
||||
|
||||
@@ -407,8 +416,8 @@ export interface CryptoApi {
|
||||
*
|
||||
* If an all-devices verification is already in flight, returns it. Otherwise, initiates a new one.
|
||||
*
|
||||
* To control the methods offered, set {@link ICreateClientOpts.verificationMethods} when creating the
|
||||
* MatrixClient.
|
||||
* To control the methods offered, set {@link matrix.ICreateClientOpts.verificationMethods} when creating the
|
||||
* `MatrixClient`.
|
||||
*
|
||||
* @returns a VerificationRequest when the request has been sent to the other party.
|
||||
*/
|
||||
@@ -422,8 +431,8 @@ export interface CryptoApi {
|
||||
*
|
||||
* If a verification for this user/device is already in flight, returns it. Otherwise, initiates a new one.
|
||||
*
|
||||
* To control the methods offered, set {@link ICreateClientOpts.verificationMethods} when creating the
|
||||
* MatrixClient.
|
||||
* To control the methods offered, set {@link matrix.ICreateClientOpts.verificationMethods} when creating the
|
||||
* `MatrixClient`.
|
||||
*
|
||||
* @param userId - ID of the owner of the device to verify
|
||||
* @param deviceId - ID of the device to verify
|
||||
@@ -480,7 +489,7 @@ export interface CryptoApi {
|
||||
/**
|
||||
* Determine if a key backup can be trusted.
|
||||
*
|
||||
* @param info - key backup info dict from {@link MatrixClient#getKeyBackupVersion}.
|
||||
* @param info - key backup info dict from {@link matrix.MatrixClient.getKeyBackupVersion}.
|
||||
*/
|
||||
isKeyBackupTrusted(info: KeyBackupInfo): Promise<BackupTrustInfo>;
|
||||
|
||||
@@ -500,7 +509,7 @@ export interface CryptoApi {
|
||||
*
|
||||
* If there are existing backups they will be replaced.
|
||||
*
|
||||
* The decryption key will be saved in Secret Storage (the {@link SecretStorageCallbacks.getSecretStorageKey} Crypto
|
||||
* The decryption key will be saved in Secret Storage (the {@link matrix.SecretStorage.SecretStorageCallbacks.getSecretStorageKey} Crypto
|
||||
* callback will be called)
|
||||
* and the backup engine will be started.
|
||||
*/
|
||||
@@ -841,9 +850,9 @@ export class DeviceVerificationStatus {
|
||||
* Check if we should consider this device "verified".
|
||||
*
|
||||
* A device is "verified" if either:
|
||||
* * it has been manually marked as such via {@link MatrixClient#setDeviceVerified}.
|
||||
* * it has been manually marked as such via {@link matrix.MatrixClient.setDeviceVerified}.
|
||||
* * it has been cross-signed with a verified signing key, **and** the client has been configured to trust
|
||||
* cross-signed devices via {@link Crypto.CryptoApi#setTrustCrossSignedDevices}.
|
||||
* cross-signed devices via {@link CryptoApi.setTrustCrossSignedDevices}.
|
||||
*
|
||||
* @returns true if this device is verified via any means.
|
||||
*/
|
||||
|
||||
@@ -35,7 +35,7 @@ export interface Aes256AuthData {
|
||||
* Information about a server-side key backup.
|
||||
*
|
||||
* Returned by [`GET /_matrix/client/v3/room_keys/version`](https://spec.matrix.org/v1.7/client-server-api/#get_matrixclientv3room_keysversion)
|
||||
* and hence {@link MatrixClient#getKeyBackupVersion}.
|
||||
* and hence {@link matrix.MatrixClient.getKeyBackupVersion}.
|
||||
*/
|
||||
export interface KeyBackupInfo {
|
||||
algorithm: string;
|
||||
@@ -63,7 +63,7 @@ export interface BackupTrustInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* The result of {@link Crypto.CryptoApi.checkKeyBackupAndEnable}.
|
||||
* The result of {@link CryptoApi.checkKeyBackupAndEnable}.
|
||||
*/
|
||||
export interface KeyBackupCheck {
|
||||
backupInfo: KeyBackupInfo;
|
||||
|
||||
@@ -119,7 +119,7 @@ export interface VerificationRequest
|
||||
*
|
||||
* If a verifier has already been created for this request, returns that verifier.
|
||||
*
|
||||
* This does *not* send the `m.key.verification.start` event - to do so, call {@link Crypto.Verifier#verify} on the
|
||||
* This does *not* send the `m.key.verification.start` event - to do so, call {@link Verifier.verify} on the
|
||||
* returned verifier.
|
||||
*
|
||||
* If no previous events have been sent, pass in `targetDevice` to set who to direct this request to.
|
||||
@@ -281,7 +281,7 @@ export interface Verifier extends TypedEventEmitter<VerifierEvent, VerifierEvent
|
||||
* Cancel a verification.
|
||||
*
|
||||
* We will send an `m.key.verification.cancel` if the verification is still in flight. The verification promise
|
||||
* will reject, and a {@link Crypto.VerifierEvent#Cancel} will be emitted.
|
||||
* will reject, and a {@link crypto-api.VerifierEvent.Cancel | VerifierEvent.Cancel} will be emitted.
|
||||
*
|
||||
* @param e - the reason for the cancellation.
|
||||
*/
|
||||
|
||||
+3
-6
@@ -16,11 +16,8 @@ limitations under the License.
|
||||
|
||||
import encryptAESSecretStorageItem from "../utils/encryptAESSecretStorageItem.ts";
|
||||
import decryptAESSecretStorageItem from "../utils/decryptAESSecretStorageItem.ts";
|
||||
import { AESEncryptedSecretStoragePayload } from "../@types/AESEncryptedSecretStoragePayload.ts";
|
||||
|
||||
// Export for backwards compatibility
|
||||
export type { AESEncryptedSecretStoragePayload as IEncryptedPayload };
|
||||
// Export with new names instead of using `as` to not break react-sdk tests
|
||||
export const encryptAES = encryptAESSecretStorageItem;
|
||||
export const decryptAES = decryptAESSecretStorageItem;
|
||||
export { calculateKeyCheck } from "../calculateKeyCheck.ts";
|
||||
export type { AESEncryptedSecretStoragePayload as IEncryptedPayload } from "../@types/AESEncryptedSecretStoragePayload.ts";
|
||||
export { encryptAESSecretStorageItem as encryptAES, decryptAESSecretStorageItem as decryptAES };
|
||||
export { calculateKeyCheck } from "../secret-storage.ts";
|
||||
|
||||
@@ -43,7 +43,7 @@ import { encodeRecoveryKey } from "../crypto-api/index.ts";
|
||||
import decryptAESSecretStorageItem from "../utils/decryptAESSecretStorageItem.ts";
|
||||
import encryptAESSecretStorageItem from "../utils/encryptAESSecretStorageItem.ts";
|
||||
import { AESEncryptedSecretStoragePayload } from "../@types/AESEncryptedSecretStoragePayload.ts";
|
||||
import { calculateKeyCheck } from "../calculateKeyCheck.ts";
|
||||
import { calculateKeyCheck } from "../secret-storage.ts";
|
||||
|
||||
const KEY_BACKUP_KEYS_PER_REQUEST = 200;
|
||||
const KEY_BACKUP_CHECK_RATE_LIMIT = 5000; // ms
|
||||
|
||||
+8
-1
@@ -75,6 +75,7 @@ import { MapWithDefault, recursiveMapToObject } from "../utils.ts";
|
||||
import {
|
||||
AccountDataClient,
|
||||
AddSecretStorageKeyOpts,
|
||||
calculateKeyCheck,
|
||||
SECRET_STORAGE_ALGORITHM_V1_AES,
|
||||
SecretStorageKeyDescription,
|
||||
SecretStorageKeyObject,
|
||||
@@ -109,7 +110,6 @@ import { KnownMembership } from "../@types/membership.ts";
|
||||
import decryptAESSecretStorageItem from "../utils/decryptAESSecretStorageItem.ts";
|
||||
import encryptAESSecretStorageItem from "../utils/encryptAESSecretStorageItem.ts";
|
||||
import { AESEncryptedSecretStoragePayload } from "../@types/AESEncryptedSecretStoragePayload.ts";
|
||||
import { calculateKeyCheck } from "../calculateKeyCheck.ts";
|
||||
|
||||
/* re-exports for backwards compatibility */
|
||||
export type {
|
||||
@@ -230,10 +230,14 @@ export interface IMegolmEncryptedContent {
|
||||
export type IEncryptedContent = IOlmEncryptedContent | IMegolmEncryptedContent;
|
||||
|
||||
export enum CryptoEvent {
|
||||
/** @deprecated Event not fired by the rust crypto */
|
||||
DeviceVerificationChanged = "deviceVerificationChanged",
|
||||
UserTrustStatusChanged = "userTrustStatusChanged",
|
||||
/** @deprecated Event not fired by the rust crypto */
|
||||
UserCrossSigningUpdated = "userCrossSigningUpdated",
|
||||
/** @deprecated Event not fired by the rust crypto */
|
||||
RoomKeyRequest = "crypto.roomKeyRequest",
|
||||
/** @deprecated Event not fired by the rust crypto */
|
||||
RoomKeyRequestCancellation = "crypto.roomKeyRequestCancellation",
|
||||
KeyBackupStatus = "crypto.keyBackupStatus",
|
||||
KeyBackupFailed = "crypto.keyBackupFailed",
|
||||
@@ -250,6 +254,7 @@ export enum CryptoEvent {
|
||||
*/
|
||||
KeyBackupDecryptionKeyCached = "crypto.keyBackupDecryptionKeyCached",
|
||||
|
||||
/** @deprecated Event not fired by the rust crypto */
|
||||
KeySignatureUploadFailure = "crypto.keySignatureUploadFailure",
|
||||
/** @deprecated Use `VerificationRequestReceived`. */
|
||||
VerificationRequest = "crypto.verification.request",
|
||||
@@ -261,7 +266,9 @@ export enum CryptoEvent {
|
||||
*/
|
||||
VerificationRequestReceived = "crypto.verificationRequestReceived",
|
||||
|
||||
/** @deprecated Event not fired by the rust crypto */
|
||||
Warning = "crypto.warning",
|
||||
/** @deprecated Use {@link DevicesUpdated} instead when using rust crypto */
|
||||
WillUpdateDevices = "crypto.willUpdateDevices",
|
||||
DevicesUpdated = "crypto.devicesUpdated",
|
||||
KeysChanged = "crossSigning.keysChanged",
|
||||
|
||||
+1
-6
@@ -108,12 +108,7 @@ export type { ISSOFlow as SSOFlow, LoginFlow } from "./@types/auth.ts";
|
||||
export type { IHierarchyRelation as HierarchyRelation, IHierarchyRoom as HierarchyRoom } from "./@types/spaces.ts";
|
||||
export { LocationAssetType } from "./@types/location.ts";
|
||||
|
||||
/**
|
||||
* Types supporting cryptography.
|
||||
*
|
||||
* The most important is {@link Crypto.CryptoApi}, an instance of which can be retrieved via
|
||||
* {@link MatrixClient.getCrypto}.
|
||||
*/
|
||||
/** @deprecated Backwards-compatibility re-export. Import from `crypto-api` directly. */
|
||||
export * as Crypto from "./crypto-api/index.ts";
|
||||
|
||||
let cryptoStoreFactory = (): CryptoStore => new MemoryCryptoStore();
|
||||
|
||||
@@ -448,13 +448,12 @@ export class MatrixRTCSession extends TypedEventEmitter<MatrixRTCSessionEvent, M
|
||||
}
|
||||
|
||||
private getNewEncryptionKeyIndex(): number {
|
||||
const userId = this.client.getUserId();
|
||||
const deviceId = this.client.getDeviceId();
|
||||
if (this.currentEncryptionKeyIndex === -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!userId) throw new Error("No userId!");
|
||||
if (!deviceId) throw new Error("No deviceId!");
|
||||
|
||||
return (this.getKeysForParticipantInternal(userId, deviceId)?.length ?? 0) % 16;
|
||||
// maximum key index is 255
|
||||
return (this.currentEncryptionKeyIndex + 1) % 256;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,7 @@ export class TypedEventEmitter<
|
||||
SuperclassArguments extends ListenerMap<any> = Arguments,
|
||||
> extends EventEmitter {
|
||||
/**
|
||||
* Alias for {@link TypedEventEmitter#on}.
|
||||
* Alias for {@link on}.
|
||||
*/
|
||||
public addListener<T extends Events | EventEmitterEvents>(
|
||||
event: T,
|
||||
@@ -124,7 +124,7 @@ export class TypedEventEmitter<
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for {@link TypedEventEmitter#removeListener}
|
||||
* Alias for {@link removeListener}
|
||||
*/
|
||||
public off<T extends Events | EventEmitterEvents>(event: T, listener: Listener<Events, Arguments, T>): this {
|
||||
return super.off(event, listener);
|
||||
@@ -139,7 +139,7 @@ export class TypedEventEmitter<
|
||||
* being added, and called, multiple times.
|
||||
*
|
||||
* By default, event listeners are invoked in the order they are added. The
|
||||
* {@link TypedEventEmitter#prependListener} method can be used as an alternative to add the
|
||||
* {@link prependListener} method can be used as an alternative to add the
|
||||
* event listener to the beginning of the listeners array.
|
||||
*
|
||||
* @param event - The name of the event.
|
||||
@@ -158,7 +158,7 @@ export class TypedEventEmitter<
|
||||
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||
*
|
||||
* By default, event listeners are invoked in the order they are added.
|
||||
* The {@link TypedEventEmitter#prependOnceListener} method can be used as an alternative to add the
|
||||
* The {@link prependOnceListener} method can be used as an alternative to add the
|
||||
* event listener to the beginning of the listeners array.
|
||||
*
|
||||
* @param event - The name of the event.
|
||||
|
||||
+17
-2
@@ -28,7 +28,6 @@ import { logger } from "./logger.ts";
|
||||
import encryptAESSecretStorageItem from "./utils/encryptAESSecretStorageItem.ts";
|
||||
import decryptAESSecretStorageItem from "./utils/decryptAESSecretStorageItem.ts";
|
||||
import { AESEncryptedSecretStoragePayload } from "./@types/AESEncryptedSecretStoragePayload.ts";
|
||||
import { calculateKeyCheck } from "./crypto/aes.ts";
|
||||
|
||||
export const SECRET_STORAGE_ALGORITHM_V1_AES = "m.secret_storage.v1.aes-hmac-sha2";
|
||||
|
||||
@@ -165,7 +164,7 @@ export interface SecretStorageCallbacks {
|
||||
* Descriptions of the secret storage keys are also stored in server-side storage, per the
|
||||
* [matrix specification](https://spec.matrix.org/v1.6/client-server-api/#key-storage), so
|
||||
* before a key can be used in this way, it must have been stored on the server. This is
|
||||
* done via {@link SecretStorage.ServerSideSecretStorage#addKey}.
|
||||
* done via {@link ServerSideSecretStorage#addKey}.
|
||||
*
|
||||
* Obviously the keys themselves are not stored server-side, so the js-sdk calls this callback
|
||||
* in order to retrieve a secret storage key from the application.
|
||||
@@ -676,3 +675,19 @@ export function trimTrailingEquals(input: string): string {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
// string of zeroes, for calculating the key check
|
||||
const ZERO_STR = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
|
||||
/**
|
||||
* Calculate the MAC for checking the key.
|
||||
* See https://spec.matrix.org/v1.11/client-server-api/#msecret_storagev1aes-hmac-sha2, steps 3 and 4.
|
||||
*
|
||||
* @param key - the key to use
|
||||
* @param iv - The initialization vector as a base64-encoded string.
|
||||
* If omitted, a random initialization vector will be created.
|
||||
* @returns An object that contains, `mac` and `iv` properties.
|
||||
*/
|
||||
export function calculateKeyCheck(key: Uint8Array, iv?: string): Promise<AESEncryptedSecretStoragePayload> {
|
||||
return encryptAESSecretStorageItem(ZERO_STR, key, "", iv);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { logger } from "../logger.ts";
|
||||
import { ISavedSync } from "./index.ts";
|
||||
import { IIndexedDBBackend } from "./indexeddb-backend.ts";
|
||||
import { ISyncResponse } from "../sync-accumulator.ts";
|
||||
import { TypedEventEmitter } from "../models/typed-event-emitter.ts";
|
||||
import { EventEmitterEvents, TypedEventEmitter } from "../models/typed-event-emitter.ts";
|
||||
import { IStateEventWithRoomId } from "../@types/search.ts";
|
||||
import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDeviceMessage.ts";
|
||||
import { IStoredClientOpts } from "../client.ts";
|
||||
@@ -118,7 +118,10 @@ export class IndexedDBStore extends MemoryStore {
|
||||
}
|
||||
}
|
||||
|
||||
public on = this.emitter.on.bind(this.emitter);
|
||||
/** Re-exports `TypedEventEmitter.on` */
|
||||
public on(event: EventEmitterEvents | "degraded" | "closed", handler: (...args: any[]) => void): void {
|
||||
this.emitter.on(event, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Resolved when loaded from indexed db.
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://typedoc.org/schema.json",
|
||||
"plugin": ["typedoc-plugin-mdn-links", "typedoc-plugin-missing-exports", "typedoc-plugin-coverage"],
|
||||
"coverageLabel": "TypeDoc",
|
||||
"entryPoints": ["src/matrix.ts", "src/types.ts", "src/testing.ts", "src/utils/*.ts"],
|
||||
"entryPoints": ["src/matrix.ts", "src/crypto-api", "src/types.ts", "src/testing.ts", "src/utils/*.ts"],
|
||||
"excludeExternals": true,
|
||||
"out": "_docs"
|
||||
}
|
||||
|
||||
@@ -1796,9 +1796,9 @@
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/node@18":
|
||||
version "18.19.50"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.50.tgz#8652b34ee7c0e7e2004b3f08192281808d41bf5a"
|
||||
integrity sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==
|
||||
version "18.19.54"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.54.tgz#f1048dc083f81b242640f04f18fb3e4ccf13fcdb"
|
||||
integrity sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
@@ -2278,6 +2278,11 @@ babel-plugin-polyfill-regenerator@^0.6.1:
|
||||
dependencies:
|
||||
"@babel/helper-define-polyfill-provider" "^0.6.2"
|
||||
|
||||
babel-plugin-search-and-replace@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-search-and-replace/-/babel-plugin-search-and-replace-1.1.1.tgz#2e5b4488e41d9eba1c220651b1a9b350fdf10915"
|
||||
integrity sha512-fjP2VTF3mxxOUnc96mdK22llH92A6gu7A5AFapJmgnqsQi3bqLduIRP0FpA2r5vRZOYPpnX4rE5izQlpsMBjSA==
|
||||
|
||||
babel-preset-current-node-syntax@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b"
|
||||
@@ -3128,9 +3133,9 @@ eslint-plugin-jest@^28.0.0:
|
||||
"@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
|
||||
eslint-plugin-jsdoc@^50.0.0:
|
||||
version "50.2.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.2.4.tgz#9abef68ea5869e87d8a4444bfef9e5a7787162e2"
|
||||
integrity sha512-020jA+dXaXdb+TML3ZJBvpPmzwbNROjnYuTYi/g6A5QEmEjhptz4oPJDKkOGMIByNxsPpdTLzSU1HYVqebOX1w==
|
||||
version "50.3.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.1.tgz#4b56340a3ef55df9957dede430c6338c717dc0dc"
|
||||
integrity sha512-SY9oUuTMr6aWoJggUS40LtMjsRzJPB5ZT7F432xZIHK3EfHF+8i48GbUBpwanrtlL9l1gILNTHK9o8gEhYLcKA==
|
||||
dependencies:
|
||||
"@es-joy/jsdoccomment" "~0.48.0"
|
||||
are-docs-informative "^0.0.2"
|
||||
@@ -3234,10 +3239,10 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb"
|
||||
integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==
|
||||
eslint-visitor-keys@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz#1f785cc5e81eb7534523d85922248232077d2f8c"
|
||||
integrity sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==
|
||||
|
||||
eslint@8.57.0:
|
||||
version "8.57.0"
|
||||
@@ -3284,13 +3289,13 @@ eslint@8.57.0:
|
||||
text-table "^0.2.0"
|
||||
|
||||
espree@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56"
|
||||
integrity sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-10.2.0.tgz#f4bcead9e05b0615c968e85f83816bc386a45df6"
|
||||
integrity sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==
|
||||
dependencies:
|
||||
acorn "^8.12.0"
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^4.0.0"
|
||||
eslint-visitor-keys "^4.1.0"
|
||||
|
||||
espree@^9.6.0, espree@^9.6.1:
|
||||
version "9.6.1"
|
||||
@@ -3454,10 +3459,10 @@ fetch-mock-jest@^1.5.1:
|
||||
dependencies:
|
||||
fetch-mock "^9.11.0"
|
||||
|
||||
fetch-mock@11.1.3:
|
||||
version "11.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-11.1.3.tgz#3dc8dcc81340fea1cf1db60a2c195c63e270b501"
|
||||
integrity sha512-ATh0dWgnVrUHiiXuvQm1Ry+ThWfSv1QQgqJTCtybrNxyUrFiSOaDKsNG29eyysp1SHeNP6Q+dH50+8VifN51Ig==
|
||||
fetch-mock@11.1.5:
|
||||
version "11.1.5"
|
||||
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-11.1.5.tgz#77f78942f3733cfba47fc232b8528d1138a6761f"
|
||||
integrity sha512-KHmZDnZ1ry0pCTrX4YG5DtThHi0MH+GNI9caESnzX/nMJBrvppUHMvLx47M0WY9oAtKOMiPfZDRpxhlHg89BOA==
|
||||
dependencies:
|
||||
"@types/glob-to-regexp" "^0.4.4"
|
||||
dequal "^2.0.3"
|
||||
@@ -4754,9 +4759,9 @@ kleur@^3.0.3:
|
||||
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||
|
||||
knip@^5.0.0:
|
||||
version "5.30.2"
|
||||
resolved "https://registry.yarnpkg.com/knip/-/knip-5.30.2.tgz#3cee8df2e1eb0c858f81e64568b72c0a23b94479"
|
||||
integrity sha512-UuUwuTN+6Aa6mjxufWwidayGX/tPJsxZSlwUo8q4R+Gf/0aNYuhHsUH/GccuKtRPfFnf3r+ZU/7BV0dNfC7OEQ==
|
||||
version "5.30.6"
|
||||
resolved "https://registry.yarnpkg.com/knip/-/knip-5.30.6.tgz#798dd6a7fe338025166b8b138bb183d6b8714b75"
|
||||
integrity sha512-YkcnRVl0N99xZ7eaXE7KlH/4cPTCn6BGuk9KxINEdCMFN3yita2vGBizApy97ZOHgghy8tb589gQ3xvLMFIO4w==
|
||||
dependencies:
|
||||
"@nodelib/fs.walk" "1.2.8"
|
||||
"@snyk/github-codeowners" "1.1.0"
|
||||
@@ -4769,7 +4774,7 @@ knip@^5.0.0:
|
||||
picocolors "^1.0.0"
|
||||
picomatch "^4.0.1"
|
||||
pretty-ms "^9.0.0"
|
||||
smol-toml "^1.1.4"
|
||||
smol-toml "^1.3.0"
|
||||
strip-json-comments "5.0.1"
|
||||
summary "2.1.0"
|
||||
zod "^3.22.4"
|
||||
@@ -5321,9 +5326,9 @@ parent-module@^1.0.0:
|
||||
callsites "^3.0.0"
|
||||
|
||||
parse-imports@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/parse-imports/-/parse-imports-2.1.1.tgz#ce52141df24990065d72a446a364bffd595577f4"
|
||||
integrity sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA==
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/parse-imports/-/parse-imports-2.2.1.tgz#0a6e8b5316beb5c9905f50eb2bbb8c64a4805642"
|
||||
integrity sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==
|
||||
dependencies:
|
||||
es-module-lexer "^1.5.3"
|
||||
slashes "^3.0.12"
|
||||
@@ -5906,7 +5911,7 @@ slice-ansi@^7.1.0:
|
||||
ansi-styles "^6.2.1"
|
||||
is-fullwidth-code-point "^5.0.0"
|
||||
|
||||
smol-toml@^1.1.4:
|
||||
smol-toml@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.3.0.tgz#5200e251fffadbb72570c84e9776d2a3eca48143"
|
||||
integrity sha512-tWpi2TsODPScmi48b/OQZGi2lgUmBCHy6SZrhi/FdnnHiU1GwebbCfuQuxsC3nHaLwtYeJGPrDZDIeodDOc4pA==
|
||||
|
||||
Reference in New Issue
Block a user