From b0902cc35d2fc8deab2efd249c2ec6b2b7c90432 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 25 May 2023 21:23:41 +0100 Subject: [PATCH 1/8] Add `getShowSasCallbacks`, `getShowQrCodeCallbacks` to VerifierBase ... to avoid some type-casting --- src/crypto/verification/Base.ts | 27 ++++++++++++++++++++++++++- src/crypto/verification/QRCode.ts | 4 ++++ src/crypto/verification/SAS.ts | 4 ++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/crypto/verification/Base.ts b/src/crypto/verification/Base.ts index 89bead3aa3e..30280d18a8d 100644 --- a/src/crypto/verification/Base.ts +++ b/src/crypto/verification/Base.ts @@ -29,7 +29,12 @@ import { IVerificationChannel } from "./request/Channel"; import { MatrixClient } from "../../client"; import { VerificationRequest } from "./request/VerificationRequest"; import { TypedEventEmitter } from "../../models/typed-event-emitter"; -import { VerifierEvent, VerifierEventHandlerMap } from "../../crypto-api/verification"; +import { + ShowQrCodeCallbacks, + ShowSasCallbacks, + VerifierEvent, + VerifierEventHandlerMap, +} from "../../crypto-api/verification"; const timeoutException = new Error("Verification timed out"); @@ -373,4 +378,24 @@ export class VerificationBase< public get events(): string[] | undefined { return undefined; } + + /** + * Get the details for an SAS verification, if one is in progress + * + * Returns `null`, unless this verifier is for a SAS-based verification and we are waiting for the user to confirm + * the SAS matches. + */ + public getShowSasCallbacks(): ShowSasCallbacks | null { + return null; + } + + /** + * Get the details for a QR code verification, if one is in progress + * + * Returns `null`, unless this verifier is for a QR-code-based verification and we are waiting for the user to + * confirm a match. + */ + public getShowQrCodeCallbacks(): ShowQrCodeCallbacks | null { + return null; + } } diff --git a/src/crypto/verification/QRCode.ts b/src/crypto/verification/QRCode.ts index 38feade12db..b18a759ff8b 100644 --- a/src/crypto/verification/QRCode.ts +++ b/src/crypto/verification/QRCode.ts @@ -119,6 +119,10 @@ export class ReciprocateQRCode extends Base { } }); }; + + public getShowQrCodeCallbacks(): ShowQrCodeCallbacks | null { + return this.reciprocateQREvent ?? null; + } } const CODE_VERSION = 0x02; // the version of binary QR codes we support diff --git a/src/crypto/verification/SAS.ts b/src/crypto/verification/SAS.ts index 61f096ca452..f15adf585f0 100644 --- a/src/crypto/verification/SAS.ts +++ b/src/crypto/verification/SAS.ts @@ -480,4 +480,8 @@ export class SAS extends Base { } }); } + + public getShowSasCallbacks(): ShowSasCallbacks | null { + return this.sasEvent ?? null; + } } From e112e347be01a49268287bc59558343fdf3d7608 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 2 Jun 2023 16:51:34 +0100 Subject: [PATCH 2/8] Integration test for QR code verification Followup to https://github.com/matrix-org/matrix-js-sdk/pull/3436: another integration test, this time using the QR code flow --- spec/integ/crypto/verification.spec.ts | 123 +++++++++++++++++- .../test-data/generate-test-data.py | 90 ++++++++++++- spec/test-utils/test-data/index.ts | 51 ++++++++ 3 files changed, 261 insertions(+), 3 deletions(-) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 64a43d1ce1a..db2977b4509 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -18,12 +18,14 @@ import fetchMock from "fetch-mock-jest"; import { MockResponse } from "fetch-mock"; import { createClient, MatrixClient } from "../../../src"; -import { ShowSasCallbacks, VerifierEvent } from "../../../src/crypto-api/verification"; +import { ShowQrCodeCallbacks, ShowSasCallbacks, VerifierEvent } from "../../../src/crypto-api/verification"; import { escapeRegExp } from "../../../src/utils"; import { VerificationBase } from "../../../src/crypto/verification/Base"; import { CRYPTO_BACKENDS, InitCrypto } from "../../test-utils/test-utils"; import { SyncResponder } from "../../test-utils/SyncResponder"; import { + MASTER_CROSS_SIGNING_PUBLIC_KEY_BASE64, + SIGNED_CROSS_SIGNING_KEYS_DATA, SIGNED_TEST_DEVICE_DATA, TEST_DEVICE_ID, TEST_DEVICE_PUBLIC_ED25519_KEY_BASE64, @@ -40,6 +42,17 @@ import { // to ensure that we don't end up with dangling timeouts. jest.useFakeTimers(); +// Stub out global.crypto +// +// This shouldn't leak into other files, because jest gives each file a new environment. +global["crypto"] = { + // @ts-ignore this doesn't match the type in typescript, but that doesn't really matter + getRandomValues: function (array: T): T { + array.fill(0x12); + return array; + }, +}; + /** * Integration tests for verification functionality. * @@ -208,6 +221,110 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st olmSAS.free(); }); + oldBackendOnly( + "Outgoing verification: can verify another device via QR code with an untrusted cross-signing key", + async () => { + // we need to have bootstrapped cross-signing for this + //await bootstrapCrossSigning(aliceClient); + // console.warn("Bootstrapped"); + + // expect requests to download our own keys + fetchMock.post(new RegExp("/_matrix/client/(r0|v3)/keys/query"), { + device_keys: { + [TEST_USER_ID]: { + [TEST_DEVICE_ID]: SIGNED_TEST_DEVICE_DATA, + }, + }, + ...SIGNED_CROSS_SIGNING_KEYS_DATA, + }); + + // QRCode fails if we don't yet have the cross-signing keys, so make sure we have them now. + // + // Completing the initial sync will make the device list download outdated device lists (of which our own + // user will be one). + syncResponder.sendOrQueueSyncResponse({}); + // DeviceList has a sleep(5) which we need to make happen + await jest.advanceTimersByTimeAsync(10); + expect(aliceClient.getStoredCrossSigningForUser(TEST_USER_ID)).toBeTruthy(); + + // 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]), + ]); + const transactionId = request.channel.transactionId; + + const toDeviceMessage = requestBody.messages[TEST_USER_ID][TEST_DEVICE_ID]; + expect(toDeviceMessage.methods).toContain("m.qr_code.show.v1"); + expect(toDeviceMessage.methods).toContain("m.qr_code.scan.v1"); + expect(toDeviceMessage.methods).toContain("m.reciprocate.v1"); + expect(toDeviceMessage.from_device).toEqual(aliceClient.deviceId); + expect(toDeviceMessage.transaction_id).toEqual(transactionId); + + // The dummy device replies with an m.key.verification.ready, with an indication we can scan the QR code + returnToDeviceMessageFromSync({ + type: "m.key.verification.ready", + content: { + from_device: TEST_DEVICE_ID, + methods: ["m.qr_code.scan.v1"], + transaction_id: transactionId, + }, + }); + await waitForVerificationRequestChanged(request); + expect(request.phase).toEqual(Phase.Ready); + + // we should now have QR data we can display + const qrCodeData = request.qrCodeData!; + expect(qrCodeData).toBeTruthy(); + const qrCodeBuffer = qrCodeData.getBuffer(); + // https://spec.matrix.org/v1.7/client-server-api/#qr-code-format + expect(qrCodeBuffer.subarray(0, 6).toString("latin1")).toEqual("MATRIX"); + expect(qrCodeBuffer.readUint8(6)).toEqual(0x02); // version + expect(qrCodeBuffer.readUint8(7)).toEqual(0x02); // mode + const txnIdLen = qrCodeBuffer.readUint16BE(8); + expect(qrCodeBuffer.subarray(10, 10 + txnIdLen).toString("utf-8")).toEqual(transactionId); + // const aliceDevicePubKey = qrCodeBuffer.subarray(10 + txnIdLen, 32 + 10 + txnIdLen); + expect(qrCodeBuffer.subarray(42 + txnIdLen, 32 + 42 + txnIdLen)).toEqual( + Buffer.from(MASTER_CROSS_SIGNING_PUBLIC_KEY_BASE64, "base64"), + ); + const sharedSecret = qrCodeBuffer.subarray(74 + txnIdLen); + + // the dummy device "scans" the displayed QR code and acknowledges it with a "m.key.verification.start" + returnToDeviceMessageFromSync({ + type: "m.key.verification.start", + content: { + from_device: TEST_DEVICE_ID, + method: "m.reciprocate.v1", + transaction_id: transactionId, + secret: encodeUnpaddedBase64(sharedSecret), + }, + }); + await waitForVerificationRequestChanged(request); + expect(request.phase).toEqual(Phase.Started); + expect(request.chosenMethod).toEqual("m.reciprocate.v1"); + + // there should now be a verifier + const verifier: VerificationBase = request.verifier!; + expect(verifier).toBeDefined(); + + // ... which we call .verify on, which emits a ShowReciprocateQr event + const verificationPromise = verifier.verify(); + const reciprocateQRCodeCallbacks = await new Promise((resolve) => { + verifier.once(VerifierEvent.ShowReciprocateQr, resolve); + }); + + // Alice confirms she is happy + reciprocateQRCodeCallbacks.confirm(); + + // that should satisfy Alice, who should reply with a 'done' + await expectSendToDeviceMessage("m.key.verification.done"); + + // ... and the whole thing should be done! + await verificationPromise; + expect(request.phase).toEqual(Phase.Done); + }, + ); + function returnToDeviceMessageFromSync(ev: { type: string; content: object; sender?: string }): void { ev.sender ??= TEST_USER_ID; syncResponder.sendOrQueueSyncResponse({ to_device: { events: [ev] } }); @@ -253,3 +370,7 @@ function calculateMAC(olmSAS: Olm.SAS, input: string, info: string): string { //console.info(`Test MAC: input:'${input}, info: '${info}' -> '${mac}`); return mac; } + +function encodeUnpaddedBase64(uint8Array: ArrayBuffer | Uint8Array): string { + return Buffer.from(uint8Array).toString("base64").replace(/=+$/g, ""); +} diff --git a/spec/test-utils/test-data/generate-test-data.py b/spec/test-utils/test-data/generate-test-data.py index f5eae004e4a..3ba7dd4a8b9 100755 --- a/spec/test-utils/test-data/generate-test-data.py +++ b/spec/test-utils/test-data/generate-test-data.py @@ -37,6 +37,10 @@ # any 32-byte string can be an ed25519 private key. TEST_DEVICE_PRIVATE_KEY_BYTES = b"deadbeefdeadbeefdeadbeefdeadbeef" +MASTER_CROSS_SIGNING_PRIVATE_KEY_BYTES = b"doyouspeakwhaaaaaaaaaaaaaaaaaale" +USER_CROSS_SIGNING_PRIVATE_KEY_BYTES = b"useruseruseruseruseruseruseruser" +SELF_CROSS_SIGNING_PRIVATE_KEY_BYTES = b"selfselfselfselfselfselfselfself" + def main() -> None: private_key = ed25519.Ed25519PrivateKey.from_private_bytes( @@ -57,10 +61,17 @@ def main() -> None: "user_id": TEST_USER_ID, } - device_data["signatures"][TEST_USER_ID][ f"ed25519:{TEST_DEVICE_ID}"] = sign_json( + device_data["signatures"][TEST_USER_ID][f"ed25519:{TEST_DEVICE_ID}"] = sign_json( device_data, private_key ) + master_private_key = ed25519.Ed25519PrivateKey.from_private_bytes( + MASTER_CROSS_SIGNING_PRIVATE_KEY_BYTES + ) + b64_master_public_key = encode_base64( + master_private_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw) + ) + print( f"""\ /* Test data for cryptography tests @@ -69,6 +80,7 @@ def main() -> None: */ import {{ IDeviceKeys }} from "../../../src/@types/crypto"; +import {{ IDownloadKeyResult }} from "../../../src"; /* eslint-disable comma-dangle */ @@ -80,8 +92,82 @@ def main() -> None: /** Signed device data, suitable for returning from a `/keys/query` call */ export const SIGNED_TEST_DEVICE_DATA: IDeviceKeys = {json.dumps(device_data, indent=4)}; -""", end='', + +/** base64-encoded public master cross-signing key */ +export const MASTER_CROSS_SIGNING_PUBLIC_KEY_BASE64 = "{b64_master_public_key}"; + +/** Signed cross-signing keys data, also suitable for returning from a `/keys/query` call */ +export const SIGNED_CROSS_SIGNING_KEYS_DATA: Partial = { + json.dumps(build_cross_signing_keys_data(), indent=4) +}; +""", + end="", + ) + + +def build_cross_signing_keys_data() -> dict: + """Build the signed cross-signing-keys data for return from /keys/query""" + master_private_key = ed25519.Ed25519PrivateKey.from_private_bytes( + MASTER_CROSS_SIGNING_PRIVATE_KEY_BYTES ) + b64_master_public_key = encode_base64( + master_private_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw) + ) + self_signing_private_key = ed25519.Ed25519PrivateKey.from_private_bytes( + SELF_CROSS_SIGNING_PRIVATE_KEY_BYTES + ) + b64_self_signing_public_key = encode_base64( + self_signing_private_key.public_key().public_bytes( + Encoding.Raw, PublicFormat.Raw + ) + ) + user_signing_private_key = ed25519.Ed25519PrivateKey.from_private_bytes( + USER_CROSS_SIGNING_PRIVATE_KEY_BYTES + ) + b64_user_signing_public_key = encode_base64( + user_signing_private_key.public_key().public_bytes( + Encoding.Raw, PublicFormat.Raw + ) + ) + # create without signatures initially + cross_signing_keys_data = { + "master_keys": { + TEST_USER_ID: { + "keys": { + f"ed25519:{b64_master_public_key}": b64_master_public_key, + }, + "user_id": TEST_USER_ID, + "usage": ["master"], + } + }, + "self_signing_keys": { + TEST_USER_ID: { + "keys": { + f"ed25519:{b64_self_signing_public_key}": b64_self_signing_public_key, + }, + "user_id": TEST_USER_ID, + "usage": ["self_signing"], + }, + }, + "user_signing_keys": { + TEST_USER_ID: { + "keys": { + f"ed25519:{b64_user_signing_public_key}": b64_user_signing_public_key, + }, + "user_id": TEST_USER_ID, + "usage": ["user_signing"], + }, + }, + } + # sign the sub-keys with the master + for k in ["self_signing_keys", "user_signing_keys"]: + to_sign = cross_signing_keys_data[k][TEST_USER_ID] + sig = sign_json(to_sign, master_private_key) + to_sign["signatures"] = { + TEST_USER_ID: {f"ed25519:{b64_master_public_key}": sig} + } + + return cross_signing_keys_data def encode_base64(input_bytes: bytes) -> str: diff --git a/spec/test-utils/test-data/index.ts b/spec/test-utils/test-data/index.ts index fbb9a1c2bc7..07ff1222526 100644 --- a/spec/test-utils/test-data/index.ts +++ b/spec/test-utils/test-data/index.ts @@ -4,6 +4,7 @@ */ import { IDeviceKeys } from "../../../src/@types/crypto"; +import { IDownloadKeyResult } from "../../../src"; /* eslint-disable comma-dangle */ @@ -31,3 +32,53 @@ export const SIGNED_TEST_DEVICE_DATA: IDeviceKeys = { } } }; + +/** base64-encoded public master cross-signing key */ +export const MASTER_CROSS_SIGNING_PUBLIC_KEY_BASE64 = "J+5An10v1vzZpAXTYFokD1/PEVccFnLC61EfRXit0UY"; + +/** Signed cross-signing keys data, also suitable for returning from a `/keys/query` call */ +export const SIGNED_CROSS_SIGNING_KEYS_DATA: Partial = { + "master_keys": { + "@alice:localhost": { + "keys": { + "ed25519:J+5An10v1vzZpAXTYFokD1/PEVccFnLC61EfRXit0UY": "J+5An10v1vzZpAXTYFokD1/PEVccFnLC61EfRXit0UY" + }, + "user_id": "@alice:localhost", + "usage": [ + "master" + ] + } + }, + "self_signing_keys": { + "@alice:localhost": { + "keys": { + "ed25519:aU2+2CyXQTCuDcmWW0EL2bhJ6PdjFW2LbAsbHqf02AY": "aU2+2CyXQTCuDcmWW0EL2bhJ6PdjFW2LbAsbHqf02AY" + }, + "user_id": "@alice:localhost", + "usage": [ + "self_signing" + ], + "signatures": { + "@alice:localhost": { + "ed25519:J+5An10v1vzZpAXTYFokD1/PEVccFnLC61EfRXit0UY": "XfhYEhZmOs8BJdb3viatILBZ/bElsHXEW28V4tIaY5CxrBR0YOym3yZHWmRmypXessHZAKOhZn3yBMXzdajyCw" + } + } + } + }, + "user_signing_keys": { + "@alice:localhost": { + "keys": { + "ed25519:g5TC/zjQXyZYuDLZv7a41z5fFVrXpYPypG//AFQj8hY": "g5TC/zjQXyZYuDLZv7a41z5fFVrXpYPypG//AFQj8hY" + }, + "user_id": "@alice:localhost", + "usage": [ + "user_signing" + ], + "signatures": { + "@alice:localhost": { + "ed25519:J+5An10v1vzZpAXTYFokD1/PEVccFnLC61EfRXit0UY": "6AkD1XM2H0/ebgP9oBdMKNeft7uxsrb0XN1CsjjHgeZCvCTMmv3BHlLiT/Hzy4fe8H+S1tr484dcXN/PIdnfDA" + } + } + } + } +}; From d748649b297c82c5563172bbbafd81f6e207494e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 2 Jun 2023 16:59:43 +0100 Subject: [PATCH 3/8] Rename method ... it turns out not to be used quite as I thought. --- src/crypto/verification/Base.ts | 8 ++++---- src/crypto/verification/QRCode.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/crypto/verification/Base.ts b/src/crypto/verification/Base.ts index 30280d18a8d..de6a0f836b0 100644 --- a/src/crypto/verification/Base.ts +++ b/src/crypto/verification/Base.ts @@ -390,12 +390,12 @@ export class VerificationBase< } /** - * Get the details for a QR code verification, if one is in progress + * Get the details for reciprocating QR code verification, if one is in progress * - * Returns `null`, unless this verifier is for a QR-code-based verification and we are waiting for the user to - * confirm a match. + * Returns `null`, unless this verifier is for reciprocating a QR-code-based verification (ie, the other user has + * already scanned our QR code), and we are waiting for the user to confirm. */ - public getShowQrCodeCallbacks(): ShowQrCodeCallbacks | null { + public getReciprocateQrCodeCallbacks(): ShowQrCodeCallbacks | null { return null; } } diff --git a/src/crypto/verification/QRCode.ts b/src/crypto/verification/QRCode.ts index b18a759ff8b..a51db2e34e6 100644 --- a/src/crypto/verification/QRCode.ts +++ b/src/crypto/verification/QRCode.ts @@ -120,7 +120,7 @@ export class ReciprocateQRCode extends Base { }); }; - public getShowQrCodeCallbacks(): ShowQrCodeCallbacks | null { + public getReciprocateQrCodeCallbacks(): ShowQrCodeCallbacks | null { return this.reciprocateQREvent ?? null; } } From 0a6f49212179f9898b622aac688dca06dec52e7c Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 2 Jun 2023 17:13:29 +0100 Subject: [PATCH 4/8] tests for new methods --- spec/integ/crypto/verification.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index db2977b4509..be6817e945c 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -188,6 +188,9 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st verifier.once(VerifierEvent.ShowSas, resolve); }); + // `getShowSasCallbacks` is an alternative way to get the callbacks + expect(verifier.getShowSasCallbacks()).toBe(showSas); + // user confirms that the emoji match, and alice sends a 'mac' [requestBody] = await Promise.all([expectSendToDeviceMessage("m.key.verification.mac"), showSas.confirm()]); toDeviceMessage = requestBody.messages[TEST_USER_ID][TEST_DEVICE_ID]; @@ -313,6 +316,9 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st verifier.once(VerifierEvent.ShowReciprocateQr, resolve); }); + // getReciprocateQrCodeCallbacks() is an alternative way to get the callbacks + expect(verifier.getReciprocateQrCodeCallbacks()).toBe(reciprocateQRCodeCallbacks); + // Alice confirms she is happy reciprocateQRCodeCallbacks.confirm(); From 10aae141fac69890776fc3a683797e8a0177ee66 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 2 Jun 2023 17:37:57 +0100 Subject: [PATCH 5/8] Use Object.defineProperty, and restore afterwards Apparently global.crypto exists in some environments --- spec/integ/crypto/verification.spec.ts | 37 +++++++++++++++++++------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index db2977b4509..0a27bf34332 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -42,16 +42,33 @@ import { // to ensure that we don't end up with dangling timeouts. jest.useFakeTimers(); -// Stub out global.crypto -// -// This shouldn't leak into other files, because jest gives each file a new environment. -global["crypto"] = { - // @ts-ignore this doesn't match the type in typescript, but that doesn't really matter - getRandomValues: function (array: T): T { - array.fill(0x12); - return array; - }, -}; +let previousCrypto: Crypto | undefined; + +beforeAll(() => { + // Stub out global.crypto + previousCrypto = global["crypto"]; + + Object.defineProperty(global, "crypto", { + value: { + // @ts-ignore this doesn't match the type in typescript, but that doesn't really matter + getRandomValues: function (array: T): T { + array.fill(0x12); + return array; + }, + }, + }); +}); + +// restore the original global.crypto +afterAll(() => { + if (previousCrypto === undefined) { + delete global.crypto; + } else { + Object.defineProperty(global, "crypto", { + value: previousCrypto, + }); + } +}); /** * Integration tests for verification functionality. From f43fadd65c59597c48bc922a9601c232e1aac095 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 2 Jun 2023 17:49:21 +0100 Subject: [PATCH 6/8] apply ts-ignore --- spec/integ/crypto/verification.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 0a27bf34332..ce0906d98d3 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -50,7 +50,6 @@ beforeAll(() => { Object.defineProperty(global, "crypto", { value: { - // @ts-ignore this doesn't match the type in typescript, but that doesn't really matter getRandomValues: function (array: T): T { array.fill(0x12); return array; @@ -62,6 +61,7 @@ beforeAll(() => { // restore the original global.crypto afterAll(() => { if (previousCrypto === undefined) { + // @ts-ignore deleting a non-optional property. It *is* optional really. delete global.crypto; } else { Object.defineProperty(global, "crypto", { From ebfbba7112a72229cbe03f4725e5f97836bd8d45 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 2 Jun 2023 18:17:14 +0100 Subject: [PATCH 7/8] More test coverage --- spec/integ/crypto/verification.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 5656333ddb5..03ec5568c04 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -170,6 +170,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // there should now be a verifier const verifier: VerificationBase = request.verifier!; expect(verifier).toBeDefined(); + expect(verifier.getShowSasCallbacks()).toBeNull(); // start off the verification process: alice will send an `accept` const verificationPromise = verifier.verify(); @@ -207,6 +208,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // `getShowSasCallbacks` is an alternative way to get the callbacks expect(verifier.getShowSasCallbacks()).toBe(showSas); + expect(verifier.getReciprocateQrCodeCallbacks()).toBeNull(); // user confirms that the emoji match, and alice sends a 'mac' [requestBody] = await Promise.all([expectSendToDeviceMessage("m.key.verification.mac"), showSas.confirm()]); @@ -326,6 +328,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // there should now be a verifier const verifier: VerificationBase = request.verifier!; expect(verifier).toBeDefined(); + expect(verifier.getReciprocateQrCodeCallbacks()).toBeNull(); // ... which we call .verify on, which emits a ShowReciprocateQr event const verificationPromise = verifier.verify(); @@ -335,6 +338,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // getReciprocateQrCodeCallbacks() is an alternative way to get the callbacks expect(verifier.getReciprocateQrCodeCallbacks()).toBe(reciprocateQRCodeCallbacks); + expect(verifier.getShowSasCallbacks()).toBeNull(); // Alice confirms she is happy reciprocateQRCodeCallbacks.confirm(); From 6cad9cc14a20d08610bc7c93e7e5aee6d934d73e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 6 Jun 2023 12:09:08 +0100 Subject: [PATCH 8/8] fix bad merge --- spec/integ/crypto/verification.spec.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/integ/crypto/verification.spec.ts b/spec/integ/crypto/verification.spec.ts index 530cb2b8398..f4690294515 100644 --- a/spec/integ/crypto/verification.spec.ts +++ b/spec/integ/crypto/verification.spec.ts @@ -325,6 +325,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st // there should now be a verifier const verifier: VerificationBase = request.verifier!; expect(verifier).toBeDefined(); + expect(verifier.getReciprocateQrCodeCallbacks()).toBeNull(); // ... which we call .verify on, which emits a ShowReciprocateQr event const verificationPromise = verifier.verify(); @@ -332,6 +333,10 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st verifier.once(VerifierEvent.ShowReciprocateQr, resolve); }); + // getReciprocateQrCodeCallbacks() is an alternative way to get the callbacks + expect(verifier.getReciprocateQrCodeCallbacks()).toBe(reciprocateQRCodeCallbacks); + expect(verifier.getShowSasCallbacks()).toBeNull(); + // Alice confirms she is happy reciprocateQRCodeCallbacks.confirm();