diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 0750a66af76..af553790418 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -14,10 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import fetchMock from "fetch-mock-jest"; -import { MockResponse } from "fetch-mock"; import "fake-indexeddb/auto"; +import { MockResponse } from "fetch-mock"; +import fetchMock from "fetch-mock-jest"; +import { IDBFactory } from "fake-indexeddb"; + import { createClient, CryptoEvent, MatrixClient } from "../../../src"; import { canAcceptVerificationRequest, @@ -67,6 +69,13 @@ beforeAll(async () => { await global.Olm.init(); }); +afterEach(() => { + // reset fake-indexeddb after each test, to make sure we don't leak connections + // cf https://github.com/dumbmatter/fakeIndexedDB#wipingresetting-the-indexeddb-for-a-fresh-state + // eslint-disable-next-line no-global-assign + indexedDB = new IDBFactory(); +}); + // restore the original global.crypto afterAll(() => { if (previousCrypto === undefined) { @@ -317,6 +326,35 @@ function runTests(backend: string, initCrypto: InitCrypto, methods: string[] | u olmSAS.free(); }); + it("Can make a verification request to *all* devices", async () => { + // we need an existing cross-signing key for this + e2eKeyResponder.addCrossSigningData(SIGNED_CROSS_SIGNING_KEYS_DATA); + await waitForDeviceList(); + + // 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.getCrypto()!.requestOwnUserVerification(), + ]); + + const transactionId = request.transactionId; + expect(transactionId).toBeDefined(); + expect(request.phase).toEqual(VerificationPhase.Requested); + + // and now the request should be visible via `getVerificationRequestsToDeviceInProgress` + { + const requests = aliceClient.getCrypto()!.getVerificationRequestsToDeviceInProgress(TEST_USER_ID); + expect(requests.length).toEqual(1); + expect(requests[0].transactionId).toEqual(transactionId); + } + + // legacy crypto picks devices individually; rust crypto uses a broadcast message + const toDeviceMessage = + requestBody.messages[TEST_USER_ID]["*"] ?? requestBody.messages[TEST_USER_ID][TEST_DEVICE_ID]; + expect(toDeviceMessage.from_device).toEqual(aliceClient.deviceId); + expect(toDeviceMessage.transaction_id).toEqual(transactionId); + }); + oldBackendOnly("can verify another via QR code with an untrusted cross-signing key", async () => { // QRCode fails if we don't yet have the cross-signing keys, so make sure we have them now. e2eKeyResponder.addCrossSigningData(SIGNED_CROSS_SIGNING_KEYS_DATA); diff --git a/src/rust-crypto/rust-crypto.ts b/src/rust-crypto/rust-crypto.ts index 2807b782c55..aa73a4c4b55 100644 --- a/src/rust-crypto/rust-crypto.ts +++ b/src/rust-crypto/rust-crypto.ts @@ -584,7 +584,19 @@ export class RustCrypto implements CryptoBackend { * @returns a VerificationRequest when the request has been sent to the other party. */ public async requestOwnUserVerification(): Promise { - throw new Error("not implemented"); + const userIdentity: RustSdkCryptoJs.OwnUserIdentity | undefined = await this.olmMachine.getIdentity( + new RustSdkCryptoJs.UserId(this.userId), + ); + if (userIdentity === undefined) { + throw new Error("cannot request verification for this device when there is no existing cross-signing key"); + } + + const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] = + await userIdentity.requestVerification( + this.supportedVerificationMethods?.map(verificationMethodIdentifierToMethod), + ); + await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest); + return new RustVerificationRequest(request, this.outgoingRequestProcessor); } /**