1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-25 05:23:13 +03:00

Some more types

This commit is contained in:
Michael Telatynski
2021-06-24 21:48:55 +01:00
parent 3675e95970
commit 48ad9ba3d7
3 changed files with 93 additions and 47 deletions

View File

@@ -47,7 +47,7 @@ import {
PREFIX_UNSTABLE, PREFIX_UNSTABLE,
retryNetworkOperation, retryNetworkOperation,
} from "./http-api"; } from "./http-api";
import { Crypto, fixBackupKey, IBootstrapCrossSigningOpts, isCryptoAvailable } from './crypto'; import { Crypto, fixBackupKey, IBootstrapCrossSigningOpts, IMegolmSessionData, isCryptoAvailable } from './crypto';
import { DeviceInfo, IDevice } from "./crypto/deviceinfo"; import { DeviceInfo, IDevice } from "./crypto/deviceinfo";
import { decodeRecoveryKey } from './crypto/recoverykey'; import { decodeRecoveryKey } from './crypto/recoverykey';
import { keyFromAuthData } from './crypto/key_passphrase'; import { keyFromAuthData } from './crypto/key_passphrase';
@@ -2096,7 +2096,7 @@ export class MatrixClient extends EventEmitter {
* @return {Promise} a promise which resolves when the keys * @return {Promise} a promise which resolves when the keys
* have been imported * have been imported
*/ */
public importRoomKeys(keys: any[], opts: IImportRoomKeysOpts): Promise<void> { public importRoomKeys(keys: IMegolmSessionData[], opts: IImportRoomKeysOpts): Promise<void> {
if (!this.crypto) { if (!this.crypto) {
throw new Error("End-to-end encryption disabled"); throw new Error("End-to-end encryption disabled");
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 - 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -20,13 +20,20 @@ limitations under the License.
* @module * @module
*/ */
import { MatrixClient } from "../../client";
import { Room } from "../../models/room";
import { OlmDevice } from "../OlmDevice";
import { MatrixEvent, RoomMember } from "../..";
import { IEventDecryptionResult, IMegolmSessionData, IncomingRoomKeyRequest } from "..";
import { DeviceInfo } from "../deviceinfo";
/** /**
* map of registered encryption algorithm classes. A map from string to {@link * map of registered encryption algorithm classes. A map from string to {@link
* module:crypto/algorithms/base.EncryptionAlgorithm|EncryptionAlgorithm} class * module:crypto/algorithms/base.EncryptionAlgorithm|EncryptionAlgorithm} class
* *
* @type {Object.<string, function(new: module:crypto/algorithms/base.EncryptionAlgorithm)>} * @type {Object.<string, function(new: module:crypto/algorithms/base.EncryptionAlgorithm)>}
*/ */
export const ENCRYPTION_CLASSES = {}; export const ENCRYPTION_CLASSES: Record<string, EncryptionAlgorithm> = {};
/** /**
* map of registered encryption algorithm classes. Map from string to {@link * map of registered encryption algorithm classes. Map from string to {@link
@@ -34,7 +41,16 @@ export const ENCRYPTION_CLASSES = {};
* *
* @type {Object.<string, function(new: module:crypto/algorithms/base.DecryptionAlgorithm)>} * @type {Object.<string, function(new: module:crypto/algorithms/base.DecryptionAlgorithm)>}
*/ */
export const DECRYPTION_CLASSES = {}; export const DECRYPTION_CLASSES: Record<string, DecryptionAlgorithm> = {};
interface IParams {
userId: string;
deviceId: string;
crypto: Crypto;
olmDevice: OlmDevice;
baseApis: MatrixClient;
roomId: string;
}
/** /**
* base type for encryption implementations * base type for encryption implementations
@@ -50,14 +66,21 @@ export const DECRYPTION_CLASSES = {};
* @param {string} params.roomId The ID of the room we will be sending to * @param {string} params.roomId The ID of the room we will be sending to
* @param {object} params.config The body of the m.room.encryption event * @param {object} params.config The body of the m.room.encryption event
*/ */
export class EncryptionAlgorithm { export abstract class EncryptionAlgorithm {
constructor(params) { protected readonly userId: string;
this._userId = params.userId; protected readonly deviceId: string;
this._deviceId = params.deviceId; protected readonly crypto: Crypto;
this._crypto = params.crypto; protected readonly olmDevice: OlmDevice;
this._olmDevice = params.olmDevice; protected readonly baseApis: MatrixClient;
this._baseApis = params.baseApis; protected readonly roomId: string;
this._roomId = params.roomId;
constructor(params: IParams) {
this.userId = params.userId;
this.deviceId = params.deviceId;
this.crypto = params.crypto;
this.olmDevice = params.olmDevice;
this.baseApis = params.baseApis;
this.roomId = params.roomId;
} }
/** /**
@@ -66,21 +89,22 @@ export class EncryptionAlgorithm {
* *
* @param {module:models/room} room the room the event is in * @param {module:models/room} room the room the event is in
*/ */
prepareToEncrypt(room) { public abstract prepareToEncrypt(room: Room): void;
}
/** /**
* Encrypt a message event * Encrypt a message event
* *
* @method module:crypto/algorithms/base.EncryptionAlgorithm.encryptMessage * @method module:crypto/algorithms/base.EncryptionAlgorithm.encryptMessage
* @public
* @abstract * @abstract
* *
* @param {module:models/room} room * @param {module:models/room} room
* @param {string} eventType * @param {string} eventType
* @param {object} plaintext event content * @param {object} content event content
* *
* @return {Promise} Promise which resolves to the new event body * @return {Promise} Promise which resolves to the new event body
*/ */
public abstract encryptMessage(room: Room, eventType: string, content: object): Promise<object>;
/** /**
* Called when the membership of a member of the room changes. * Called when the membership of a member of the room changes.
@@ -89,9 +113,18 @@ export class EncryptionAlgorithm {
* @param {module:models/room-member} member user whose membership changed * @param {module:models/room-member} member user whose membership changed
* @param {string=} oldMembership previous membership * @param {string=} oldMembership previous membership
* @public * @public
* @abstract
*/ */
onRoomMembership(event, member, oldMembership) { public abstract onRoomMembership(event: MatrixEvent, member: RoomMember, oldMembership?: string);
}
public abstract reshareKeyWithDevice(
senderKey: string,
sessionId: string,
userId: string,
device: DeviceInfo,
): Promise<void>;
public forceDiscardSession?: () => void;
} }
/** /**
@@ -106,13 +139,19 @@ export class EncryptionAlgorithm {
* @param {string=} params.roomId The ID of the room we will be receiving * @param {string=} params.roomId The ID of the room we will be receiving
* from. Null for to-device events. * from. Null for to-device events.
*/ */
export class DecryptionAlgorithm { export abstract class DecryptionAlgorithm {
constructor(params) { private readonly userId: string;
this._userId = params.userId; private readonly crypto: Crypto;
this._crypto = params.crypto; private readonly olmDevice: OlmDevice;
this._olmDevice = params.olmDevice; private readonly baseApis: MatrixClient;
this._baseApis = params.baseApis; private readonly roomId: string;
this._roomId = params.roomId;
constructor(params: Omit<IParams, "deviceId">) {
this.userId = params.userId;
this.crypto = params.crypto;
this.olmDevice = params.olmDevice;
this.baseApis = params.baseApis;
this.roomId = params.roomId;
} }
/** /**
@@ -127,6 +166,7 @@ export class DecryptionAlgorithm {
* resolves once we have finished decrypting. Rejects with an * resolves once we have finished decrypting. Rejects with an
* `algorithms.DecryptionError` if there is a problem decrypting the event. * `algorithms.DecryptionError` if there is a problem decrypting the event.
*/ */
public abstract decryptEvent(event: MatrixEvent): Promise<IEventDecryptionResult>;
/** /**
* Handle a key event * Handle a key event
@@ -135,7 +175,7 @@ export class DecryptionAlgorithm {
* *
* @param {module:models/event.MatrixEvent} params event key event * @param {module:models/event.MatrixEvent} params event key event
*/ */
onRoomKeyEvent(params) { public onRoomKeyEvent(params: MatrixEvent): void {
// ignore by default // ignore by default
} }
@@ -143,8 +183,9 @@ export class DecryptionAlgorithm {
* Import a room key * Import a room key
* *
* @param {module:crypto/OlmDevice.MegolmSessionData} session * @param {module:crypto/OlmDevice.MegolmSessionData} session
* @param {object} opts object
*/ */
importRoomKey(session) { public async importRoomKey(session: IMegolmSessionData, opts: object): Promise<void> {
// ignore by default // ignore by default
} }
@@ -155,7 +196,7 @@ export class DecryptionAlgorithm {
* @return {Promise<boolean>} true if we have the keys and could (theoretically) share * @return {Promise<boolean>} true if we have the keys and could (theoretically) share
* them; else false. * them; else false.
*/ */
hasKeysForKeyRequest(keyRequest) { public hasKeysForKeyRequest(keyRequest: IncomingRoomKeyRequest): Promise<boolean> {
return Promise.resolve(false); return Promise.resolve(false);
} }
@@ -164,7 +205,7 @@ export class DecryptionAlgorithm {
* *
* @param {module:crypto~IncomingRoomKeyRequest} keyRequest * @param {module:crypto~IncomingRoomKeyRequest} keyRequest
*/ */
shareKeysWithDevice(keyRequest) { public shareKeysWithDevice(keyRequest: IncomingRoomKeyRequest) {
throw new Error("shareKeysWithDevice not supported for this DecryptionAlgorithm"); throw new Error("shareKeysWithDevice not supported for this DecryptionAlgorithm");
} }
@@ -174,9 +215,12 @@ export class DecryptionAlgorithm {
* *
* @param {string} senderKey the sender's key * @param {string} senderKey the sender's key
*/ */
async retryDecryptionFromSender(senderKey) { public async retryDecryptionFromSender(senderKey: string): Promise<void> {
// ignore by default // ignore by default
} }
public onRoomKeyWithheldEvent?: (event: MatrixEvent) => Promise<void>;
public sendSharedHistoryInboundSessions?: (devicesByUser: Record<string, DeviceInfo[]>) => Promise<void>;
} }
/** /**
@@ -191,22 +235,21 @@ export class DecryptionAlgorithm {
* @extends Error * @extends Error
*/ */
export class DecryptionError extends Error { export class DecryptionError extends Error {
constructor(code, msg, details) { public readonly detailedString: string;
constructor(public readonly code: string, msg: string, details: Record<string, string>) {
super(msg); super(msg);
this.code = code; this.code = code;
this.name = 'DecryptionError'; this.name = 'DecryptionError';
this.detailedString = _detailedStringForDecryptionError(this, details); this.detailedString = detailedStringForDecryptionError(this, details);
} }
} }
function _detailedStringForDecryptionError(err, details) { function detailedStringForDecryptionError(err: DecryptionError, details: Record<string, string>): string {
let result = err.name + '[msg: ' + err.message; let result = err.name + '[msg: ' + err.message;
if (details) { if (details) {
result += ', ' + result += ', ' + Object.keys(details).map((k) => k + ': ' + details[k]).join(', ');
Object.keys(details).map(
(k) => k + ': ' + details[k],
).join(', ');
} }
result += ']'; result += ']';
@@ -224,7 +267,7 @@ function _detailedStringForDecryptionError(err, details) {
* @extends Error * @extends Error
*/ */
export class UnknownDeviceError extends Error { export class UnknownDeviceError extends Error {
constructor(msg, devices) { constructor(msg: string, public readonly devices: Record<string, Record<string, object>>) {
super(msg); super(msg);
this.name = "UnknownDeviceError"; this.name = "UnknownDeviceError";
this.devices = devices; this.devices = devices;
@@ -244,7 +287,11 @@ export class UnknownDeviceError extends Error {
* module:crypto/algorithms/base.DecryptionAlgorithm|DecryptionAlgorithm} * module:crypto/algorithms/base.DecryptionAlgorithm|DecryptionAlgorithm}
* implementation * implementation
*/ */
export function registerAlgorithm(algorithm, encryptor, decryptor) { export function registerAlgorithm(
algorithm: string,
encryptor: EncryptionAlgorithm,
decryptor: DecryptionAlgorithm,
): void {
ENCRYPTION_CLASSES[algorithm] = encryptor; ENCRYPTION_CLASSES[algorithm] = encryptor;
DECRYPTION_CLASSES[algorithm] = decryptor; DECRYPTION_CLASSES[algorithm] = decryptor;
} }

View File

@@ -117,13 +117,14 @@ export interface IRoomKeyRequestBody extends IRoomKey {
sender_key: string sender_key: string
} }
interface IMegolmSessionData { export interface IMegolmSessionData {
sender_key: string; sender_key: string;
forwarding_curve25519_key_chain: string[]; forwarding_curve25519_key_chain: string[];
sender_claimed_keys: Record<string, string>; sender_claimed_keys: Record<string, string>;
room_id: string; room_id: string;
session_id: string; session_id: string;
session_key: string; session_key: string;
algorithm: string;
} }
/* eslint-enable camelcase */ /* eslint-enable camelcase */
@@ -168,7 +169,7 @@ interface ISignableObject {
unsigned?: object unsigned?: object
} }
interface IEventDecryptionResult { export interface IEventDecryptionResult {
clearEvent: object; clearEvent: object;
senderCurve25519Key?: string; senderCurve25519Key?: string;
claimedEd25519Key?: string; claimedEd25519Key?: string;
@@ -193,7 +194,7 @@ export class Crypto extends EventEmitter {
private readonly reEmitter: ReEmitter; private readonly reEmitter: ReEmitter;
private readonly verificationMethods: any; // TODO types private readonly verificationMethods: any; // TODO types
private readonly supportedAlgorithms: DecryptionAlgorithm[]; private readonly supportedAlgorithms: string[];
private readonly outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager; private readonly outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager;
private readonly toDeviceVerificationRequests: ToDeviceRequests; private readonly toDeviceVerificationRequests: ToDeviceRequests;
private readonly inRoomVerificationRequests: InRoomRequests; private readonly inRoomVerificationRequests: InRoomRequests;
@@ -2630,7 +2631,7 @@ export class Crypto extends EventEmitter {
* @param {Function} opts.progressCallback called with an object which has a stage param * @param {Function} opts.progressCallback called with an object which has a stage param
* @return {Promise} a promise which resolves once the keys have been imported * @return {Promise} a promise which resolves once the keys have been imported
*/ */
public importRoomKeys(keys: IRoomKey[], opts: any = {}): Promise<any> { // TODO types public importRoomKeys(keys: IMegolmSessionData[], opts: any = {}): Promise<any> { // TODO types
let successes = 0; let successes = 0;
let failures = 0; let failures = 0;
const total = keys.length; const total = keys.length;
@@ -3430,9 +3431,7 @@ export class Crypto extends EventEmitter {
} }
try { try {
await encryptor.reshareKeyWithDevice( await encryptor.reshareKeyWithDevice(body.sender_key, body.session_id, userId, device);
body.sender_key, body.session_id, userId, device,
);
} catch (e) { } catch (e) {
logger.warn( logger.warn(
"Failed to re-share keys for session " + body.session_id + "Failed to re-share keys for session " + body.session_id +
@@ -3643,7 +3642,7 @@ export function fixBackupKey(key: string): string | null {
* the relevant crypto algorithm implementation to share the keys for * the relevant crypto algorithm implementation to share the keys for
* this request. * this request.
*/ */
class IncomingRoomKeyRequest { export class IncomingRoomKeyRequest {
public readonly userId: string; public readonly userId: string;
public readonly deviceId: string; public readonly deviceId: string;
public readonly requestId: string; public readonly requestId: string;