Skip to content

Commit bd66e38

Browse files
authored
Element R: Implement requestOwnUserVerification (#3508)
Part of element-hq/element-web#25319.
1 parent 96e484a commit bd66e38

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

spec/integ/crypto/verification.spec.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import fetchMock from "fetch-mock-jest";
18-
import { MockResponse } from "fetch-mock";
1917
import "fake-indexeddb/auto";
2018

19+
import { MockResponse } from "fetch-mock";
20+
import fetchMock from "fetch-mock-jest";
21+
import { IDBFactory } from "fake-indexeddb";
22+
2123
import { createClient, CryptoEvent, MatrixClient } from "../../../src";
2224
import {
2325
canAcceptVerificationRequest,
@@ -67,6 +69,13 @@ beforeAll(async () => {
6769
await global.Olm.init();
6870
});
6971

72+
afterEach(() => {
73+
// reset fake-indexeddb after each test, to make sure we don't leak connections
74+
// cf https://github.com/dumbmatter/fakeIndexedDB#wipingresetting-the-indexeddb-for-a-fresh-state
75+
// eslint-disable-next-line no-global-assign
76+
indexedDB = new IDBFactory();
77+
});
78+
7079
// restore the original global.crypto
7180
afterAll(() => {
7281
if (previousCrypto === undefined) {
@@ -317,6 +326,35 @@ function runTests(backend: string, initCrypto: InitCrypto, methods: string[] | u
317326
olmSAS.free();
318327
});
319328

329+
it("Can make a verification request to *all* devices", async () => {
330+
// we need an existing cross-signing key for this
331+
e2eKeyResponder.addCrossSigningData(SIGNED_CROSS_SIGNING_KEYS_DATA);
332+
await waitForDeviceList();
333+
334+
// have alice initiate a verification. She should send a m.key.verification.request
335+
const [requestBody, request] = await Promise.all([
336+
expectSendToDeviceMessage("m.key.verification.request"),
337+
aliceClient.getCrypto()!.requestOwnUserVerification(),
338+
]);
339+
340+
const transactionId = request.transactionId;
341+
expect(transactionId).toBeDefined();
342+
expect(request.phase).toEqual(VerificationPhase.Requested);
343+
344+
// and now the request should be visible via `getVerificationRequestsToDeviceInProgress`
345+
{
346+
const requests = aliceClient.getCrypto()!.getVerificationRequestsToDeviceInProgress(TEST_USER_ID);
347+
expect(requests.length).toEqual(1);
348+
expect(requests[0].transactionId).toEqual(transactionId);
349+
}
350+
351+
// legacy crypto picks devices individually; rust crypto uses a broadcast message
352+
const toDeviceMessage =
353+
requestBody.messages[TEST_USER_ID]["*"] ?? requestBody.messages[TEST_USER_ID][TEST_DEVICE_ID];
354+
expect(toDeviceMessage.from_device).toEqual(aliceClient.deviceId);
355+
expect(toDeviceMessage.transaction_id).toEqual(transactionId);
356+
});
357+
320358
oldBackendOnly("can verify another via QR code with an untrusted cross-signing key", async () => {
321359
// QRCode fails if we don't yet have the cross-signing keys, so make sure we have them now.
322360
e2eKeyResponder.addCrossSigningData(SIGNED_CROSS_SIGNING_KEYS_DATA);

src/rust-crypto/rust-crypto.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,19 @@ export class RustCrypto implements CryptoBackend {
584584
* @returns a VerificationRequest when the request has been sent to the other party.
585585
*/
586586
public async requestOwnUserVerification(): Promise<VerificationRequest> {
587-
throw new Error("not implemented");
587+
const userIdentity: RustSdkCryptoJs.OwnUserIdentity | undefined = await this.olmMachine.getIdentity(
588+
new RustSdkCryptoJs.UserId(this.userId),
589+
);
590+
if (userIdentity === undefined) {
591+
throw new Error("cannot request verification for this device when there is no existing cross-signing key");
592+
}
593+
594+
const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] =
595+
await userIdentity.requestVerification(
596+
this.supportedVerificationMethods?.map(verificationMethodIdentifierToMethod),
597+
);
598+
await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
599+
return new RustVerificationRequest(request, this.outgoingRequestProcessor);
588600
}
589601

590602
/**

0 commit comments

Comments
 (0)