You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-07 23:02:56 +03:00
Add support for scanning QR codes during verification, with Rust crypto (#3565)
* Offer `m.qr_code.scan.v1` verification method by default Normally, the application specifies the supported verification methods when creating the MatrixClient (and matrix-react-sdk does so). If the application leaves it unset, then the idea is that the js-sdk offers all known verification methods. However, by default, the rust-sdk doesn't specify `m.qr_code.scan.v1`. So basically, we need to set our own list of supported methods, rather than relying on the rust-sdk's defaults. * Factor out base class from `RustSASVerifier` * Implement QR code scanning * Update src/rust-crypto/verification.ts
This commit is contained in:
committed by
GitHub
parent
d5b22e1deb
commit
9db6ce107a
@@ -85,6 +85,10 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st
|
||||
// Rust backend. Once we have full support in the rust sdk, it will go away.
|
||||
const oldBackendOnly = backend === "rust-sdk" ? test.skip : test;
|
||||
|
||||
// newBackendOnly is the opposite to `oldBackendOnly`: it will skip the test if we are running against the legacy
|
||||
// backend.
|
||||
const newBackendOnly = backend === "rust-sdk" ? test : test.skip;
|
||||
|
||||
/** the client under test */
|
||||
let aliceClient: MatrixClient;
|
||||
|
||||
@@ -469,6 +473,64 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st
|
||||
await verificationPromise;
|
||||
expect(request.phase).toEqual(VerificationPhase.Done);
|
||||
});
|
||||
|
||||
newBackendOnly("can verify another by scanning their QR code", async () => {
|
||||
aliceClient = await startTestClient();
|
||||
// we need cross-signing keys for a QR code verification
|
||||
e2eKeyResponder.addCrossSigningData(SIGNED_CROSS_SIGNING_KEYS_DATA);
|
||||
await waitForDeviceList();
|
||||
|
||||
// Alice sends a m.key.verification.request
|
||||
const [, request] = await Promise.all([
|
||||
expectSendToDeviceMessage("m.key.verification.request"),
|
||||
aliceClient.getCrypto()!.requestDeviceVerification(TEST_USER_ID, TEST_DEVICE_ID),
|
||||
]);
|
||||
const transactionId = request.transactionId!;
|
||||
|
||||
// The dummy device replies with an m.key.verification.ready, indicating it can show a QR code
|
||||
returnToDeviceMessageFromSync(buildReadyMessage(transactionId, ["m.qr_code.show.v1", "m.reciprocate.v1"]));
|
||||
await waitForVerificationRequestChanged(request);
|
||||
expect(request.phase).toEqual(VerificationPhase.Ready);
|
||||
expect(request.otherPartySupportsMethod("m.qr_code.show.v1")).toBe(true);
|
||||
|
||||
// the dummy device shows a QR code
|
||||
const sharedSecret = "SUPERSEKRET";
|
||||
const qrCodeBuffer = buildQRCode(
|
||||
transactionId,
|
||||
TEST_DEVICE_PUBLIC_ED25519_KEY_BASE64,
|
||||
MASTER_CROSS_SIGNING_PUBLIC_KEY_BASE64,
|
||||
sharedSecret,
|
||||
);
|
||||
|
||||
// Alice scans the QR code
|
||||
const sendToDevicePromise = expectSendToDeviceMessage("m.key.verification.start");
|
||||
const verifier = await request.scanQRCode(qrCodeBuffer);
|
||||
|
||||
const requestBody = await sendToDevicePromise;
|
||||
const toDeviceMessage = requestBody.messages[TEST_USER_ID][TEST_DEVICE_ID];
|
||||
expect(toDeviceMessage).toEqual({
|
||||
from_device: aliceClient.deviceId,
|
||||
method: "m.reciprocate.v1",
|
||||
transaction_id: transactionId,
|
||||
secret: encodeUnpaddedBase64(Buffer.from(sharedSecret)),
|
||||
});
|
||||
|
||||
expect(request.phase).toEqual(VerificationPhase.Started);
|
||||
expect(request.chosenMethod).toEqual("m.reciprocate.v1");
|
||||
expect(verifier.getReciprocateQrCodeCallbacks()).toBeNull();
|
||||
|
||||
const verificationPromise = verifier.verify();
|
||||
|
||||
// the dummy device confirms that Alice scanned the QR code, by replying with a done
|
||||
returnToDeviceMessageFromSync(buildDoneMessage(transactionId));
|
||||
|
||||
// Alice also replies with a 'done'
|
||||
await expectSendToDeviceMessage("m.key.verification.done");
|
||||
|
||||
// ... and the whole thing should be done!
|
||||
await verificationPromise;
|
||||
expect(request.phase).toEqual(VerificationPhase.Done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("cancellation", () => {
|
||||
@@ -794,3 +856,22 @@ function buildDoneMessage(transactionId: string) {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function buildQRCode(transactionId: string, key1Base64: string, key2Base64: string, sharedSecret: string): Uint8Array {
|
||||
// https://spec.matrix.org/v1.7/client-server-api/#qr-code-format
|
||||
|
||||
const qrCodeBuffer = Buffer.alloc(150); // oversize
|
||||
let idx = 0;
|
||||
idx += qrCodeBuffer.write("MATRIX", idx, "ascii");
|
||||
idx = qrCodeBuffer.writeUInt8(0x02, idx); // version
|
||||
idx = qrCodeBuffer.writeUInt8(0x02, idx); // mode
|
||||
idx = qrCodeBuffer.writeInt16BE(transactionId.length, idx);
|
||||
idx += qrCodeBuffer.write(transactionId, idx, "ascii");
|
||||
|
||||
idx += Buffer.from(key1Base64, "base64").copy(qrCodeBuffer, idx);
|
||||
idx += Buffer.from(key2Base64, "base64").copy(qrCodeBuffer, idx);
|
||||
idx += qrCodeBuffer.write(sharedSecret, idx);
|
||||
|
||||
// truncate to the right length
|
||||
return qrCodeBuffer.subarray(0, idx);
|
||||
}
|
||||
|
@@ -87,7 +87,7 @@ function makeTestRequest(
|
||||
): RustVerificationRequest {
|
||||
inner ??= makeMockedInner();
|
||||
outgoingRequestProcessor ??= {} as OutgoingRequestProcessor;
|
||||
return new RustVerificationRequest(inner, outgoingRequestProcessor, undefined);
|
||||
return new RustVerificationRequest(inner, outgoingRequestProcessor, []);
|
||||
}
|
||||
|
||||
/** Mock up a rust-side VerificationRequest */
|
||||
|
@@ -2241,7 +2241,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
this.cryptoCallbacks,
|
||||
useIndexedDB ? RUST_SDK_STORE_PREFIX : null,
|
||||
);
|
||||
rustCrypto.supportedVerificationMethods = this.verificationMethods;
|
||||
rustCrypto.setSupportedVerificationMethods(this.verificationMethods);
|
||||
|
||||
this.cryptoBackend = rustCrypto;
|
||||
|
||||
|
@@ -136,12 +136,27 @@ export interface VerificationRequest
|
||||
/**
|
||||
* Send an `m.key.verification.start` event to start verification via a particular method.
|
||||
*
|
||||
* This is normally used when starting a verification via emojis (ie, `method` is set to `m.sas.v1`).
|
||||
*
|
||||
* @param method - the name of the verification method to use.
|
||||
*
|
||||
* @returns The verifier which will do the actual verification.
|
||||
*/
|
||||
startVerification(method: string): Promise<Verifier>;
|
||||
|
||||
/**
|
||||
* Start a QR code verification by providing a scanned QR code for this verification flow.
|
||||
*
|
||||
* Validates the QR code, and if it is ok, sends an `m.key.verification.start` event with `method` set to
|
||||
* `m.reciprocate.v1`, to tell the other side the scan was successful.
|
||||
*
|
||||
* See also {@link VerificationRequest#startVerification} which can be used to start other verification methods.
|
||||
*
|
||||
* @param qrCodeData - the decoded QR code.
|
||||
* @returns A verifier; call `.verify()` on it to wait for the other side to complete the verification flow.
|
||||
*/
|
||||
scanQRCode(qrCodeData: Uint8Array): Promise<Verifier>;
|
||||
|
||||
/**
|
||||
* The verifier which is doing the actual verification, once the method has been established.
|
||||
* Only defined when the `phase` is Started.
|
||||
|
@@ -478,6 +478,10 @@ export class VerificationRequest<C extends IVerificationChannel = IVerificationC
|
||||
return verifier;
|
||||
}
|
||||
|
||||
public scanQRCode(qrCodeData: Uint8Array): Promise<Verifier> {
|
||||
throw new Error("QR code scanning not supported by legacy crypto");
|
||||
}
|
||||
|
||||
/**
|
||||
* sends the initial .request event.
|
||||
* @returns resolves when the event has been sent.
|
||||
|
@@ -56,6 +56,8 @@ import { EventType } from "../@types/event";
|
||||
import { CryptoEvent } from "../crypto";
|
||||
import { TypedEventEmitter } from "../models/typed-event-emitter";
|
||||
|
||||
const ALL_VERIFICATION_METHODS = ["m.sas.v1", "m.qr_code.scan.v1", "m.qr_code.show.v1", "m.reciprocate.v1"];
|
||||
|
||||
/**
|
||||
* An implementation of {@link CryptoBackend} using the Rust matrix-sdk-crypto.
|
||||
*
|
||||
@@ -560,7 +562,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
new RustVerificationRequest(
|
||||
request,
|
||||
this.outgoingRequestProcessor,
|
||||
this.supportedVerificationMethods,
|
||||
this._supportedVerificationMethods,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -582,10 +584,18 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
|
||||
/**
|
||||
* The verification methods we offer to the other side during an interactive verification.
|
||||
*/
|
||||
private _supportedVerificationMethods: string[] = ALL_VERIFICATION_METHODS;
|
||||
|
||||
/**
|
||||
* Set the verification methods we offer to the other side during an interactive verification.
|
||||
*
|
||||
* If `undefined`, we will offer all the methods supported by the Rust SDK.
|
||||
*/
|
||||
public supportedVerificationMethods: string[] | undefined;
|
||||
public setSupportedVerificationMethods(methods: string[] | undefined): void {
|
||||
// by default, the Rust SDK does not offer `m.qr_code.scan.v1`, but we do want to offer that.
|
||||
this._supportedVerificationMethods = methods ?? ALL_VERIFICATION_METHODS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a verification request to our other devices.
|
||||
@@ -606,10 +616,10 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
|
||||
const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] =
|
||||
await userIdentity.requestVerification(
|
||||
this.supportedVerificationMethods?.map(verificationMethodIdentifierToMethod),
|
||||
this._supportedVerificationMethods.map(verificationMethodIdentifierToMethod),
|
||||
);
|
||||
await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
|
||||
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this.supportedVerificationMethods);
|
||||
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this._supportedVerificationMethods);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -636,10 +646,10 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
|
||||
const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] =
|
||||
await device.requestVerification(
|
||||
this.supportedVerificationMethods?.map(verificationMethodIdentifierToMethod),
|
||||
this._supportedVerificationMethods.map(verificationMethodIdentifierToMethod),
|
||||
);
|
||||
await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
|
||||
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this.supportedVerificationMethods);
|
||||
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this._supportedVerificationMethods);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -793,7 +803,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
if (request) {
|
||||
this.emit(
|
||||
CryptoEvent.VerificationRequestReceived,
|
||||
new RustVerificationRequest(request, this.outgoingRequestProcessor, this.supportedVerificationMethods),
|
||||
new RustVerificationRequest(request, this.outgoingRequestProcessor, this._supportedVerificationMethods),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -58,17 +58,18 @@ export class RustVerificationRequest
|
||||
public constructor(
|
||||
private readonly inner: RustSdkCryptoJs.VerificationRequest,
|
||||
private readonly outgoingRequestProcessor: OutgoingRequestProcessor,
|
||||
private readonly supportedVerificationMethods: string[] | undefined,
|
||||
private readonly supportedVerificationMethods: string[],
|
||||
) {
|
||||
super();
|
||||
|
||||
const onChange = async (): Promise<void> => {
|
||||
// if we now have a `Verification` where we lacked one before, wrap it.
|
||||
// TODO: QR support
|
||||
if (this._verifier === undefined) {
|
||||
const verification: RustSdkCryptoJs.Qr | RustSdkCryptoJs.Sas | undefined = this.inner.getVerification();
|
||||
if (verification instanceof RustSdkCryptoJs.Sas) {
|
||||
this._verifier = new RustSASVerifier(verification, this, outgoingRequestProcessor);
|
||||
this.setVerifier(new RustSASVerifier(verification, this, outgoingRequestProcessor));
|
||||
} else if (verification instanceof RustSdkCryptoJs.Qr) {
|
||||
this.setVerifier(new RustQrCodeVerifier(verification, outgoingRequestProcessor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +78,10 @@ export class RustVerificationRequest
|
||||
inner.registerChangesCallback(onChange);
|
||||
}
|
||||
|
||||
private setVerifier(verifier: RustSASVerifier | RustQrCodeVerifier): void {
|
||||
this._verifier = verifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unique ID for this verification request.
|
||||
*
|
||||
@@ -188,6 +193,8 @@ export class RustVerificationRequest
|
||||
// TODO: this isn't quite right. The existence of a Verification doesn't prove that we have .started.
|
||||
if (verification instanceof RustSdkCryptoJs.Sas) {
|
||||
return "m.sas.v1";
|
||||
} else if (verification instanceof RustSdkCryptoJs.Qr) {
|
||||
return "m.reciprocate.v1";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -225,10 +232,7 @@ export class RustVerificationRequest
|
||||
|
||||
this._accepting = true;
|
||||
try {
|
||||
const req: undefined | OutgoingRequest =
|
||||
this.supportedVerificationMethods === undefined
|
||||
? this.inner.accept()
|
||||
: this.inner.acceptWithMethods(
|
||||
const req: undefined | OutgoingRequest = this.inner.acceptWithMethods(
|
||||
this.supportedVerificationMethods.map(verificationMethodIdentifierToMethod),
|
||||
);
|
||||
if (req) {
|
||||
@@ -315,6 +319,32 @@ export class RustVerificationRequest
|
||||
return this._verifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a QR code verification by providing a scanned QR code for this verification flow.
|
||||
*
|
||||
* Implementation of {@link Crypto.VerificationRequest#scanQRCode}.
|
||||
*
|
||||
* @param qrCodeData - the decoded QR code.
|
||||
* @returns A verifier; call `.verify()` on it to wait for the other side to complete the verification flow.
|
||||
*/
|
||||
public async scanQRCode(uint8Array: Uint8Array): Promise<Verifier> {
|
||||
const scan = RustSdkCryptoJs.QrCodeScan.fromBytes(new Uint8ClampedArray(uint8Array));
|
||||
const verifier: RustSdkCryptoJs.Qr = await this.inner.scanQrCode(scan);
|
||||
|
||||
// this should have triggered the onChange callback, and we should now have a verifier
|
||||
if (!this._verifier) {
|
||||
throw new Error("Still no verifier after scanQrCode() call");
|
||||
}
|
||||
|
||||
// we can immediately trigger the reciprocate request
|
||||
const req: undefined | OutgoingRequest = verifier.reciprocate();
|
||||
if (req) {
|
||||
await this.outgoingRequestProcessor.makeOutgoingRequest(req);
|
||||
}
|
||||
|
||||
return this._verifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* The verifier which is doing the actual verification, once the method has been established.
|
||||
* Only defined when the `phase` is Started.
|
||||
@@ -359,23 +389,28 @@ export class RustVerificationRequest
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class RustSASVerifier extends TypedEventEmitter<VerifierEvent, VerifierEventHandlerMap> implements Verifier {
|
||||
/** Common base class for `Verifier` implementations which wrap rust classes.
|
||||
*
|
||||
* The generic parameter `InnerType` is the type of the rust Verification class which we wrap.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract class BaseRustVerifer<InnerType extends RustSdkCryptoJs.Qr | RustSdkCryptoJs.Sas> extends TypedEventEmitter<
|
||||
VerifierEvent,
|
||||
VerifierEventHandlerMap
|
||||
> {
|
||||
/** A promise which completes when the verification completes (or rejects when it is cancelled/fails) */
|
||||
private readonly completionPromise: Promise<void>;
|
||||
|
||||
private callbacks: ShowSasCallbacks | null = null;
|
||||
protected readonly completionPromise: Promise<void>;
|
||||
|
||||
public constructor(
|
||||
private readonly inner: RustSdkCryptoJs.Sas,
|
||||
_verificationRequest: RustVerificationRequest,
|
||||
private readonly outgoingRequestProcessor: OutgoingRequestProcessor,
|
||||
protected readonly inner: InnerType,
|
||||
protected readonly outgoingRequestProcessor: OutgoingRequestProcessor,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.completionPromise = new Promise<void>((resolve, reject) => {
|
||||
const onChange = async (): Promise<void> => {
|
||||
this.updateCallbacks();
|
||||
this.onChange();
|
||||
|
||||
if (this.inner.isDone()) {
|
||||
resolve(undefined);
|
||||
@@ -396,8 +431,113 @@ export class RustSASVerifier extends TypedEventEmitter<VerifierEvent, VerifierEv
|
||||
this.completionPromise.catch(() => null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook which is called when the underlying rust class notifies us that there has been a change.
|
||||
*
|
||||
* Can be overridden by subclasses to see if we can notify the application about an update.
|
||||
*/
|
||||
protected onChange(): void {}
|
||||
|
||||
/**
|
||||
* Returns true if the verification has been cancelled, either by us or the other side.
|
||||
*/
|
||||
public get hasBeenCancelled(): boolean {
|
||||
return this.inner.isCancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the other user in the verification process.
|
||||
*/
|
||||
public get userId(): string {
|
||||
return this.inner.otherUserId.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a verification.
|
||||
*
|
||||
* We will send an `m.key.verification.cancel` if the verification is still in flight. The verification promise
|
||||
* will reject, and a {@link Crypto.VerifierEvent#Cancel} will be emitted.
|
||||
*
|
||||
* @param e - the reason for the cancellation.
|
||||
*/
|
||||
public cancel(e: Error): void {
|
||||
// TODO: something with `e`
|
||||
const req: undefined | OutgoingRequest = this.inner.cancel();
|
||||
if (req) {
|
||||
this.outgoingRequestProcessor.makeOutgoingRequest(req);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 reciprocating QR code verification, if one is in progress
|
||||
*
|
||||
* 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 getReciprocateQrCodeCallbacks(): ShowQrCodeCallbacks | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** A Verifier instance which is used to show and/or scan a QR code. */
|
||||
export class RustQrCodeVerifier extends BaseRustVerifer<RustSdkCryptoJs.Qr> implements Verifier {
|
||||
public constructor(inner: RustSdkCryptoJs.Qr, outgoingRequestProcessor: OutgoingRequestProcessor) {
|
||||
super(inner, outgoingRequestProcessor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the key verification, if it has not already been started.
|
||||
*
|
||||
* @returns Promise which resolves when the verification has completed, or rejects if the verification is cancelled
|
||||
* or times out.
|
||||
*/
|
||||
public async verify(): Promise<void> {
|
||||
// Nothing to do here but wait.
|
||||
await this.completionPromise;
|
||||
}
|
||||
}
|
||||
|
||||
/** A Verifier instance which is used if we are exchanging emojis */
|
||||
export class RustSASVerifier extends BaseRustVerifer<RustSdkCryptoJs.Sas> implements Verifier {
|
||||
private callbacks: ShowSasCallbacks | null = null;
|
||||
|
||||
public constructor(
|
||||
inner: RustSdkCryptoJs.Sas,
|
||||
_verificationRequest: RustVerificationRequest,
|
||||
outgoingRequestProcessor: OutgoingRequestProcessor,
|
||||
) {
|
||||
super(inner, outgoingRequestProcessor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the key verification, if it has not already been started.
|
||||
*
|
||||
* This means sending a `m.key.verification.start` if we are the first responder, or a `m.key.verification.accept`
|
||||
* if the other side has already sent a start event.
|
||||
*
|
||||
* @returns Promise which resolves when the verification has completed, or rejects if the verification is cancelled
|
||||
* or times out.
|
||||
*/
|
||||
public async verify(): Promise<void> {
|
||||
const req: undefined | OutgoingRequest = this.inner.accept();
|
||||
if (req) {
|
||||
await this.outgoingRequestProcessor.makeOutgoingRequest(req);
|
||||
}
|
||||
await this.completionPromise;
|
||||
}
|
||||
|
||||
/** if we can now show the callbacks, do so */
|
||||
private updateCallbacks(): void {
|
||||
protected onChange(): void {
|
||||
if (this.callbacks === null) {
|
||||
const emoji: Array<Emoji> | undefined = this.inner.emoji();
|
||||
const decimal = this.inner.decimals() as [number, number, number] | undefined;
|
||||
@@ -428,53 +568,6 @@ export class RustSASVerifier extends TypedEventEmitter<VerifierEvent, VerifierEv
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the verification has been cancelled, either by us or the other side.
|
||||
*/
|
||||
public get hasBeenCancelled(): boolean {
|
||||
return this.inner.isCancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the other user in the verification process.
|
||||
*/
|
||||
public get userId(): string {
|
||||
return this.inner.otherUserId.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the key verification, if it has not already been started.
|
||||
*
|
||||
* This means sending a `m.key.verification.start` if we are the first responder, or a `m.key.verification.accept`
|
||||
* if the other side has already sent a start event.
|
||||
*
|
||||
* @returns Promise which resolves when the verification has completed, or rejects if the verification is cancelled
|
||||
* or times out.
|
||||
*/
|
||||
public async verify(): Promise<void> {
|
||||
const req: undefined | OutgoingRequest = this.inner.accept();
|
||||
if (req) {
|
||||
await this.outgoingRequestProcessor.makeOutgoingRequest(req);
|
||||
}
|
||||
await this.completionPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a verification.
|
||||
*
|
||||
* We will send an `m.key.verification.cancel` if the verification is still in flight. The verification promise
|
||||
* will reject, and a {@link Crypto.VerifierEvent#Cancel} will be emitted.
|
||||
*
|
||||
* @param e - the reason for the cancellation.
|
||||
*/
|
||||
public cancel(e: Error): void {
|
||||
// TODO: something with `e`
|
||||
const req: undefined | OutgoingRequest = this.inner.cancel();
|
||||
if (req) {
|
||||
this.outgoingRequestProcessor.makeOutgoingRequest(req);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details for an SAS verification, if one is in progress
|
||||
*
|
||||
@@ -484,16 +577,6 @@ export class RustSASVerifier extends TypedEventEmitter<VerifierEvent, VerifierEv
|
||||
public getShowSasCallbacks(): ShowSasCallbacks | null {
|
||||
return this.callbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details for reciprocating QR code verification, if one is in progress
|
||||
*
|
||||
* 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 getReciprocateQrCodeCallbacks(): ShowQrCodeCallbacks | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** For each specced verification method, the rust-side `VerificationMethod` corresponding to it */
|
||||
|
Reference in New Issue
Block a user