You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-25 05:23:13 +03:00
Pull out a public CryptoApi (#3211)
... so that we don't have to implement annoying shims in `MatrixClient`
This commit is contained in:
committed by
GitHub
parent
913cd257f4
commit
333872e878
@@ -536,6 +536,10 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
fetchMock.mockReset();
|
||||
});
|
||||
|
||||
it("MatrixClient.getCrypto returns a CryptoApi", () => {
|
||||
expect(aliceClient.getCrypto()).toHaveProperty("globalBlacklistUnverifiedDevices");
|
||||
});
|
||||
|
||||
it("Alice receives a megolm message", async () => {
|
||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
@@ -206,6 +206,7 @@ import { LocalNotificationSettings } from "./@types/local_notifications";
|
||||
import { buildFeatureSupportMap, Feature, ServerSupport } from "./feature";
|
||||
import { CryptoBackend } from "./common-crypto/CryptoBackend";
|
||||
import { RUST_SDK_STORE_PREFIX } from "./rust-crypto/constants";
|
||||
import { CryptoApi } from "./crypto-api";
|
||||
|
||||
export type Store = IStore;
|
||||
|
||||
@@ -1166,7 +1167,15 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
public urlPreviewCache: { [key: string]: Promise<IPreviewUrlResponse> } = {};
|
||||
public identityServer?: IIdentityServerProvider;
|
||||
public http: MatrixHttpApi<IHttpOpts & { onlyData: true }>; // XXX: Intended private, used in code.
|
||||
public crypto?: Crypto; // libolm crypto implementation. XXX: Intended private, used in code. Being replaced by cryptoBackend
|
||||
|
||||
/**
|
||||
* The libolm crypto implementation, if it is in use.
|
||||
*
|
||||
* @deprecated This should not be used. Instead, use the methods exposed directly on this class or
|
||||
* (where they are available) via {@link getCrypto}.
|
||||
*/
|
||||
public crypto?: Crypto; // XXX: Intended private, used in code. Being replaced by cryptoBackend
|
||||
|
||||
private cryptoBackend?: CryptoBackend; // one of crypto or rustCrypto
|
||||
public cryptoCallbacks: ICryptoCallbacks; // XXX: Intended private, used in code.
|
||||
public callEventHandler?: CallEventHandler; // XXX: Intended private, used in code.
|
||||
@@ -2200,9 +2209,20 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
this.on(RoomMemberEvent.Membership, rustCrypto.onRoomMembership.bind(rustCrypto));
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the crypto API for this client.
|
||||
*
|
||||
* If end-to-end encryption has been enabled for this client (via {@link initCrypto} or {@link initRustCrypto}),
|
||||
* returns an object giving access to the crypto API. Otherwise, returns `undefined`.
|
||||
*/
|
||||
public getCrypto(): CryptoApi | undefined {
|
||||
return this.cryptoBackend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is end-to-end crypto enabled for this client.
|
||||
* @returns True if end-to-end is enabled.
|
||||
* @deprecated prefer {@link getCrypto}
|
||||
*/
|
||||
public isCryptoEnabled(): boolean {
|
||||
return !!this.cryptoBackend;
|
||||
@@ -2448,6 +2468,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
* do not specify a value.
|
||||
*
|
||||
* @param value - whether to blacklist all unverified devices by default
|
||||
*
|
||||
* @deprecated Prefer direct access to {@link CryptoApi.globalBlacklistUnverifiedDevices}:
|
||||
*
|
||||
* ```javascript
|
||||
* client.getCrypto().globalBlacklistUnverifiedDevices = value;
|
||||
* ```
|
||||
*/
|
||||
public setGlobalBlacklistUnverifiedDevices(value: boolean): boolean {
|
||||
if (!this.cryptoBackend) {
|
||||
@@ -2459,6 +2485,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
|
||||
/**
|
||||
* @returns whether to blacklist all unverified devices by default
|
||||
*
|
||||
* @deprecated Prefer direct access to {@link CryptoApi.globalBlacklistUnverifiedDevices}:
|
||||
*
|
||||
* ```javascript
|
||||
* value = client.getCrypto().globalBlacklistUnverifiedDevices;
|
||||
* ```
|
||||
*/
|
||||
public getGlobalBlacklistUnverifiedDevices(): boolean {
|
||||
if (!this.cryptoBackend) {
|
||||
@@ -2476,6 +2508,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
* This API is currently UNSTABLE and may change or be removed without notice.
|
||||
*
|
||||
* @param value - whether error on unknown devices
|
||||
*
|
||||
* @deprecated Prefer direct access to {@link CryptoApi.globalBlacklistUnverifiedDevices}:
|
||||
*
|
||||
* ```ts
|
||||
* client.getCrypto().globalBlacklistUnverifiedDevices = value;
|
||||
* ```
|
||||
*/
|
||||
public setGlobalErrorOnUnknownDevices(value: boolean): void {
|
||||
if (!this.cryptoBackend) {
|
||||
@@ -2535,8 +2573,6 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
* The cross-signing API is currently UNSTABLE and may change without notice.
|
||||
*
|
||||
* @param userId - The ID of the user to check.
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
public checkUserTrust(userId: string): UserTrustLevel {
|
||||
if (!this.cryptoBackend) {
|
||||
@@ -2618,6 +2654,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
* Perform any background tasks that can be done before a message is ready to
|
||||
* send, in order to speed up sending of the message.
|
||||
* @param room - the room the event is in
|
||||
*
|
||||
* @deprecated Prefer {@link CryptoApi.prepareToEncrypt | `CryptoApi.prepareToEncrypt`}:
|
||||
*
|
||||
* ```javascript
|
||||
* client.getCrypto().prepareToEncrypt(room);
|
||||
* ```
|
||||
*/
|
||||
public prepareToEncrypt(room: Room): void {
|
||||
if (!this.cryptoBackend) {
|
||||
@@ -2631,6 +2673,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
*
|
||||
* This means downloading the devicelist for the user and checking if the list includes
|
||||
* the cross-signing pseudo-device.
|
||||
*
|
||||
* @deprecated Prefer {@link CryptoApi.userHasCrossSigningKeys | `CryptoApi.userHasCrossSigningKeys`}:
|
||||
*
|
||||
* ```javascript
|
||||
* result = client.getCrypto().userHasCrossSigningKeys();
|
||||
* ```
|
||||
*/
|
||||
public userHasCrossSigningKeys(): Promise<boolean> {
|
||||
if (!this.cryptoBackend) {
|
||||
@@ -3088,8 +3136,13 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
*
|
||||
* This should be encrypted before returning it to the user.
|
||||
*
|
||||
* @returns a promise which resolves to a list of
|
||||
* session export objects
|
||||
* @returns a promise which resolves to a list of session export objects
|
||||
*
|
||||
* @deprecated Prefer {@link CryptoApi.exportRoomKeys | `CryptoApi.exportRoomKeys`}:
|
||||
*
|
||||
* ```javascript
|
||||
* sessionData = await client.getCrypto().exportRoomKeys();
|
||||
* ```
|
||||
*/
|
||||
public exportRoomKeys(): Promise<IMegolmSessionData[]> {
|
||||
if (!this.cryptoBackend) {
|
||||
|
||||
@@ -14,31 +14,26 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto";
|
||||
import type { IToDeviceEvent } from "../sync-accumulator";
|
||||
import type { DeviceTrustLevel, UserTrustLevel } from "../crypto/CrossSigning";
|
||||
import { MatrixEvent } from "../models/event";
|
||||
import { Room } from "../models/room";
|
||||
import { CryptoApi } from "../crypto-api";
|
||||
import { DeviceTrustLevel, UserTrustLevel } from "../crypto/CrossSigning";
|
||||
import { IEncryptedEventInfo } from "../crypto/api";
|
||||
import { IEventDecryptionResult } from "../@types/crypto";
|
||||
|
||||
/**
|
||||
* Common interface for the crypto implementations
|
||||
*/
|
||||
export interface CryptoBackend extends SyncCryptoCallbacks {
|
||||
/**
|
||||
* Global override for whether the client should ever send encrypted
|
||||
* messages to unverified devices. This provides the default for rooms which
|
||||
* do not specify a value.
|
||||
*
|
||||
* If true, all unverified devices will be blacklisted by default
|
||||
*/
|
||||
globalBlacklistUnverifiedDevices: boolean;
|
||||
|
||||
export interface CryptoBackend extends SyncCryptoCallbacks, CryptoApi {
|
||||
/**
|
||||
* Whether sendMessage in a room with unknown and unverified devices
|
||||
* should throw an error and not send the message. This has 'Global' for
|
||||
* symmetry with setGlobalBlacklistUnverifiedDevices but there is currently
|
||||
* no room-level equivalent for this setting.
|
||||
*
|
||||
* @remarks this is here, rather than in `CryptoApi`, because I don't think we're
|
||||
* going to support it in the rust crypto implementation.
|
||||
*/
|
||||
globalErrorOnUnknownDevices: boolean;
|
||||
|
||||
@@ -47,16 +42,6 @@ export interface CryptoBackend extends SyncCryptoCallbacks {
|
||||
*/
|
||||
stop(): void;
|
||||
|
||||
/**
|
||||
* Checks if the user has previously published cross-signing keys
|
||||
*
|
||||
* This means downloading the devicelist for the user and checking if the list includes
|
||||
* the cross-signing pseudo-device.
|
||||
|
||||
* @returns true if the user has previously published cross-signing keys
|
||||
*/
|
||||
userHasCrossSigningKeys(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Get the verification level for a given user
|
||||
*
|
||||
@@ -76,14 +61,6 @@ export interface CryptoBackend extends SyncCryptoCallbacks {
|
||||
*/
|
||||
checkDeviceTrust(userId: string, deviceId: string): DeviceTrustLevel;
|
||||
|
||||
/**
|
||||
* Perform any background tasks that can be done before a message is ready to
|
||||
* send, in order to speed up sending of the message.
|
||||
*
|
||||
* @param room - the room the event is in
|
||||
*/
|
||||
prepareToEncrypt(room: Room): void;
|
||||
|
||||
/**
|
||||
* Encrypt an event according to the configuration of the room.
|
||||
*
|
||||
@@ -110,16 +87,6 @@ export interface CryptoBackend extends SyncCryptoCallbacks {
|
||||
* @param event - event to be checked
|
||||
*/
|
||||
getEventEncryptionInfo(event: MatrixEvent): IEncryptedEventInfo;
|
||||
|
||||
/**
|
||||
* Get a list containing all of the room keys
|
||||
*
|
||||
* This should be encrypted before returning it to the user.
|
||||
*
|
||||
* @returns a promise which resolves to a list of
|
||||
* session export objects
|
||||
*/
|
||||
exportRoomKeys(): Promise<IMegolmSessionData[]>;
|
||||
}
|
||||
|
||||
/** The methods which crypto implementations should expose to the Sync api */
|
||||
|
||||
62
src/crypto-api.ts
Normal file
62
src/crypto-api.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2023 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.
|
||||
*/
|
||||
|
||||
import type { IMegolmSessionData } from "./@types/crypto";
|
||||
import { Room } from "./models/room";
|
||||
|
||||
/**
|
||||
* Public interface to the cryptography parts of the js-sdk
|
||||
*
|
||||
* @remarks Currently, this is a work-in-progress. In time, more methods will be added here.
|
||||
*/
|
||||
export interface CryptoApi {
|
||||
/**
|
||||
* Global override for whether the client should ever send encrypted
|
||||
* messages to unverified devices. This provides the default for rooms which
|
||||
* do not specify a value.
|
||||
*
|
||||
* If true, all unverified devices will be blacklisted by default
|
||||
*/
|
||||
globalBlacklistUnverifiedDevices: boolean;
|
||||
|
||||
/**
|
||||
* Checks if the user has previously published cross-signing keys
|
||||
*
|
||||
* This means downloading the devicelist for the user and checking if the list includes
|
||||
* the cross-signing pseudo-device.
|
||||
*
|
||||
* @returns true if the user has previously published cross-signing keys
|
||||
*/
|
||||
userHasCrossSigningKeys(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Perform any background tasks that can be done before a message is ready to
|
||||
* send, in order to speed up sending of the message.
|
||||
*
|
||||
* @param room - the room the event is in
|
||||
*/
|
||||
prepareToEncrypt(room: Room): void;
|
||||
|
||||
/**
|
||||
* Get a list containing all of the room keys
|
||||
*
|
||||
* This should be encrypted before returning it to the user.
|
||||
*
|
||||
* @returns a promise which resolves to a list of
|
||||
* session export objects
|
||||
*/
|
||||
exportRoomKeys(): Promise<IMegolmSessionData[]>;
|
||||
}
|
||||
@@ -60,6 +60,7 @@ export { createNewMatrixCall } from "./webrtc/call";
|
||||
export type { MatrixCall } from "./webrtc/call";
|
||||
export { GroupCallEvent, GroupCallIntent, GroupCallState, GroupCallType } from "./webrtc/groupCall";
|
||||
export type { GroupCall } from "./webrtc/groupCall";
|
||||
export type { CryptoApi } from "./crypto-api";
|
||||
|
||||
let cryptoStoreFactory = (): CryptoStore => new MemoryCryptoStore();
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ export async function initRustCrypto(
|
||||
await RustSdkCryptoJs.initAsync();
|
||||
|
||||
// enable tracing in the rust-sdk
|
||||
new RustSdkCryptoJs.Tracing(RustSdkCryptoJs.LoggerLevel.Debug).turnOn();
|
||||
new RustSdkCryptoJs.Tracing(RustSdkCryptoJs.LoggerLevel.Trace).turnOn();
|
||||
|
||||
const u = new RustSdkCryptoJs.UserId(userId);
|
||||
const d = new RustSdkCryptoJs.DeviceId(deviceId);
|
||||
|
||||
@@ -34,7 +34,6 @@ import { KeyClaimManager } from "./KeyClaimManager";
|
||||
* An implementation of {@link CryptoBackend} using the Rust matrix-sdk-crypto.
|
||||
*/
|
||||
export class RustCrypto implements CryptoBackend {
|
||||
public globalBlacklistUnverifiedDevices = false;
|
||||
public globalErrorOnUnknownDevices = false;
|
||||
|
||||
/** whether {@link stop} has been called */
|
||||
@@ -81,14 +80,6 @@ export class RustCrypto implements CryptoBackend {
|
||||
this.olmMachine.close();
|
||||
}
|
||||
|
||||
public prepareToEncrypt(room: Room): void {
|
||||
const encryptor = this.roomEncryptors[room.roomId];
|
||||
|
||||
if (encryptor) {
|
||||
encryptor.ensureEncryptionSession();
|
||||
}
|
||||
}
|
||||
|
||||
public async encryptEvent(event: MatrixEvent, _room: Room): Promise<void> {
|
||||
const roomId = event.getRoomId()!;
|
||||
const encryptor = this.roomEncryptors[roomId];
|
||||
@@ -147,16 +138,6 @@ export class RustCrypto implements CryptoBackend {
|
||||
return ret as IEncryptedEventInfo;
|
||||
}
|
||||
|
||||
public async userHasCrossSigningKeys(): Promise<boolean> {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
public async exportRoomKeys(): Promise<IMegolmSessionData[]> {
|
||||
// TODO
|
||||
return [];
|
||||
}
|
||||
|
||||
public checkUserTrust(userId: string): UserTrustLevel {
|
||||
// TODO
|
||||
return new UserTrustLevel(false, false, false);
|
||||
@@ -167,6 +148,32 @@ export class RustCrypto implements CryptoBackend {
|
||||
return new DeviceTrustLevel(false, false, false, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CryptoApi implementation
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public globalBlacklistUnverifiedDevices = false;
|
||||
|
||||
public async userHasCrossSigningKeys(): Promise<boolean> {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
public prepareToEncrypt(room: Room): void {
|
||||
const encryptor = this.roomEncryptors[room.roomId];
|
||||
|
||||
if (encryptor) {
|
||||
encryptor.ensureEncryptionSession();
|
||||
}
|
||||
}
|
||||
|
||||
public async exportRoomKeys(): Promise<IMegolmSessionData[]> {
|
||||
// TODO
|
||||
return [];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SyncCryptoCallbacks implementation
|
||||
|
||||
Reference in New Issue
Block a user