You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-26 17:03:12 +03:00
Merge pull request #1050 from uhoreg/verification_in_dms
verification in DMs
This commit is contained in:
@@ -273,4 +273,127 @@ describe("SAS verification", function() {
|
|||||||
expect(bob.setDeviceVerified)
|
expect(bob.setDeviceVerified)
|
||||||
.toNotHaveBeenCalled();
|
.toNotHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("verification in DM", function() {
|
||||||
|
let alice;
|
||||||
|
let bob;
|
||||||
|
let aliceSasEvent;
|
||||||
|
let bobSasEvent;
|
||||||
|
let aliceVerifier;
|
||||||
|
let bobPromise;
|
||||||
|
|
||||||
|
beforeEach(async function() {
|
||||||
|
[alice, bob] = await makeTestClients(
|
||||||
|
[
|
||||||
|
{userId: "@alice:example.com", deviceId: "Osborne2"},
|
||||||
|
{userId: "@bob:example.com", deviceId: "Dynabook"},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
verificationMethods: [verificationMethods.SAS],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
alice.setDeviceVerified = expect.createSpy();
|
||||||
|
alice.getDeviceEd25519Key = () => {
|
||||||
|
return "alice+base64+ed25519+key";
|
||||||
|
};
|
||||||
|
alice.getStoredDevice = () => {
|
||||||
|
return DeviceInfo.fromStorage(
|
||||||
|
{
|
||||||
|
keys: {
|
||||||
|
"ed25519:Dynabook": "bob+base64+ed25519+key",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Dynabook",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
alice.downloadKeys = () => {
|
||||||
|
return Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
bob.setDeviceVerified = expect.createSpy();
|
||||||
|
bob.getStoredDevice = () => {
|
||||||
|
return DeviceInfo.fromStorage(
|
||||||
|
{
|
||||||
|
keys: {
|
||||||
|
"ed25519:Osborne2": "alice+base64+ed25519+key",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Osborne2",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
bob.getDeviceEd25519Key = () => {
|
||||||
|
return "bob+base64+ed25519+key";
|
||||||
|
};
|
||||||
|
bob.downloadKeys = () => {
|
||||||
|
return Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
aliceSasEvent = null;
|
||||||
|
bobSasEvent = null;
|
||||||
|
|
||||||
|
bobPromise = new Promise((resolve, reject) => {
|
||||||
|
bob.on("event", async (event) => {
|
||||||
|
const content = event.getContent();
|
||||||
|
if (event.getType() === "m.room.message"
|
||||||
|
&& content.msgtype === "m.key.verification.request") {
|
||||||
|
expect(content.methods).toInclude(SAS.NAME);
|
||||||
|
expect(content.to).toBe(bob.getUserId());
|
||||||
|
const verifier = bob.acceptVerificationDM(event, SAS.NAME);
|
||||||
|
verifier.on("show_sas", (e) => {
|
||||||
|
if (!e.sas.emoji || !e.sas.decimal) {
|
||||||
|
e.cancel();
|
||||||
|
} else if (!aliceSasEvent) {
|
||||||
|
bobSasEvent = e;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
expect(e.sas).toEqual(aliceSasEvent.sas);
|
||||||
|
e.confirm();
|
||||||
|
aliceSasEvent.confirm();
|
||||||
|
} catch (error) {
|
||||||
|
e.mismatch();
|
||||||
|
aliceSasEvent.mismatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await verifier.verify();
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
aliceVerifier = await alice.requestVerificationDM(
|
||||||
|
bob.getUserId(), "!room_id", [verificationMethods.SAS],
|
||||||
|
);
|
||||||
|
aliceVerifier.on("show_sas", (e) => {
|
||||||
|
if (!e.sas.emoji || !e.sas.decimal) {
|
||||||
|
e.cancel();
|
||||||
|
} else if (!bobSasEvent) {
|
||||||
|
aliceSasEvent = e;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
expect(e.sas).toEqual(bobSasEvent.sas);
|
||||||
|
e.confirm();
|
||||||
|
bobSasEvent.confirm();
|
||||||
|
} catch (error) {
|
||||||
|
e.mismatch();
|
||||||
|
bobSasEvent.mismatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should verify a key", async function() {
|
||||||
|
await Promise.all([
|
||||||
|
aliceVerifier.verify(),
|
||||||
|
bobPromise,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// make sure Alice and Bob verified each other
|
||||||
|
expect(alice.setDeviceVerified)
|
||||||
|
.toHaveBeenCalledWith(bob.getUserId(), bob.deviceId);
|
||||||
|
expect(bob.setDeviceVerified)
|
||||||
|
.toHaveBeenCalledWith(alice.getUserId(), alice.deviceId);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -43,6 +43,25 @@ export async function makeTestClients(userInfos, options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const sendEvent = function(room, type, content) {
|
||||||
|
// make up a unique ID as the event ID
|
||||||
|
const eventId = "$" + this.makeTxnId(); // eslint-disable-line babel/no-invalid-this
|
||||||
|
const event = new MatrixEvent({
|
||||||
|
sender: this.getUserId(), // eslint-disable-line babel/no-invalid-this
|
||||||
|
type: type,
|
||||||
|
content: content,
|
||||||
|
room_id: room,
|
||||||
|
event_id: eventId,
|
||||||
|
});
|
||||||
|
for (const client of clients) {
|
||||||
|
setTimeout(
|
||||||
|
() => client.emit("event", event),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {event_id: eventId};
|
||||||
|
};
|
||||||
|
|
||||||
for (const userInfo of userInfos) {
|
for (const userInfo of userInfos) {
|
||||||
const client = (new TestClient(
|
const client = (new TestClient(
|
||||||
@@ -54,6 +73,7 @@ export async function makeTestClients(userInfos, options) {
|
|||||||
}
|
}
|
||||||
clientMap[userInfo.userId][userInfo.deviceId] = client;
|
clientMap[userInfo.userId][userInfo.deviceId] = client;
|
||||||
client.sendToDevice = sendToDevice;
|
client.sendToDevice = sendToDevice;
|
||||||
|
client.sendEvent = sendEvent;
|
||||||
clients.push(client);
|
clients.push(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -785,6 +785,40 @@ async function _setDeviceVerification(
|
|||||||
client.emit("deviceVerificationChanged", userId, deviceId, dev);
|
client.emit("deviceVerificationChanged", userId, deviceId, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request a key verification from another user, using a DM.
|
||||||
|
*
|
||||||
|
* @param {string} userId the user to request verification with
|
||||||
|
* @param {string} roomId the room to use for verification
|
||||||
|
* @param {Array} methods array of verification methods to use. Defaults to
|
||||||
|
* all known methods
|
||||||
|
*
|
||||||
|
* @returns {Promise<module:crypto/verification/Base>} resolves to a verifier
|
||||||
|
* when the request is accepted by the other user
|
||||||
|
*/
|
||||||
|
MatrixClient.prototype.requestVerificationDM = function(userId, roomId, methods) {
|
||||||
|
if (this._crypto === null) {
|
||||||
|
throw new Error("End-to-end encryption disabled");
|
||||||
|
}
|
||||||
|
return this._crypto.requestVerificationDM(userId, roomId, methods);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept a key verification request from a DM.
|
||||||
|
*
|
||||||
|
* @param {module:models/event~MatrixEvent} event the verification request
|
||||||
|
* that is accepted
|
||||||
|
* @param {string} method the verification mmethod to use
|
||||||
|
*
|
||||||
|
* @returns {module:crypto/verification/Base} a verifier
|
||||||
|
*/
|
||||||
|
MatrixClient.prototype.acceptVerificationDM = function(event, method) {
|
||||||
|
if (this._crypto === null) {
|
||||||
|
throw new Error("End-to-end encryption disabled");
|
||||||
|
}
|
||||||
|
return this._crypto.acceptVerificationDM(event, method);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request a key verification from another user.
|
* Request a key verification from another user.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -756,6 +756,132 @@ Crypto.prototype.setDeviceVerification = async function(
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function verificationEventHandler(target, userId, roomId, eventId) {
|
||||||
|
return function(event) {
|
||||||
|
// listen for events related to this verification
|
||||||
|
if (event.getRoomId() !== roomId
|
||||||
|
|| event.getSender() !== userId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const content = event.getContent();
|
||||||
|
if (!content["m.relates_to"]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const relatesTo
|
||||||
|
= content["m.relationship"] || content["m.relates_to"];
|
||||||
|
if (!relatesTo.rel_type
|
||||||
|
|| relatesTo.rel_type !== "m.reference"
|
||||||
|
|| !relatesTo.event_id
|
||||||
|
|| relatesTo.event_id !== eventId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the event seems to be related to this verification, so pass it on to
|
||||||
|
// the verification handler
|
||||||
|
target.handleEvent(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Crypto.prototype.requestVerificationDM = async function(userId, roomId, methods) {
|
||||||
|
let methodMap;
|
||||||
|
if (methods) {
|
||||||
|
methodMap = new Map();
|
||||||
|
for (const method of methods) {
|
||||||
|
if (typeof method === "string") {
|
||||||
|
methodMap.set(method, defaultVerificationMethods[method]);
|
||||||
|
} else if (method.NAME) {
|
||||||
|
methodMap.set(method.NAME, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
methodMap = this._baseApis._crypto._verificationMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
let eventId = undefined;
|
||||||
|
const listenPromise = new Promise((_resolve, _reject) => {
|
||||||
|
const listener = (event) => {
|
||||||
|
// listen for events related to this verification
|
||||||
|
if (event.getRoomId() !== roomId
|
||||||
|
|| event.getSender() !== userId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const relatesTo = event.getRelation();
|
||||||
|
if (!relatesTo || !relatesTo.rel_type
|
||||||
|
|| relatesTo.rel_type !== "m.reference"
|
||||||
|
|| !relatesTo.event_id
|
||||||
|
|| relatesTo.event_id !== eventId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = event.getContent();
|
||||||
|
// the event seems to be related to this verification
|
||||||
|
switch (event.getType()) {
|
||||||
|
case "m.key.verification.start": {
|
||||||
|
const verifier = new (methodMap.get(content.method))(
|
||||||
|
this._baseApis, userId, content.from_device, eventId,
|
||||||
|
roomId, event,
|
||||||
|
);
|
||||||
|
verifier.handler = verificationEventHandler(
|
||||||
|
verifier, userId, roomId, eventId,
|
||||||
|
);
|
||||||
|
// this handler gets removed when the verification finishes
|
||||||
|
// (see the verify method of crypto/verification/Base.js)
|
||||||
|
this._baseApis.on("event", verifier.handler);
|
||||||
|
resolve(verifier);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "m.key.verification.cancel": {
|
||||||
|
reject(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this._baseApis.on("event", listener);
|
||||||
|
|
||||||
|
const resolve = (...args) => {
|
||||||
|
this._baseApis.off("event", listener);
|
||||||
|
_resolve(...args);
|
||||||
|
};
|
||||||
|
const reject = (...args) => {
|
||||||
|
this._baseApis.off("event", listener);
|
||||||
|
_reject(...args);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await this._baseApis.sendEvent(
|
||||||
|
roomId, "m.room.message",
|
||||||
|
{
|
||||||
|
body: this._baseApis.getUserId() + " is requesting to verify " +
|
||||||
|
"your key, but your client does not support in-chat key " +
|
||||||
|
"verification. You will need to use legacy key " +
|
||||||
|
"verification to verify keys.",
|
||||||
|
msgtype: "m.key.verification.request",
|
||||||
|
to: userId,
|
||||||
|
from_device: this._baseApis.getDeviceId(),
|
||||||
|
methods: [...methodMap.keys()],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
eventId = res.event_id;
|
||||||
|
|
||||||
|
return listenPromise;
|
||||||
|
};
|
||||||
|
|
||||||
|
Crypto.prototype.acceptVerificationDM = function(event, Method) {
|
||||||
|
if (typeof(Method) === "string") {
|
||||||
|
Method = defaultVerificationMethods[Method];
|
||||||
|
}
|
||||||
|
const content = event.getContent();
|
||||||
|
const verifier = new Method(
|
||||||
|
this._baseApis, event.getSender(), content.from_device, event.getId(),
|
||||||
|
event.getRoomId(),
|
||||||
|
);
|
||||||
|
verifier.handler = verificationEventHandler(
|
||||||
|
verifier, event.getSender(), event.getRoomId(), event.getId(),
|
||||||
|
);
|
||||||
|
this._baseApis.on("event", verifier.handler);
|
||||||
|
return verifier;
|
||||||
|
};
|
||||||
|
|
||||||
Crypto.prototype.requestVerification = function(userId, methods, devices) {
|
Crypto.prototype.requestVerification = function(userId, methods, devices) {
|
||||||
if (!methods) {
|
if (!methods) {
|
||||||
// .keys() returns an iterator, so we need to explicitly turn it into an array
|
// .keys() returns an iterator, so we need to explicitly turn it into an array
|
||||||
@@ -803,20 +929,7 @@ Crypto.prototype.beginKeyVerification = function(
|
|||||||
this._verificationTransactions.set(userId, new Map());
|
this._verificationTransactions.set(userId, new Map());
|
||||||
}
|
}
|
||||||
transactionId = transactionId || randomString(32);
|
transactionId = transactionId || randomString(32);
|
||||||
if (method instanceof Array) {
|
if (this._verificationMethods.has(method)) {
|
||||||
if (method.length !== 2
|
|
||||||
|| !this._verificationMethods.has(method[0])
|
|
||||||
|| !this._verificationMethods.has(method[1])) {
|
|
||||||
throw newUnknownMethodError();
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
return new TwoPartVerification(
|
|
||||||
this._verificationMethods[method[0]],
|
|
||||||
this._verificationMethods[method[1]],
|
|
||||||
userId, deviceId, transactionId,
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
} else if (this._verificationMethods.has(method)) {
|
|
||||||
const verifier = new (this._verificationMethods.get(method))(
|
const verifier = new (this._verificationMethods.get(method))(
|
||||||
this._baseApis, userId, deviceId, transactionId,
|
this._baseApis, userId, deviceId, transactionId,
|
||||||
);
|
);
|
||||||
@@ -1826,22 +1939,6 @@ Crypto.prototype._onKeyVerificationStart = function(event) {
|
|||||||
transaction_id: content.transactionId,
|
transaction_id: content.transactionId,
|
||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
} else if (content.next_method) {
|
|
||||||
if (!this._verificationMethods.has(content.next_method)) {
|
|
||||||
cancel(newUnknownMethodError({
|
|
||||||
transaction_id: content.transactionId,
|
|
||||||
}));
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
/* TODO:
|
|
||||||
const verification = new TwoPartVerification(
|
|
||||||
this._verificationMethods[content.method],
|
|
||||||
this._verificationMethods[content.next_method],
|
|
||||||
userId, deviceId,
|
|
||||||
);
|
|
||||||
this.emit(verification.event_type, verification);
|
|
||||||
this.emit(verification.first.event_type, verification);*/
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const verifier = new (this._verificationMethods.get(content.method))(
|
const verifier = new (this._verificationMethods.get(content.method))(
|
||||||
this._baseApis, sender, deviceId, content.transaction_id,
|
this._baseApis, sender, deviceId, content.transaction_id,
|
||||||
@@ -1896,8 +1993,6 @@ Crypto.prototype._onKeyVerificationStart = function(event) {
|
|||||||
|
|
||||||
handler.request.resolve(verifier);
|
handler.request.resolve(verifier);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// FIXME: make sure we're in a two-part verification, and the start matches the second part
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._baseApis.emit("crypto.verification.start", verifier);
|
this._baseApis.emit("crypto.verification.start", verifier);
|
||||||
|
|||||||
@@ -47,42 +47,54 @@ export default class VerificationBase extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @param {string} transactionId the transaction ID to be used when sending events
|
* @param {string} transactionId the transaction ID to be used when sending events
|
||||||
*
|
*
|
||||||
* @param {object} startEvent the m.key.verification.start event that
|
* @param {string} [roomId] the room to use for verification
|
||||||
|
*
|
||||||
|
* @param {object} [startEvent] the m.key.verification.start event that
|
||||||
* initiated this verification, if any
|
* initiated this verification, if any
|
||||||
*
|
*
|
||||||
* @param {object} request the key verification request object related to
|
* @param {object} [request] the key verification request object related to
|
||||||
* this verification, if any
|
* this verification, if any
|
||||||
*
|
|
||||||
* @param {object} parent parent verification for this verification, if any
|
|
||||||
*/
|
*/
|
||||||
constructor(baseApis, userId, deviceId, transactionId, startEvent, request, parent) {
|
constructor(baseApis, userId, deviceId, transactionId, roomId, startEvent, request) {
|
||||||
super();
|
super();
|
||||||
this._baseApis = baseApis;
|
this._baseApis = baseApis;
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.deviceId = deviceId;
|
this.deviceId = deviceId;
|
||||||
this.transactionId = transactionId;
|
this.transactionId = transactionId;
|
||||||
this.startEvent = startEvent;
|
if (typeof(roomId) === "string" || roomId instanceof String) {
|
||||||
this.request = request;
|
this.roomId = roomId;
|
||||||
|
this.startEvent = startEvent;
|
||||||
|
this.request = request;
|
||||||
|
} else {
|
||||||
|
// if room ID was omitted, but start event and request were not
|
||||||
|
this.startEvent= roomId;
|
||||||
|
this.request = startEvent;
|
||||||
|
}
|
||||||
this.cancelled = false;
|
this.cancelled = false;
|
||||||
this._parent = parent;
|
|
||||||
this._done = false;
|
this._done = false;
|
||||||
this._promise = null;
|
this._promise = null;
|
||||||
this._transactionTimeoutTimer = null;
|
this._transactionTimeoutTimer = null;
|
||||||
|
|
||||||
// At this point, the verification request was received so start the timeout timer.
|
// At this point, the verification request was received so start the timeout timer.
|
||||||
this._resetTimer();
|
this._resetTimer();
|
||||||
|
|
||||||
|
if (this.roomId) {
|
||||||
|
this._send = this._sendMessage;
|
||||||
|
} else {
|
||||||
|
this._send = this._sendToDevice;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_resetTimer() {
|
_resetTimer() {
|
||||||
console.log("Refreshing/starting the verification transaction timeout timer");
|
logger.info("Refreshing/starting the verification transaction timeout timer");
|
||||||
if (this._transactionTimeoutTimer !== null) {
|
if (this._transactionTimeoutTimer !== null) {
|
||||||
clearTimeout(this._transactionTimeoutTimer);
|
clearTimeout(this._transactionTimeoutTimer);
|
||||||
}
|
}
|
||||||
this._transactionTimeoutTimer = setTimeout(() => {
|
this._transactionTimeoutTimer = setTimeout(() => {
|
||||||
if (!this._done && !this.cancelled) {
|
if (!this._done && !this.cancelled) {
|
||||||
console.log("Triggering verification timeout");
|
logger.info("Triggering verification timeout");
|
||||||
this.cancel(timeoutException);
|
this.cancel(timeoutException);
|
||||||
}
|
}
|
||||||
}, 10 * 60 * 1000); // 10 minutes
|
}, 10 * 60 * 1000); // 10 minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +105,8 @@ export default class VerificationBase extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* send a message to the other participant, using to-device messages
|
||||||
|
*/
|
||||||
_sendToDevice(type, content) {
|
_sendToDevice(type, content) {
|
||||||
if (this._done) {
|
if (this._done) {
|
||||||
return Promise.reject(new Error("Verification is already done"));
|
return Promise.reject(new Error("Verification is already done"));
|
||||||
@@ -103,6 +117,21 @@ export default class VerificationBase extends EventEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* send a message to the other participant, using in-roomm messages
|
||||||
|
*/
|
||||||
|
_sendMessage(type, content) {
|
||||||
|
if (this._done) {
|
||||||
|
return Promise.reject(new Error("Verification is already done"));
|
||||||
|
}
|
||||||
|
// FIXME: if MSC1849 decides to use m.relationship instead of
|
||||||
|
// m.relates_to, we should follow suit here
|
||||||
|
content["m.relates_to"] = {
|
||||||
|
rel_type: "m.reference",
|
||||||
|
event_id: this.transactionId,
|
||||||
|
};
|
||||||
|
return this._baseApis.sendEvent(this.roomId, type, content);
|
||||||
|
}
|
||||||
|
|
||||||
_waitForEvent(type) {
|
_waitForEvent(type) {
|
||||||
if (this._done) {
|
if (this._done) {
|
||||||
return Promise.reject(new Error("Verification is already done"));
|
return Promise.reject(new Error("Verification is already done"));
|
||||||
@@ -140,6 +169,10 @@ export default class VerificationBase extends EventEmitter {
|
|||||||
done() {
|
done() {
|
||||||
this._endTimer(); // always kill the activity timer
|
this._endTimer(); // always kill the activity timer
|
||||||
if (!this._done) {
|
if (!this._done) {
|
||||||
|
if (this.roomId) {
|
||||||
|
// verification in DM requires a done message
|
||||||
|
this._send("m.key.verification.done", {});
|
||||||
|
}
|
||||||
this._resolve();
|
this._resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +186,7 @@ export default class VerificationBase extends EventEmitter {
|
|||||||
// cancelled by the other user)
|
// cancelled by the other user)
|
||||||
if (e === timeoutException) {
|
if (e === timeoutException) {
|
||||||
const timeoutEvent = newTimeoutError();
|
const timeoutEvent = newTimeoutError();
|
||||||
this._sendToDevice(timeoutEvent.getType(), timeoutEvent.getContent());
|
this._send(timeoutEvent.getType(), timeoutEvent.getContent());
|
||||||
} else if (e instanceof MatrixEvent) {
|
} else if (e instanceof MatrixEvent) {
|
||||||
const sender = e.getSender();
|
const sender = e.getSender();
|
||||||
if (sender !== this.userId) {
|
if (sender !== this.userId) {
|
||||||
@@ -163,9 +196,9 @@ export default class VerificationBase extends EventEmitter {
|
|||||||
content.reason = content.reason || content.body
|
content.reason = content.reason || content.body
|
||||||
|| "Unknown reason";
|
|| "Unknown reason";
|
||||||
content.transaction_id = this.transactionId;
|
content.transaction_id = this.transactionId;
|
||||||
this._sendToDevice("m.key.verification.cancel", content);
|
this._send("m.key.verification.cancel", content);
|
||||||
} else {
|
} else {
|
||||||
this._sendToDevice("m.key.verification.cancel", {
|
this._send("m.key.verification.cancel", {
|
||||||
code: "m.unknown",
|
code: "m.unknown",
|
||||||
reason: content.body || "Unknown reason",
|
reason: content.body || "Unknown reason",
|
||||||
transaction_id: this.transactionId,
|
transaction_id: this.transactionId,
|
||||||
@@ -173,7 +206,7 @@ export default class VerificationBase extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this._sendToDevice("m.key.verification.cancel", {
|
this._send("m.key.verification.cancel", {
|
||||||
code: "m.unknown",
|
code: "m.unknown",
|
||||||
reason: e.toString(),
|
reason: e.toString(),
|
||||||
transaction_id: this.transactionId,
|
transaction_id: this.transactionId,
|
||||||
@@ -206,11 +239,17 @@ export default class VerificationBase extends EventEmitter {
|
|||||||
this._resolve = (...args) => {
|
this._resolve = (...args) => {
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this._endTimer();
|
this._endTimer();
|
||||||
|
if (this.handler) {
|
||||||
|
this._baseApis.off("event", this.handler);
|
||||||
|
}
|
||||||
resolve(...args);
|
resolve(...args);
|
||||||
};
|
};
|
||||||
this._reject = (...args) => {
|
this._reject = (...args) => {
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this._endTimer();
|
this._endTimer();
|
||||||
|
if (this.handler) {
|
||||||
|
this._baseApis.off("event", this.handler);
|
||||||
|
}
|
||||||
reject(...args);
|
reject(...args);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -213,9 +213,10 @@ export default class SAS extends Base {
|
|||||||
message_authentication_codes: MAC_LIST,
|
message_authentication_codes: MAC_LIST,
|
||||||
// FIXME: allow app to specify what SAS methods can be used
|
// FIXME: allow app to specify what SAS methods can be used
|
||||||
short_authentication_string: SAS_LIST,
|
short_authentication_string: SAS_LIST,
|
||||||
transaction_id: this.transactionId,
|
|
||||||
};
|
};
|
||||||
this._sendToDevice("m.key.verification.start", initialMessage);
|
// NOTE: this._send will modify initialMessage to include the
|
||||||
|
// transaction_id field, or the m.relationship/m.relates_to field
|
||||||
|
this._send("m.key.verification.start", initialMessage);
|
||||||
|
|
||||||
|
|
||||||
let e = await this._waitForEvent("m.key.verification.accept");
|
let e = await this._waitForEvent("m.key.verification.accept");
|
||||||
@@ -235,7 +236,7 @@ export default class SAS extends Base {
|
|||||||
const hashCommitment = content.commitment;
|
const hashCommitment = content.commitment;
|
||||||
const olmSAS = new global.Olm.SAS();
|
const olmSAS = new global.Olm.SAS();
|
||||||
try {
|
try {
|
||||||
this._sendToDevice("m.key.verification.key", {
|
this._send("m.key.verification.key", {
|
||||||
key: olmSAS.get_pubkey(),
|
key: olmSAS.get_pubkey(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -306,7 +307,7 @@ export default class SAS extends Base {
|
|||||||
const olmSAS = new global.Olm.SAS();
|
const olmSAS = new global.Olm.SAS();
|
||||||
try {
|
try {
|
||||||
const commitmentStr = olmSAS.get_pubkey() + anotherjson.stringify(content);
|
const commitmentStr = olmSAS.get_pubkey() + anotherjson.stringify(content);
|
||||||
this._sendToDevice("m.key.verification.accept", {
|
this._send("m.key.verification.accept", {
|
||||||
key_agreement_protocol: keyAgreement,
|
key_agreement_protocol: keyAgreement,
|
||||||
hash: hashMethod,
|
hash: hashMethod,
|
||||||
message_authentication_code: macMethod,
|
message_authentication_code: macMethod,
|
||||||
@@ -320,7 +321,7 @@ export default class SAS extends Base {
|
|||||||
// FIXME: make sure event is properly formed
|
// FIXME: make sure event is properly formed
|
||||||
content = e.getContent();
|
content = e.getContent();
|
||||||
olmSAS.set_their_key(content.key);
|
olmSAS.set_their_key(content.key);
|
||||||
this._sendToDevice("m.key.verification.key", {
|
this._send("m.key.verification.key", {
|
||||||
key: olmSAS.get_pubkey(),
|
key: olmSAS.get_pubkey(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -369,7 +370,7 @@ export default class SAS extends Base {
|
|||||||
keyId,
|
keyId,
|
||||||
baseInfo + "KEY_IDS",
|
baseInfo + "KEY_IDS",
|
||||||
);
|
);
|
||||||
this._sendToDevice("m.key.verification.mac", { mac, keys });
|
this._send("m.key.verification.mac", { mac, keys });
|
||||||
}
|
}
|
||||||
|
|
||||||
async _checkMAC(olmSAS, content, method) {
|
async _checkMAC(olmSAS, content, method) {
|
||||||
|
|||||||
Reference in New Issue
Block a user