From 143b6c6fdb336256592a9e7fce176e638d8d213e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 14 Jun 2023 16:12:41 +0100 Subject: [PATCH 1/3] Avoid deprecated classes in verification integ test https://github.com/matrix-org/matrix-js-sdk/pull/3449 deprecated a bunch of exports from `src/crypto/verification/request/VerificationRequest`. Let's stop using them in the integration test. --- spec/integ/crypto/verification.spec.ts | 40 ++++++++++++++------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 2f366558723..0ceac47246d 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -18,7 +18,16 @@ import fetchMock from "fetch-mock-jest"; import { MockResponse } from "fetch-mock"; import { createClient, CryptoEvent, MatrixClient } from "../../../src"; -import { ShowQrCodeCallbacks, ShowSasCallbacks, Verifier, VerifierEvent } from "../../../src/crypto-api/verification"; +import { + ShowQrCodeCallbacks, + ShowSasCallbacks, + Verifier, + VerifierEvent, + VerificationPhase, + VerificationRequest, + VerificationRequestEvent, + canAcceptVerificationRequest, +} from "../../../src/crypto-api/verification"; import { escapeRegExp } from "../../../src/utils"; import { CRYPTO_BACKENDS, emitPromise, InitCrypto } from "../../test-utils/test-utils"; import { SyncResponder } from "../../test-utils/SyncResponder"; @@ -31,11 +40,6 @@ import { TEST_USER_ID, } from "../../test-utils/test-data"; import { mockInitialApiRequests } from "../../test-utils/mockEndpoints"; -import { - Phase, - VerificationRequest, - VerificationRequestEvent, -} from "../../../src/crypto/verification/request/VerificationRequest"; // The verification flows use javascript timers to set timeouts. We tell jest to use mock timer implementations // to ensure that we don't end up with dangling timeouts. @@ -130,7 +134,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st ]); const transactionId = request.transactionId; expect(transactionId).toBeDefined(); - expect(request.phase).toEqual(Phase.Requested); + expect(request.phase).toEqual(VerificationPhase.Requested); expect(request.roomId).toBeUndefined(); let toDeviceMessage = requestBody.messages[TEST_USER_ID][TEST_DEVICE_ID]; @@ -148,7 +152,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st }, }); await waitForVerificationRequestChanged(request); - expect(request.phase).toEqual(Phase.Ready); + expect(request.phase).toEqual(VerificationPhase.Ready); expect(request.otherDeviceId).toEqual(TEST_DEVICE_ID); // ... and picks a method with m.key.verification.start @@ -165,7 +169,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st }, }); await waitForVerificationRequestChanged(request); - expect(request.phase).toEqual(Phase.Started); + expect(request.phase).toEqual(VerificationPhase.Started); expect(request.chosenMethod).toEqual("m.sas.v1"); // there should now be a verifier @@ -238,7 +242,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // ... and the whole thing should be done! await verificationPromise; - expect(request.phase).toEqual(Phase.Done); + expect(request.phase).toEqual(VerificationPhase.Done); // we're done with the temporary keypair olmSAS.free(); @@ -290,7 +294,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st }, }); await waitForVerificationRequestChanged(request); - expect(request.phase).toEqual(Phase.Ready); + expect(request.phase).toEqual(VerificationPhase.Ready); // we should now have QR data we can display const qrCodeBuffer = request.getQRCodeBytes()!; @@ -320,7 +324,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st }, }); await waitForVerificationRequestChanged(request); - expect(request.phase).toEqual(Phase.Started); + expect(request.phase).toEqual(VerificationPhase.Started); expect(request.chosenMethod).toEqual("m.reciprocate.v1"); // there should now be a verifier @@ -346,7 +350,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // ... and the whole thing should be done! await verificationPromise; - expect(request.phase).toEqual(Phase.Done); + expect(request.phase).toEqual(VerificationPhase.Done); }, ); @@ -374,18 +378,18 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st }); const request: VerificationRequest = await emitPromise(aliceClient, CryptoEvent.VerificationRequest); expect(request.transactionId).toEqual(TRANSACTION_ID); - expect(request.phase).toEqual(Phase.Requested); + expect(request.phase).toEqual(VerificationPhase.Requested); expect(request.roomId).toBeUndefined(); - expect(request.canAccept).toBe(true); + expect(canAcceptVerificationRequest(request)).toBe(true); // Alice accepts, by sending a to-device message const sendToDevicePromise = expectSendToDeviceMessage("m.key.verification.ready"); const acceptPromise = request.accept(); - expect(request.canAccept).toBe(false); - expect(request.phase).toEqual(Phase.Requested); + expect(canAcceptVerificationRequest(request)).toBe(false); + expect(request.phase).toEqual(VerificationPhase.Requested); await acceptPromise; const requestBody = await sendToDevicePromise; - expect(request.phase).toEqual(Phase.Ready); + expect(request.phase).toEqual(VerificationPhase.Ready); const toDeviceMessage = requestBody.messages[TEST_USER_ID][TEST_DEVICE_ID]; expect(toDeviceMessage.methods).toContain("m.sas.v1"); From 1a78e860480b0e65b58aa096a4006b85b31efc79 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 6 Jun 2023 17:29:59 +0100 Subject: [PATCH 2/3] Add accessors for verification requests to CryptoApi Part of https://github.com/vector-im/crypto-internal/issues/97 --- src/client.ts | 8 +++++- src/common-crypto/CryptoBackend.ts | 10 ------- src/crypto-api.ts | 25 +++++++++++++++++ src/rust-crypto/rust-crypto.ts | 44 +++++++++++++++++++++--------- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/client.ts b/src/client.ts index bf7b5adfcc5..36740fa74bb 100644 --- a/src/client.ts +++ b/src/client.ts @@ -2431,12 +2431,17 @@ export class MatrixClient extends TypedEventEmitter; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Device/User verification + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Returns to-device verification requests that are already in progress for the given user id. + * + * @param userId - the ID of the user to query + * + * @returns the VerificationRequests that are in progress + */ + getVerificationRequestsToDeviceInProgress(userId: string): VerificationRequest[]; + + /** + * Finds a DM verification request that is already in progress for the given room id + * + * @param roomId - the room to use for verification + * + * @returns the VerificationRequest that is in progress, if any + */ + findVerificationRequestDMInProgress(roomId: string): VerificationRequest | undefined; } /** diff --git a/src/rust-crypto/rust-crypto.ts b/src/rust-crypto/rust-crypto.ts index 598c4b00073..78c1ed929f3 100644 --- a/src/rust-crypto/rust-crypto.ts +++ b/src/rust-crypto/rust-crypto.ts @@ -32,12 +32,13 @@ import { KeyClaimManager } from "./KeyClaimManager"; import { MapWithDefault } from "../utils"; import { BootstrapCrossSigningOpts, + CrossSigningKey, CrossSigningStatus, DeviceVerificationStatus, GeneratedSecretStorageKey, ImportRoomKeyProgressData, ImportRoomKeysOpts, - CrossSigningKey, + VerificationRequest, } from "../crypto-api"; import { deviceKeysToDeviceMap, rustDeviceToJsDevice } from "./device-converter"; import { IDownloadKeyResult, IQueryKeysRequest } from "../client"; @@ -165,18 +166,6 @@ export class RustCrypto implements CryptoBackend { return new UserTrustLevel(false, false, false); } - /** - * Finds a DM verification request that is already in progress for the given room id - * - * @param roomId - the room to use for verification - * - * @returns the VerificationRequest that is in progress, if any - */ - public findVerificationRequestDMInProgress(roomId: string): undefined { - // TODO - return; - } - /** * Get the cross signing information for a given user. * @@ -439,6 +428,35 @@ export class RustCrypto implements CryptoBackend { }; } + /** + * Returns to-device verification requests that are already in progress for the given user id. + * + * Implementation of {@link CryptoApi#getVerificationRequestsToDeviceInProgress} + * + * @param userId - the ID of the user to query + * + * @returns the VerificationRequests that are in progress + */ + public getVerificationRequestsToDeviceInProgress(userId: string): VerificationRequest[] { + // TODO + return []; + } + + /** + * Finds a DM verification request that is already in progress for the given room id + * + * Implementation of {@link CryptoApi#findVerificationRequestDMInProgress} + * + * @param roomId - the room to use for verification + * + * @returns the VerificationRequest that is in progress, if any + * + */ + public findVerificationRequestDMInProgress(roomId: string): undefined { + // TODO + return; + } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SyncCryptoCallbacks implementation From 8e680be9e968bff3359f0b0fb7a8a1a9b6dae515 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 7 Jun 2023 14:19:20 +0100 Subject: [PATCH 3/3] Add new methods for verification to `CryptoApi` and deprecate old method https://github.com/vector-im/crypto-internal/issues/98 --- spec/integ/crypto/verification.spec.ts | 10 ++++----- src/client.ts | 2 ++ src/crypto-api.ts | 21 +++++++++++++++++++ src/crypto/index.ts | 9 ++++++++ src/rust-crypto/rust-crypto.ts | 29 ++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 0ceac47246d..b5f500f5887 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -19,14 +19,14 @@ import { MockResponse } from "fetch-mock"; import { createClient, CryptoEvent, MatrixClient } from "../../../src"; import { + canAcceptVerificationRequest, ShowQrCodeCallbacks, ShowSasCallbacks, - Verifier, - VerifierEvent, VerificationPhase, VerificationRequest, VerificationRequestEvent, - canAcceptVerificationRequest, + Verifier, + VerifierEvent, } from "../../../src/crypto-api/verification"; import { escapeRegExp } from "../../../src/utils"; import { CRYPTO_BACKENDS, emitPromise, InitCrypto } from "../../test-utils/test-utils"; @@ -130,7 +130,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // have alice initiate a verification. She should send a m.key.verification.request let [requestBody, request] = await Promise.all([ expectSendToDeviceMessage("m.key.verification.request"), - aliceClient.requestVerification(TEST_USER_ID, [TEST_DEVICE_ID]), + aliceClient.getCrypto()!.requestDeviceVerification(TEST_USER_ID, TEST_DEVICE_ID), ]); const transactionId = request.transactionId; expect(transactionId).toBeDefined(); @@ -273,7 +273,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // have alice initiate a verification. She should send a m.key.verification.request const [requestBody, request] = await Promise.all([ expectSendToDeviceMessage("m.key.verification.request"), - aliceClient.requestVerification(TEST_USER_ID, [TEST_DEVICE_ID]), + aliceClient.getCrypto()!.requestDeviceVerification(TEST_USER_ID, TEST_DEVICE_ID), ]); const transactionId = request.transactionId; diff --git a/src/client.ts b/src/client.ts index 36740fa74bb..d0d71266206 100644 --- a/src/client.ts +++ b/src/client.ts @@ -2468,6 +2468,8 @@ export class MatrixClient extends TypedEventEmitter { if (!this.crypto) { diff --git a/src/crypto-api.ts b/src/crypto-api.ts index 2868980d53d..b91dde6bf1d 100644 --- a/src/crypto-api.ts +++ b/src/crypto-api.ts @@ -252,6 +252,27 @@ export interface CryptoApi { * @returns the VerificationRequest that is in progress, if any */ findVerificationRequestDMInProgress(roomId: string): VerificationRequest | undefined; + + /** + * Send a verification request to our other devices. + * + * If a verification is already in flight, returns it. Otherwise, initiates a new one. + * + * @returns a VerificationRequest when the request has been sent to the other party. + */ + requestOwnUserVerification(): Promise; + + /** + * Request an interactive verification with the given device. + * + * If a verification is already in flight, returns it. Otherwise, initiates a new one. + * + * @param userId - ID of the owner of the device to verify + * @param deviceId - ID of the device to verify + * + * @returns a VerificationRequest when the request has been sent to the other party. + */ + requestDeviceVerification(userId: string, deviceId: string): Promise; } /** diff --git a/src/crypto/index.ts b/src/crypto/index.ts index 16462d74445..d9ebd74a9ae 100644 --- a/src/crypto/index.ts +++ b/src/crypto/index.ts @@ -2356,6 +2356,7 @@ export class Crypto extends TypedEventEmitter { if (!devices) { devices = Object.keys(this.deviceList.getRawStoredDevicesForUser(userId)); @@ -2368,6 +2369,14 @@ export class Crypto extends TypedEventEmitter { + return this.requestVerification(this.userId); + } + + public requestDeviceVerification(userId: string, deviceId: string): Promise { + return this.requestVerification(userId, [deviceId]); + } + private async requestVerificationWithChannel( userId: string, channel: IVerificationChannel, diff --git a/src/rust-crypto/rust-crypto.ts b/src/rust-crypto/rust-crypto.ts index 78c1ed929f3..84a21c548d3 100644 --- a/src/rust-crypto/rust-crypto.ts +++ b/src/rust-crypto/rust-crypto.ts @@ -457,6 +457,35 @@ export class RustCrypto implements CryptoBackend { return; } + /** + * Send a verification request to our other devices. + * + * If a verification is already in flight, returns it. Otherwise, initiates a new one. + * + * Implementation of {@link CryptoApi#requestOwnUserVerification}. + * + * @returns a VerificationRequest when the request has been sent to the other party. + */ + public requestOwnUserVerification(): Promise { + throw new Error("not implemented"); + } + + /** + * Request an interactive verification with the given device. + * + * If a verification is already in flight, returns it. Otherwise, initiates a new one. + * + * Implementation of {@link CryptoApi#requestDeviceVerification }. + * + * @param userId - ID of the owner of the device to verify + * @param deviceId - ID of the device to verify + * + * @returns a VerificationRequest when the request has been sent to the other party. + */ + public requestDeviceVerification(userId: string, deviceId: string): Promise { + throw new Error("not implemented"); + } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // SyncCryptoCallbacks implementation