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
Handle MatrixRTC encryption keys arriving out of order (#4345)
* Handle MatrixRTC encryption keys arriving out of order * Apply suggestions from code review Co-authored-by: Andrew Ferrazzutti <andrewf@element.io> * Suggestion from code review --------- Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
This commit is contained in:
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { EventTimeline, EventType, MatrixClient, MatrixError, MatrixEvent, Room } from "../../../src";
|
||||
import { encodeBase64, EventTimeline, EventType, MatrixClient, MatrixError, MatrixEvent, Room } from "../../../src";
|
||||
import { KnownMembership } from "../../../src/@types/membership";
|
||||
import {
|
||||
CallMembershipData,
|
||||
@@ -1145,6 +1145,7 @@ describe("MatrixRTCSession", () => {
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
getTs: jest.fn().mockReturnValue(Date.now()),
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
const bobKeys = sess.getKeysForParticipant("@bob:example.org", "bobsphone")!;
|
||||
@@ -1168,6 +1169,7 @@ describe("MatrixRTCSession", () => {
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
getTs: jest.fn().mockReturnValue(Date.now()),
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
const bobKeys = sess.getKeysForParticipant("@bob:example.org", "bobsphone")!;
|
||||
@@ -1179,6 +1181,130 @@ describe("MatrixRTCSession", () => {
|
||||
expect(bobKeys[4]).toEqual(Buffer.from("this is the key", "utf-8"));
|
||||
});
|
||||
|
||||
it("collects keys by merging", () => {
|
||||
const mockRoom = makeMockRoom([membershipTemplate]);
|
||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||
sess.onCallEncryption({
|
||||
getType: jest.fn().mockReturnValue("io.element.call.encryption_keys"),
|
||||
getContent: jest.fn().mockReturnValue({
|
||||
device_id: "bobsphone",
|
||||
call_id: "",
|
||||
keys: [
|
||||
{
|
||||
index: 0,
|
||||
key: "dGhpcyBpcyB0aGUga2V5",
|
||||
},
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
getTs: jest.fn().mockReturnValue(Date.now()),
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
let bobKeys = sess.getKeysForParticipant("@bob:example.org", "bobsphone")!;
|
||||
expect(bobKeys).toHaveLength(1);
|
||||
expect(bobKeys[0]).toEqual(Buffer.from("this is the key", "utf-8"));
|
||||
|
||||
sess.onCallEncryption({
|
||||
getType: jest.fn().mockReturnValue("io.element.call.encryption_keys"),
|
||||
getContent: jest.fn().mockReturnValue({
|
||||
device_id: "bobsphone",
|
||||
call_id: "",
|
||||
keys: [
|
||||
{
|
||||
index: 4,
|
||||
key: "dGhpcyBpcyB0aGUga2V5",
|
||||
},
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
getTs: jest.fn().mockReturnValue(Date.now()),
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
bobKeys = sess.getKeysForParticipant("@bob:example.org", "bobsphone")!;
|
||||
expect(bobKeys).toHaveLength(5);
|
||||
expect(bobKeys[4]).toEqual(Buffer.from("this is the key", "utf-8"));
|
||||
});
|
||||
|
||||
it("ignores older keys at same index", () => {
|
||||
const mockRoom = makeMockRoom([membershipTemplate]);
|
||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||
sess.onCallEncryption({
|
||||
getType: jest.fn().mockReturnValue("io.element.call.encryption_keys"),
|
||||
getContent: jest.fn().mockReturnValue({
|
||||
device_id: "bobsphone",
|
||||
call_id: "",
|
||||
keys: [
|
||||
{
|
||||
index: 0,
|
||||
key: encodeBase64(Buffer.from("newer key", "utf-8")),
|
||||
},
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
getTs: jest.fn().mockReturnValue(2000),
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
sess.onCallEncryption({
|
||||
getType: jest.fn().mockReturnValue("io.element.call.encryption_keys"),
|
||||
getContent: jest.fn().mockReturnValue({
|
||||
device_id: "bobsphone",
|
||||
call_id: "",
|
||||
keys: [
|
||||
{
|
||||
index: 0,
|
||||
key: encodeBase64(Buffer.from("older key", "utf-8")),
|
||||
},
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
getTs: jest.fn().mockReturnValue(1000), // earlier timestamp than the newer key
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
const bobKeys = sess.getKeysForParticipant("@bob:example.org", "bobsphone")!;
|
||||
expect(bobKeys).toHaveLength(1);
|
||||
expect(bobKeys[0]).toEqual(Buffer.from("newer key", "utf-8"));
|
||||
});
|
||||
|
||||
it("key timestamps are treated as monotonic", () => {
|
||||
const mockRoom = makeMockRoom([membershipTemplate]);
|
||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||
sess.onCallEncryption({
|
||||
getType: jest.fn().mockReturnValue("io.element.call.encryption_keys"),
|
||||
getContent: jest.fn().mockReturnValue({
|
||||
device_id: "bobsphone",
|
||||
call_id: "",
|
||||
keys: [
|
||||
{
|
||||
index: 0,
|
||||
key: encodeBase64(Buffer.from("first key", "utf-8")),
|
||||
},
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
getTs: jest.fn().mockReturnValue(1000),
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
sess.onCallEncryption({
|
||||
getType: jest.fn().mockReturnValue("io.element.call.encryption_keys"),
|
||||
getContent: jest.fn().mockReturnValue({
|
||||
device_id: "bobsphone",
|
||||
call_id: "",
|
||||
keys: [
|
||||
{
|
||||
index: 0,
|
||||
key: encodeBase64(Buffer.from("second key", "utf-8")),
|
||||
},
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
getTs: jest.fn().mockReturnValue(1000), // same timestamp as the first key
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
const bobKeys = sess.getKeysForParticipant("@bob:example.org", "bobsphone")!;
|
||||
expect(bobKeys).toHaveLength(1);
|
||||
expect(bobKeys[0]).toEqual(Buffer.from("second key", "utf-8"));
|
||||
});
|
||||
|
||||
it("ignores keys event for the local participant", () => {
|
||||
const mockRoom = makeMockRoom([membershipTemplate]);
|
||||
sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom);
|
||||
@@ -1195,6 +1321,7 @@ describe("MatrixRTCSession", () => {
|
||||
],
|
||||
}),
|
||||
getSender: jest.fn().mockReturnValue(client.getUserId()),
|
||||
getTs: jest.fn().mockReturnValue(Date.now()),
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
const myKeys = sess.getKeysForParticipant(client.getUserId()!, client.getDeviceId()!)!;
|
||||
|
Reference in New Issue
Block a user