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
Map decryption errors correctly from rust (#3710)
* Refactor key backup recovery to prepare for rust * rust backup restore support * map decryption errors correctly from rust * Move export out of old crypto to api with re-export * extract base64 utility * add tests for base64 util * more efficient regex * fix typo * use different vector for bob * missing import * Group tests for decryption errors * Do not map unneeded rust error for now
This commit is contained in:
@@ -57,6 +57,7 @@ import {
|
|||||||
RoomStateEvent,
|
RoomStateEvent,
|
||||||
} from "../../../src/matrix";
|
} from "../../../src/matrix";
|
||||||
import { DeviceInfo } from "../../../src/crypto/deviceinfo";
|
import { DeviceInfo } from "../../../src/crypto/deviceinfo";
|
||||||
|
import * as testData from "../../test-utils/test-data";
|
||||||
import { E2EKeyReceiver, IE2EKeyReceiver } from "../../test-utils/E2EKeyReceiver";
|
import { E2EKeyReceiver, IE2EKeyReceiver } from "../../test-utils/E2EKeyReceiver";
|
||||||
import { ISyncResponder, SyncResponder } from "../../test-utils/SyncResponder";
|
import { ISyncResponder, SyncResponder } from "../../test-utils/SyncResponder";
|
||||||
import { escapeRegExp } from "../../../src/utils";
|
import { escapeRegExp } from "../../../src/utils";
|
||||||
@@ -70,6 +71,7 @@ import {
|
|||||||
import { AddSecretStorageKeyOpts, SECRET_STORAGE_ALGORITHM_V1_AES } from "../../../src/secret-storage";
|
import { AddSecretStorageKeyOpts, SECRET_STORAGE_ALGORITHM_V1_AES } from "../../../src/secret-storage";
|
||||||
import { CrossSigningKey, CryptoCallbacks, KeyBackupInfo } from "../../../src/crypto-api";
|
import { CrossSigningKey, CryptoCallbacks, KeyBackupInfo } from "../../../src/crypto-api";
|
||||||
import { E2EKeyResponder } from "../../test-utils/E2EKeyResponder";
|
import { E2EKeyResponder } from "../../test-utils/E2EKeyResponder";
|
||||||
|
import { DecryptionError } from "../../../src/crypto/algorithms";
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
// reset fake-indexeddb after each test, to make sure we don't leak connections
|
// reset fake-indexeddb after each test, to make sure we don't leak connections
|
||||||
@@ -629,6 +631,107 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
|||||||
expect(decryptedEvent.getContent().body).toEqual("42");
|
expect(decryptedEvent.getContent().body).toEqual("42");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Unable to decrypt error codes", function () {
|
||||||
|
it("Encryption fails with expected UISI error", async () => {
|
||||||
|
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||||
|
await startClientAndAwaitFirstSync();
|
||||||
|
|
||||||
|
const awaitUISI = new Promise<void>((resolve) => {
|
||||||
|
aliceClient.on(MatrixEventEvent.Decrypted, (ev, err) => {
|
||||||
|
const error = err as DecryptionError;
|
||||||
|
if (error.code == "MEGOLM_UNKNOWN_INBOUND_SESSION_ID") {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Alice gets both the events in a single sync
|
||||||
|
const syncResponse = {
|
||||||
|
next_batch: 1,
|
||||||
|
rooms: {
|
||||||
|
join: {
|
||||||
|
[testData.TEST_ROOM_ID]: { timeline: { events: [testData.ENCRYPTED_EVENT] } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
syncResponder.sendOrQueueSyncResponse(syncResponse);
|
||||||
|
await syncPromise(aliceClient);
|
||||||
|
|
||||||
|
await awaitUISI;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Encryption fails with expected Unknown Index error", async () => {
|
||||||
|
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||||
|
await startClientAndAwaitFirstSync();
|
||||||
|
|
||||||
|
const awaitUnknownIndex = new Promise<void>((resolve) => {
|
||||||
|
aliceClient.on(MatrixEventEvent.Decrypted, (ev, err) => {
|
||||||
|
const error = err as DecryptionError;
|
||||||
|
if (error.code == "OLM_UNKNOWN_MESSAGE_INDEX") {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await aliceClient.getCrypto()!.importRoomKeys([testData.RATCHTED_MEGOLM_SESSION_DATA]);
|
||||||
|
|
||||||
|
// Alice gets both the events in a single sync
|
||||||
|
const syncResponse = {
|
||||||
|
next_batch: 1,
|
||||||
|
rooms: {
|
||||||
|
join: {
|
||||||
|
[testData.TEST_ROOM_ID]: { timeline: { events: [testData.ENCRYPTED_EVENT] } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
syncResponder.sendOrQueueSyncResponse(syncResponse);
|
||||||
|
await syncPromise(aliceClient);
|
||||||
|
|
||||||
|
await awaitUnknownIndex;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Encryption fails with Unable to decrypt for other errors", async () => {
|
||||||
|
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||||
|
await startClientAndAwaitFirstSync();
|
||||||
|
|
||||||
|
await aliceClient.getCrypto()!.importRoomKeys([testData.MEGOLM_SESSION_DATA]);
|
||||||
|
|
||||||
|
const awaitDecryptionError = new Promise<void>((resolve) => {
|
||||||
|
aliceClient.on(MatrixEventEvent.Decrypted, (ev, err) => {
|
||||||
|
const error = err as DecryptionError;
|
||||||
|
// rust and libolm can't have an exact 1:1 mapping for all errors,
|
||||||
|
// but some errors are part of API and should match
|
||||||
|
if (
|
||||||
|
error.code != "MEGOLM_UNKNOWN_INBOUND_SESSION_ID" &&
|
||||||
|
error.code != "OLM_UNKNOWN_MESSAGE_INDEX"
|
||||||
|
) {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const malformedEvent: Partial<IEvent> = JSON.parse(JSON.stringify(testData.ENCRYPTED_EVENT));
|
||||||
|
malformedEvent.content!.ciphertext = "AwgAEnAkBmciEAyhh1j6DCk29UXJ7kv/kvayUNfuNT0iAioLxcXjFX";
|
||||||
|
|
||||||
|
// Alice gets both the events in a single sync
|
||||||
|
const syncResponse = {
|
||||||
|
next_batch: 1,
|
||||||
|
rooms: {
|
||||||
|
join: {
|
||||||
|
[testData.TEST_ROOM_ID]: { timeline: { events: [malformedEvent] } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
syncResponder.sendOrQueueSyncResponse(syncResponse);
|
||||||
|
await syncPromise(aliceClient);
|
||||||
|
|
||||||
|
await awaitDecryptionError;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("Alice receives a megolm message before the session keys", async () => {
|
it("Alice receives a megolm message before the session keys", async () => {
|
||||||
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
|
||||||
await startClientAndAwaitFirstSync();
|
await startClientAndAwaitFirstSync();
|
||||||
|
@@ -43,6 +43,8 @@ ALICE_DATA = {
|
|||||||
"TEST_ROOM_ID": "!room:id",
|
"TEST_ROOM_ID": "!room:id",
|
||||||
# any 32-byte string can be an ed25519 private key.
|
# any 32-byte string can be an ed25519 private key.
|
||||||
"TEST_DEVICE_PRIVATE_KEY_BYTES": b"deadbeefdeadbeefdeadbeefdeadbeef",
|
"TEST_DEVICE_PRIVATE_KEY_BYTES": b"deadbeefdeadbeefdeadbeefdeadbeef",
|
||||||
|
# any 32-byte string can be an curve25519 private key.
|
||||||
|
"TEST_DEVICE_CURVE_PRIVATE_KEY_BYTES": b"deadmuledeadmuledeadmuledeadmule",
|
||||||
|
|
||||||
"MASTER_CROSS_SIGNING_PRIVATE_KEY_BYTES": b"doyouspeakwhaaaaaaaaaaaaaaaaaale",
|
"MASTER_CROSS_SIGNING_PRIVATE_KEY_BYTES": b"doyouspeakwhaaaaaaaaaaaaaaaaaale",
|
||||||
"USER_CROSS_SIGNING_PRIVATE_KEY_BYTES": b"useruseruseruseruseruseruseruser",
|
"USER_CROSS_SIGNING_PRIVATE_KEY_BYTES": b"useruseruseruseruseruseruseruser",
|
||||||
@@ -60,6 +62,8 @@ BOB_DATA = {
|
|||||||
"TEST_ROOM_ID": "!room:id",
|
"TEST_ROOM_ID": "!room:id",
|
||||||
# any 32-byte string can be an ed25519 private key.
|
# any 32-byte string can be an ed25519 private key.
|
||||||
"TEST_DEVICE_PRIVATE_KEY_BYTES": b"Deadbeefdeadbeefdeadbeefdeadbeef",
|
"TEST_DEVICE_PRIVATE_KEY_BYTES": b"Deadbeefdeadbeefdeadbeefdeadbeef",
|
||||||
|
# any 32-byte string can be an curve25519 private key.
|
||||||
|
"TEST_DEVICE_CURVE_PRIVATE_KEY_BYTES": b"Deadmuledeadmuledeadmuledeadmule",
|
||||||
|
|
||||||
"MASTER_CROSS_SIGNING_PRIVATE_KEY_BYTES": b"Doyouspeakwhaaaaaaaaaaaaaaaaaale",
|
"MASTER_CROSS_SIGNING_PRIVATE_KEY_BYTES": b"Doyouspeakwhaaaaaaaaaaaaaaaaaale",
|
||||||
"USER_CROSS_SIGNING_PRIVATE_KEY_BYTES": b"Useruseruseruseruseruseruseruser",
|
"USER_CROSS_SIGNING_PRIVATE_KEY_BYTES": b"Useruseruseruseruseruseruseruser",
|
||||||
@@ -80,7 +84,7 @@ def main() -> None:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {{ IDeviceKeys, IMegolmSessionData }} from "../../../src/@types/crypto";
|
import {{ IDeviceKeys, IMegolmSessionData }} from "../../../src/@types/crypto";
|
||||||
import {{ IDownloadKeyResult }} from "../../../src";
|
import {{ IDownloadKeyResult, IEvent }} from "../../../src";
|
||||||
import {{ KeyBackupSession, KeyBackupInfo }} from "../../../src/crypto-api/keybackup";
|
import {{ KeyBackupSession, KeyBackupInfo }} from "../../../src/crypto-api/keybackup";
|
||||||
|
|
||||||
/* eslint-disable comma-dangle */
|
/* eslint-disable comma-dangle */
|
||||||
@@ -102,6 +106,11 @@ def build_test_data(user_data, prefix = "") -> str:
|
|||||||
private_key = ed25519.Ed25519PrivateKey.from_private_bytes(
|
private_key = ed25519.Ed25519PrivateKey.from_private_bytes(
|
||||||
user_data["TEST_DEVICE_PRIVATE_KEY_BYTES"]
|
user_data["TEST_DEVICE_PRIVATE_KEY_BYTES"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
device_curve_key = x25519.X25519PrivateKey.from_private_bytes(
|
||||||
|
user_data["TEST_DEVICE_CURVE_PRIVATE_KEY_BYTES"]
|
||||||
|
)
|
||||||
|
|
||||||
b64_public_key = encode_base64(
|
b64_public_key = encode_base64(
|
||||||
private_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)
|
private_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)
|
||||||
)
|
)
|
||||||
@@ -169,9 +178,10 @@ def build_test_data(user_data, prefix = "") -> str:
|
|||||||
user_data["TEST_USER_ID"]: {f"ed25519:{user_data['TEST_DEVICE_ID']}": sig}
|
user_data["TEST_USER_ID"]: {f"ed25519:{user_data['TEST_DEVICE_ID']}": sig}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_of_exported_room_keys = [build_exported_megolm_key(), build_exported_megolm_key()]
|
set_of_exported_room_keys = [build_exported_megolm_key(device_curve_key)[0], build_exported_megolm_key(device_curve_key)[0]]
|
||||||
|
|
||||||
additional_exported_room_key = build_exported_megolm_key()
|
additional_exported_room_key, additional_exported_ed_key = build_exported_megolm_key(device_curve_key)
|
||||||
|
ratcheted_exported_room_key = symetric_ratchet_step_of_megolm_key(additional_exported_room_key, additional_exported_ed_key)
|
||||||
|
|
||||||
otk_to_sign = {
|
otk_to_sign = {
|
||||||
"key": user_data['OTK']
|
"key": user_data['OTK']
|
||||||
@@ -194,6 +204,8 @@ def build_test_data(user_data, prefix = "") -> str:
|
|||||||
|
|
||||||
backed_up_room_key = encrypt_megolm_key_for_backup(additional_exported_room_key, backup_decryption_key.public_key())
|
backed_up_room_key = encrypt_megolm_key_for_backup(additional_exported_room_key, backup_decryption_key.public_key())
|
||||||
|
|
||||||
|
clear_event, encrypted_event = generate_encrypted_event_content(additional_exported_room_key, additional_exported_ed_key, device_curve_key)
|
||||||
|
|
||||||
backup_recovery_key = export_recovery_key(user_data["B64_BACKUP_DECRYPTION_KEY"])
|
backup_recovery_key = export_recovery_key(user_data["B64_BACKUP_DECRYPTION_KEY"])
|
||||||
|
|
||||||
return f"""\
|
return f"""\
|
||||||
@@ -252,8 +264,19 @@ export const {prefix}MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
|||||||
json.dumps(additional_exported_room_key, indent=4)
|
json.dumps(additional_exported_room_key, indent=4)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A ratcheted version of {prefix}MEGOLM_SESSION_DATA */
|
||||||
|
export const {prefix}RATCHTED_MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
||||||
|
json.dumps(ratcheted_exported_room_key, indent=4)
|
||||||
|
};
|
||||||
|
|
||||||
/** The key from {prefix}MEGOLM_SESSION_DATA, encrypted for backup using `m.megolm_backup.v1.curve25519-aes-sha2` algorithm*/
|
/** The key from {prefix}MEGOLM_SESSION_DATA, encrypted for backup using `m.megolm_backup.v1.curve25519-aes-sha2` algorithm*/
|
||||||
export const {prefix}CURVE25519_KEY_BACKUP_DATA: KeyBackupSession = {json.dumps(backed_up_room_key, indent=4)};
|
export const {prefix}CURVE25519_KEY_BACKUP_DATA: KeyBackupSession = {json.dumps(backed_up_room_key, indent=4)};
|
||||||
|
|
||||||
|
/** A test clear event */
|
||||||
|
export const {prefix}CLEAR_EVENT: Partial<IEvent> = {json.dumps(clear_event, indent=4)};
|
||||||
|
|
||||||
|
/** The encrypted CLEAR_EVENT by MEGOLM_SESSION_DATA */
|
||||||
|
export const {prefix}ENCRYPTED_EVENT: Partial<IEvent> = {json.dumps(encrypted_event, indent=4)};
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@@ -350,10 +373,11 @@ def sign_json(json_object: dict, private_key: ed25519.Ed25519PrivateKey) -> str:
|
|||||||
|
|
||||||
return signature_base64
|
return signature_base64
|
||||||
|
|
||||||
def build_exported_megolm_key() -> dict:
|
def build_exported_megolm_key(device_curve_key: x25519.X25519PrivateKey) -> tuple[dict, ed25519.Ed25519PrivateKey]:
|
||||||
"""
|
"""
|
||||||
Creates an exported megolm room key, as per https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/megolm.md#session-export-format
|
Creates an exported megolm room key, as per https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/megolm.md#session-export-format
|
||||||
that can be imported via importRoomKeys API.
|
that can be imported via importRoomKeys API.
|
||||||
|
Returns the exported key, the matching privat edKey (needed to encrypt)
|
||||||
"""
|
"""
|
||||||
index = 0
|
index = 0
|
||||||
private_key = ed25519.Ed25519PrivateKey.from_private_bytes(randbytes(32))
|
private_key = ed25519.Ed25519PrivateKey.from_private_bytes(randbytes(32))
|
||||||
@@ -369,8 +393,10 @@ def build_exported_megolm_key() -> dict:
|
|||||||
|
|
||||||
megolm_export = {
|
megolm_export = {
|
||||||
"algorithm": "m.megolm.v1.aes-sha2",
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
"room_id": "!roomA:example.org",
|
"room_id": "!room:id",
|
||||||
"sender_key": "/Bu9e34hUClhddpf4E5gu5qEAdMY31+1A9HbiAeeQgo",
|
"sender_key": encode_base64(
|
||||||
|
device_curve_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)
|
||||||
|
),
|
||||||
"session_id": encode_base64(
|
"session_id": encode_base64(
|
||||||
private_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)
|
private_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)
|
||||||
),
|
),
|
||||||
@@ -381,6 +407,53 @@ def build_exported_megolm_key() -> dict:
|
|||||||
"forwarding_curve25519_key_chain": [],
|
"forwarding_curve25519_key_chain": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return megolm_export, private_key
|
||||||
|
|
||||||
|
def symetric_ratchet_step_of_megolm_key(previous: dict , megolm_private_key: ed25519.Ed25519PrivateKey) -> dict:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Very simple ratchet step from 0 to 1
|
||||||
|
Used to generate a ratcheted key to test unknown message index.
|
||||||
|
"""
|
||||||
|
session_key: str = previous["session_key"]
|
||||||
|
|
||||||
|
# Get the megolm R0 from the export format
|
||||||
|
decoded = base64.b64decode(session_key.encode("ascii"))
|
||||||
|
ri = decoded[5:133]
|
||||||
|
|
||||||
|
ri0 = ri[0:32]
|
||||||
|
ri1 = ri[32:64]
|
||||||
|
ri2 = ri[64:96]
|
||||||
|
ri3 = ri[96:128]
|
||||||
|
|
||||||
|
h = hmac.HMAC(ri3, hashes.SHA256())
|
||||||
|
h.update(b'x\03')
|
||||||
|
ri1_3 = h.finalize()
|
||||||
|
|
||||||
|
index = 1
|
||||||
|
private_key = megolm_private_key
|
||||||
|
|
||||||
|
# exported key, start with version byte
|
||||||
|
exported_key = bytearray(b'\x01')
|
||||||
|
exported_key += index.to_bytes(4, 'big')
|
||||||
|
exported_key += ri0
|
||||||
|
exported_key += ri1
|
||||||
|
exported_key += ri2
|
||||||
|
exported_key += ri1_3
|
||||||
|
# KPub
|
||||||
|
exported_key += private_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)
|
||||||
|
|
||||||
|
|
||||||
|
megolm_export = {
|
||||||
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
|
"room_id": "!room:id",
|
||||||
|
"sender_key": previous["sender_key"],
|
||||||
|
"session_id": previous["session_id"],
|
||||||
|
"session_key": encode_base64(exported_key),
|
||||||
|
"sender_claimed_keys": previous["sender_claimed_keys"],
|
||||||
|
"forwarding_curve25519_key_chain": [],
|
||||||
|
}
|
||||||
|
|
||||||
return megolm_export
|
return megolm_export
|
||||||
|
|
||||||
|
|
||||||
@@ -499,7 +572,7 @@ def generate_encrypted_event_content(exported_key: dict, ed_key: ed25519.Ed25519
|
|||||||
|
|
||||||
ct = encryptor.update(padded_data) + encryptor.finalize()
|
ct = encryptor.update(padded_data) + encryptor.finalize()
|
||||||
|
|
||||||
# The ratchet index i, and the cipher-text, are then packed
|
# The ratchet index i, and the cipher-text, are then packed
|
||||||
# into a message as described in Message format. Then the entire message
|
# into a message as described in Message format. Then the entire message
|
||||||
# (including the version bytes and all payload bytes) are passed through
|
# (including the version bytes and all payload bytes) are passed through
|
||||||
# HMAC-SHA-256. The first 8 bytes of the MAC are appended to the message.
|
# HMAC-SHA-256. The first 8 bytes of the MAC are appended to the message.
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { IDeviceKeys, IMegolmSessionData } from "../../../src/@types/crypto";
|
import { IDeviceKeys, IMegolmSessionData } from "../../../src/@types/crypto";
|
||||||
import { IDownloadKeyResult } from "../../../src";
|
import { IDownloadKeyResult, IEvent } from "../../../src";
|
||||||
import { KeyBackupSession, KeyBackupInfo } from "../../../src/crypto-api/keybackup";
|
import { KeyBackupSession, KeyBackupInfo } from "../../../src/crypto-api/keybackup";
|
||||||
|
|
||||||
/* eslint-disable comma-dangle */
|
/* eslint-disable comma-dangle */
|
||||||
@@ -142,8 +142,8 @@ export const SIGNED_BACKUP_DATA: KeyBackupInfo = {
|
|||||||
export const MEGOLM_SESSION_DATA_ARRAY: IMegolmSessionData[] = [
|
export const MEGOLM_SESSION_DATA_ARRAY: IMegolmSessionData[] = [
|
||||||
{
|
{
|
||||||
"algorithm": "m.megolm.v1.aes-sha2",
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
"room_id": "!roomA:example.org",
|
"room_id": "!room:id",
|
||||||
"sender_key": "/Bu9e34hUClhddpf4E5gu5qEAdMY31+1A9HbiAeeQgo",
|
"sender_key": "WimPd2udAU/1S/+YBpPbmr9L+0H5H+BnAVHSwDxlPGc",
|
||||||
"session_id": "FYOoKQSwe4d9jhTZ/LQCZFJINjPEqZ7Or4Z08reP92M",
|
"session_id": "FYOoKQSwe4d9jhTZ/LQCZFJINjPEqZ7Or4Z08reP92M",
|
||||||
"session_key": "AQAAAABZ0jXQOprFfXe41tIFmAtHxflJp4O2hM/vzQQpOazOCFeWSoW5P3Z9Q+voU3eXehMwyP8/hm/Q8xLP6/PmJdy+71se/17kdFwcDGgLxBWfa4ODM9zlI4EjKbNqmiii5loJ7rBhA/XXaw80m0hfU6zTDX/KrO55J0Pt4vJ0LDa3LBWDqCkEsHuHfY4U2fy0AmRSSDYzxKmezq+GdPK3j/dj",
|
"session_key": "AQAAAABZ0jXQOprFfXe41tIFmAtHxflJp4O2hM/vzQQpOazOCFeWSoW5P3Z9Q+voU3eXehMwyP8/hm/Q8xLP6/PmJdy+71se/17kdFwcDGgLxBWfa4ODM9zlI4EjKbNqmiii5loJ7rBhA/XXaw80m0hfU6zTDX/KrO55J0Pt4vJ0LDa3LBWDqCkEsHuHfY4U2fy0AmRSSDYzxKmezq+GdPK3j/dj",
|
||||||
"sender_claimed_keys": {
|
"sender_claimed_keys": {
|
||||||
@@ -153,8 +153,8 @@ export const MEGOLM_SESSION_DATA_ARRAY: IMegolmSessionData[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"algorithm": "m.megolm.v1.aes-sha2",
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
"room_id": "!roomA:example.org",
|
"room_id": "!room:id",
|
||||||
"sender_key": "/Bu9e34hUClhddpf4E5gu5qEAdMY31+1A9HbiAeeQgo",
|
"sender_key": "WimPd2udAU/1S/+YBpPbmr9L+0H5H+BnAVHSwDxlPGc",
|
||||||
"session_id": "mPYSGA2l1tOQiipEDEVYhDSdTSFh2lDW1qpGKYZRxTc",
|
"session_id": "mPYSGA2l1tOQiipEDEVYhDSdTSFh2lDW1qpGKYZRxTc",
|
||||||
"session_key": "AQAAAAAHwgkB49BTPAEGTCK6degxUIbl8GPG2ugPRYhNtOpNic63u11+baXFfjDw5fmVfD1gJXpQQjGsqrIYioxrB1xzl7mfb942UHhYdaMQZowpp1fSpJVsxR5TddUU2EWifYD9EQsoz8mY1zqoazm4vUP4v9yxaTcUBj2c6HMJCY0gCJj2EhgNpdbTkIoqRAxFWIQ0nU0hYdpQ1taqRimGUcU3",
|
"session_key": "AQAAAAAHwgkB49BTPAEGTCK6degxUIbl8GPG2ugPRYhNtOpNic63u11+baXFfjDw5fmVfD1gJXpQQjGsqrIYioxrB1xzl7mfb942UHhYdaMQZowpp1fSpJVsxR5TddUU2EWifYD9EQsoz8mY1zqoazm4vUP4v9yxaTcUBj2c6HMJCY0gCJj2EhgNpdbTkIoqRAxFWIQ0nU0hYdpQ1taqRimGUcU3",
|
||||||
"sender_claimed_keys": {
|
"sender_claimed_keys": {
|
||||||
@@ -167,8 +167,8 @@ export const MEGOLM_SESSION_DATA_ARRAY: IMegolmSessionData[] = [
|
|||||||
/** An exported megolm session */
|
/** An exported megolm session */
|
||||||
export const MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
export const MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
||||||
"algorithm": "m.megolm.v1.aes-sha2",
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
"room_id": "!roomA:example.org",
|
"room_id": "!room:id",
|
||||||
"sender_key": "/Bu9e34hUClhddpf4E5gu5qEAdMY31+1A9HbiAeeQgo",
|
"sender_key": "WimPd2udAU/1S/+YBpPbmr9L+0H5H+BnAVHSwDxlPGc",
|
||||||
"session_id": "ipdI6Zs/7DzFTEhiA2iGaMDfHkIYCleqXT6L+5e1/co",
|
"session_id": "ipdI6Zs/7DzFTEhiA2iGaMDfHkIYCleqXT6L+5e1/co",
|
||||||
"session_key": "AQAAAABXGO+Z9jlQJhIL6ByhXrv2BwCIxkhh7MXpKLsYmXkJcWrQlirmXmD79ga1zo+I4DCtEZzyGSpDWXBC6G7ez3H4gDMBam1RE3Jm5tc+oTlIri32UkYgSL0kBkcEnttqmIXBlK8tAfJo3cJnlh7F4ltEOAqrdME6dU0zXTkqXmURqYqXSOmbP+w8xUxIYgNohmjA3x5CGApXql0+i/uXtf3K",
|
"session_key": "AQAAAABXGO+Z9jlQJhIL6ByhXrv2BwCIxkhh7MXpKLsYmXkJcWrQlirmXmD79ga1zo+I4DCtEZzyGSpDWXBC6G7ez3H4gDMBam1RE3Jm5tc+oTlIri32UkYgSL0kBkcEnttqmIXBlK8tAfJo3cJnlh7F4ltEOAqrdME6dU0zXTkqXmURqYqXSOmbP+w8xUxIYgNohmjA3x5CGApXql0+i/uXtf3K",
|
||||||
"sender_claimed_keys": {
|
"sender_claimed_keys": {
|
||||||
@@ -177,18 +177,58 @@ export const MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
|||||||
"forwarding_curve25519_key_chain": []
|
"forwarding_curve25519_key_chain": []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A ratcheted version of MEGOLM_SESSION_DATA */
|
||||||
|
export const RATCHTED_MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
||||||
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
|
"room_id": "!room:id",
|
||||||
|
"sender_key": "WimPd2udAU/1S/+YBpPbmr9L+0H5H+BnAVHSwDxlPGc",
|
||||||
|
"session_id": "ipdI6Zs/7DzFTEhiA2iGaMDfHkIYCleqXT6L+5e1/co",
|
||||||
|
"session_key": "AQAAAAFXGO+Z9jlQJhIL6ByhXrv2BwCIxkhh7MXpKLsYmXkJcWrQlirmXmD79ga1zo+I4DCtEZzyGSpDWXBC6G7ez3H4gDMBam1RE3Jm5tc+oTlIri32UkYgSL0kBkcEnttqmIUWvpwC7by/yg231+gyzu9lDHAU4ivCj48pt7WGiORWmIqXSOmbP+w8xUxIYgNohmjA3x5CGApXql0+i/uXtf3K",
|
||||||
|
"sender_claimed_keys": {
|
||||||
|
"ed25519": "Bhbpt6hqMZlSH4sJV7xiEEEiPVeTWz4Vkujl1EMdIPI"
|
||||||
|
},
|
||||||
|
"forwarding_curve25519_key_chain": []
|
||||||
|
};
|
||||||
|
|
||||||
/** The key from MEGOLM_SESSION_DATA, encrypted for backup using `m.megolm_backup.v1.curve25519-aes-sha2` algorithm*/
|
/** The key from MEGOLM_SESSION_DATA, encrypted for backup using `m.megolm_backup.v1.curve25519-aes-sha2` algorithm*/
|
||||||
export const CURVE25519_KEY_BACKUP_DATA: KeyBackupSession = {
|
export const CURVE25519_KEY_BACKUP_DATA: KeyBackupSession = {
|
||||||
"first_message_index": 1,
|
"first_message_index": 1,
|
||||||
"forwarded_count": 0,
|
"forwarded_count": 0,
|
||||||
"is_verified": false,
|
"is_verified": false,
|
||||||
"session_data": {
|
"session_data": {
|
||||||
"ciphertext": "r6HRk2/Im2yJe5cLP8R81aVjFWjYWPHpw7TVxphiSK1cdIDZTTK57r6MfU+0i/mTPn+/PosT74OvYwCnehy2d1BPGxhDl8AhPcBu3//KzlqinE6iAfrQYHmoOTes2uOsHgvbE7M9bIyAE1/FxzIgZuzmbJ1Fp/qjgKeTeonuMujLpnezUOYzDYqbF8hyLdm+SkrVWISde/wmVfpl1TI56ItCKmz0uB4fjUMWUV0sgp+3JLAUIqIqmwb7VVZooox94ze2VuspJMu9mF6MoQs5BEk3bFi9nbdgGwGh0pFYjEwE62+xLjo9x/gdVkIy8xlBmCFjBdvWjBjtvc8NfboWKxZ1tmpPCt6IiCTwOY4kyQdmK6U+sjh3tvs7qLOX5ETThOAqwKsY9VeXbeCtWF2h/m6ZXFQpxsf/vLgpTe0djDsGpWgLY+dywAelfz6O69EiHAxti9XxEGO0WLBDs0rmyhPN03IeLa+b8Gp2RMRdJ4prjKr0m7CVTUXEHbw6LtN0SWvEnc6iBI0vCEs1EocJAFfXsiwzAAgPDmaaDrCEk1dOoYj2eXoy4tbJx3+/FXFKe+RVdmiuv1nsVAQxPq78Tx6UtIz7ihHI0tzaZV+/7PUY065b6kevDBST+SZWERwqFZdz28TWsHu6Kxjr5k2N4sahs8a4frobip6C7PhXJFiq3n7lMx1IjfRrN0HxzpMqBzhkmiat9JR6nWtGjvOvvw",
|
"ciphertext": "r6HRk2/Im2yJe5cLP8R81aVjFWjYWPHpw7TVxphiSK1cdIDZTTK57r6MfU+0i/mTPn+/PosT74OvYwCnehy2d1BPGxhDl8AhPcBu3//Kzlq2o5CssPsw+88gRehkAsPg9Zp5G9sL9to6giltvTWTbsaQpmvv3HLmBOYSFIxvyZrOT/Ffqu325f0IEsKcyV2BdIkw8Ob9Xt+VWoe4MYEGG6y1T8W125zeFgKWI4Ow76uput64H9zZjIo+Cc+hCTO9Ea4EnosSjizCotevkNck7C/zGgfhBikiohROb6SbaZgxicSsEDZ+f7brnri9yP3iXS3PMDHHpa1+XzG2VOG/Y9OQZpkPq+pbLrCC+NWJeJPslDAK5i+RURwzjnPmaHKCRHTq86CwhFyiCDf61MGwCY3xjrmBJg44BCdxWqCx0YJvwsvVqqnl4vTieUfrwThNPsQ81aVkDHvlmrgrTt8icDa8jTJhu34jem+pbRSEM5aJikV4B+zYiLz+dH/v6UpYA2eG8ReOvwpPXp6CAcIlplRPpWbMBeLFVcPkT4KAXTp9exFpB4on4pf8OsaDomlt4qAA0rhAZmhPWPKcU/A0Tz4gyMu54OivVtw1SPj+5Iq+YDQ8jB6Po3ApzMf6fwF9x/FjevbboFB05X2Jr0NrbFqXMOUwXHMgDAGiIWX8+gkmmbaiNWqg2etjN94pobQSGZelb18XGN7kuwMk+Zwk7A",
|
||||||
"ephemeral": "q+P1WdRtEiPIEtNuuGrRcueZxUbLnSKdsuTAkxewXgU",
|
"ephemeral": "q+P1WdRtEiPIEtNuuGrRcueZxUbLnSKdsuTAkxewXgU",
|
||||||
"mac": "OibmACbORhI"
|
"mac": "OibmACbORhI"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A test clear event */
|
||||||
|
export const CLEAR_EVENT: Partial<IEvent> = {
|
||||||
|
"type": "m.room.message",
|
||||||
|
"room_id": "!room:id",
|
||||||
|
"sender": "@alice:localhost",
|
||||||
|
"content": {
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": "Hello world"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The encrypted CLEAR_EVENT by MEGOLM_SESSION_DATA */
|
||||||
|
export const ENCRYPTED_EVENT: Partial<IEvent> = {
|
||||||
|
"type": "m.room.encrypted",
|
||||||
|
"room_id": "!room:id",
|
||||||
|
"sender": "@alice:localhost",
|
||||||
|
"content": {
|
||||||
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
|
"sender_key": "WimPd2udAU/1S/+YBpPbmr9L+0H5H+BnAVHSwDxlPGc",
|
||||||
|
"ciphertext": "AwgAEnAkBmciEAyhh1j6DCk29UXJ7kv/kvayUNfuNT0iAioLxcXjFXOZ5ho3jF1/wrytlt0Lb298uMM67OxdVMi+/mMfYpwlvi07P9cIH6CMSj8tyhYoWl0SrKY6tkPf5GWOlRSRRKbziXa96FHXvnA3V2FCAIGtAe3G4ei5RPbhkmKAFBLAen33/D6MjJVqU8Ojr5vTkgls5eyirarlVpsmnH06alDaxO8avrU0NL+Vsw26xvlUQgEMOnUJ",
|
||||||
|
"session_id": "ipdI6Zs/7DzFTEhiA2iGaMDfHkIYCleqXT6L+5e1/co",
|
||||||
|
"device_id": "TEST_DEVICE"
|
||||||
|
},
|
||||||
|
"event_id": "$event1",
|
||||||
|
"origin_server_ts": 1507753886000
|
||||||
|
};
|
||||||
|
|
||||||
// Bob data
|
// Bob data
|
||||||
|
|
||||||
export const BOB_TEST_USER_ID = "@bob:xyz";
|
export const BOB_TEST_USER_ID = "@bob:xyz";
|
||||||
@@ -322,8 +362,8 @@ export const BOB_SIGNED_BACKUP_DATA: KeyBackupInfo = {
|
|||||||
export const BOB_MEGOLM_SESSION_DATA_ARRAY: IMegolmSessionData[] = [
|
export const BOB_MEGOLM_SESSION_DATA_ARRAY: IMegolmSessionData[] = [
|
||||||
{
|
{
|
||||||
"algorithm": "m.megolm.v1.aes-sha2",
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
"room_id": "!roomA:example.org",
|
"room_id": "!room:id",
|
||||||
"sender_key": "/Bu9e34hUClhddpf4E5gu5qEAdMY31+1A9HbiAeeQgo",
|
"sender_key": "FOvlmz18LLI3k/llCpqRoKT90+gFF8YhuL+v1YBXHlw",
|
||||||
"session_id": "/2K+V777vipCxPZ0gpY9qcpz1DYaXwuMRIu0UEP0Wa0",
|
"session_id": "/2K+V777vipCxPZ0gpY9qcpz1DYaXwuMRIu0UEP0Wa0",
|
||||||
"session_key": "AQAAAAAclzWVMeWBKH+B/WMowa3rb4ma3jEl6n5W4GCs9ue65CruzD3ihX+85pZ9hsV9Bf6fvhjp76WNRajoJYX0UIt7aosjmu0i+H+07hEQ0zqTKpVoSH0ykJ6stAMhdr6Q4uW5crBmdTTBIsqmoWsNJZKKoE2+ldYrZ1lrFeaJbjBIY/9ivle++74qQsT2dIKWPanKc9Q2Gl8LjESLtFBD9Fmt",
|
"session_key": "AQAAAAAclzWVMeWBKH+B/WMowa3rb4ma3jEl6n5W4GCs9ue65CruzD3ihX+85pZ9hsV9Bf6fvhjp76WNRajoJYX0UIt7aosjmu0i+H+07hEQ0zqTKpVoSH0ykJ6stAMhdr6Q4uW5crBmdTTBIsqmoWsNJZKKoE2+ldYrZ1lrFeaJbjBIY/9ivle++74qQsT2dIKWPanKc9Q2Gl8LjESLtFBD9Fmt",
|
||||||
"sender_claimed_keys": {
|
"sender_claimed_keys": {
|
||||||
@@ -333,8 +373,8 @@ export const BOB_MEGOLM_SESSION_DATA_ARRAY: IMegolmSessionData[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"algorithm": "m.megolm.v1.aes-sha2",
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
"room_id": "!roomA:example.org",
|
"room_id": "!room:id",
|
||||||
"sender_key": "/Bu9e34hUClhddpf4E5gu5qEAdMY31+1A9HbiAeeQgo",
|
"sender_key": "FOvlmz18LLI3k/llCpqRoKT90+gFF8YhuL+v1YBXHlw",
|
||||||
"session_id": "+07YOpSgdZ1X9le3n3NMByw0V1B0H0Djnbm76jgmWoo",
|
"session_id": "+07YOpSgdZ1X9le3n3NMByw0V1B0H0Djnbm76jgmWoo",
|
||||||
"session_key": "AQAAAAAjWfIMo9+BWS8IvhfsQuomxXXXGy11tJs0ej505xxd1RzOIP4ftq3MbZYsfH8kqSMBc2l1Ym2u3Dksv2/nR0zGQeNIgOxeMuwHU3Ry7+DdV1I96blPylVCCn/f5RAy6smKoaeylptPdXgVXmw3YBBUVYpHpm+xCIUUp9foAdb8hftO2DqUoHWdV/ZXt59zTAcsNFdQdB9A4525u+o4JlqK",
|
"session_key": "AQAAAAAjWfIMo9+BWS8IvhfsQuomxXXXGy11tJs0ej505xxd1RzOIP4ftq3MbZYsfH8kqSMBc2l1Ym2u3Dksv2/nR0zGQeNIgOxeMuwHU3Ry7+DdV1I96blPylVCCn/f5RAy6smKoaeylptPdXgVXmw3YBBUVYpHpm+xCIUUp9foAdb8hftO2DqUoHWdV/ZXt59zTAcsNFdQdB9A4525u+o4JlqK",
|
||||||
"sender_claimed_keys": {
|
"sender_claimed_keys": {
|
||||||
@@ -347,8 +387,8 @@ export const BOB_MEGOLM_SESSION_DATA_ARRAY: IMegolmSessionData[] = [
|
|||||||
/** An exported megolm session */
|
/** An exported megolm session */
|
||||||
export const BOB_MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
export const BOB_MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
||||||
"algorithm": "m.megolm.v1.aes-sha2",
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
"room_id": "!roomA:example.org",
|
"room_id": "!room:id",
|
||||||
"sender_key": "/Bu9e34hUClhddpf4E5gu5qEAdMY31+1A9HbiAeeQgo",
|
"sender_key": "FOvlmz18LLI3k/llCpqRoKT90+gFF8YhuL+v1YBXHlw",
|
||||||
"session_id": "gywydBrIJcJWktC/ic3tunKZM1XZm1MpYiYtdbj8Rpc",
|
"session_id": "gywydBrIJcJWktC/ic3tunKZM1XZm1MpYiYtdbj8Rpc",
|
||||||
"session_key": "AQAAAADZJL7OdM/KHfPzXPZ3CtlLBIlzbwk06dnZTd3bvkcdP5u73rdmThBKdqGA4xzCyxZsHdYLZRrlmD3VwOmNfvWMqYdPxA1X0vs3d172y9EIG8i+N/skJxTRypcVSV9XoinBNIWr/gkyepuAKiQqemlc8J5amD9OkmbVkmnrxP1uyYMsMnQayCXCVpLQv4nN7bpymTNV2ZtTKWImLXW4/EaX",
|
"session_key": "AQAAAADZJL7OdM/KHfPzXPZ3CtlLBIlzbwk06dnZTd3bvkcdP5u73rdmThBKdqGA4xzCyxZsHdYLZRrlmD3VwOmNfvWMqYdPxA1X0vs3d172y9EIG8i+N/skJxTRypcVSV9XoinBNIWr/gkyepuAKiQqemlc8J5amD9OkmbVkmnrxP1uyYMsMnQayCXCVpLQv4nN7bpymTNV2ZtTKWImLXW4/EaX",
|
||||||
"sender_claimed_keys": {
|
"sender_claimed_keys": {
|
||||||
@@ -357,15 +397,55 @@ export const BOB_MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
|||||||
"forwarding_curve25519_key_chain": []
|
"forwarding_curve25519_key_chain": []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A ratcheted version of BOB_MEGOLM_SESSION_DATA */
|
||||||
|
export const BOB_RATCHTED_MEGOLM_SESSION_DATA: IMegolmSessionData = {
|
||||||
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
|
"room_id": "!room:id",
|
||||||
|
"sender_key": "FOvlmz18LLI3k/llCpqRoKT90+gFF8YhuL+v1YBXHlw",
|
||||||
|
"session_id": "gywydBrIJcJWktC/ic3tunKZM1XZm1MpYiYtdbj8Rpc",
|
||||||
|
"session_key": "AQAAAAHZJL7OdM/KHfPzXPZ3CtlLBIlzbwk06dnZTd3bvkcdP5u73rdmThBKdqGA4xzCyxZsHdYLZRrlmD3VwOmNfvWMqYdPxA1X0vs3d172y9EIG8i+N/skJxTRypcVSV9Xoil2JdGx9oPqR0dFVh661Aqs86rJRbQ4IeRiuEm35VMxboMsMnQayCXCVpLQv4nN7bpymTNV2ZtTKWImLXW4/EaX",
|
||||||
|
"sender_claimed_keys": {
|
||||||
|
"ed25519": "zBdpQwWYyz1MkZuEUhXqcdMfUNN/B9psLFDDDTJOg64"
|
||||||
|
},
|
||||||
|
"forwarding_curve25519_key_chain": []
|
||||||
|
};
|
||||||
|
|
||||||
/** The key from BOB_MEGOLM_SESSION_DATA, encrypted for backup using `m.megolm_backup.v1.curve25519-aes-sha2` algorithm*/
|
/** The key from BOB_MEGOLM_SESSION_DATA, encrypted for backup using `m.megolm_backup.v1.curve25519-aes-sha2` algorithm*/
|
||||||
export const BOB_CURVE25519_KEY_BACKUP_DATA: KeyBackupSession = {
|
export const BOB_CURVE25519_KEY_BACKUP_DATA: KeyBackupSession = {
|
||||||
"first_message_index": 1,
|
"first_message_index": 1,
|
||||||
"forwarded_count": 0,
|
"forwarded_count": 0,
|
||||||
"is_verified": false,
|
"is_verified": false,
|
||||||
"session_data": {
|
"session_data": {
|
||||||
"ciphertext": "d7UVOK17WEVky/8hK0h3HsTQrFMEbKbfqMcl2KtyTWcI9S5gGFWK9Git5BzVRxRggvxQ0c8PDfqL+dr3zHytAMW+71BJqIPQW910vV7SX3JkR91kuuiDqlFT1VHLMP9/MNsvCfeZz1Q+0/LqkJo1KTbrrjKxqOq5/e7RQequOEXHu0a658fKaK/tk0eLvO2xUTxxBCgtuuLpeysOykf4jqp3yV89+h+h3o4zsWGyA2cLIBC/9ofqiqsoF+l1smzA+sQ3ArLBM5B2wc7b4Ir7jZUzCpnOK6O6nQA3vwOpwy3AqpeCKbsuXBPLkb9QXnVH9UzNbuL1Go7M6S3zH2BlAQrUhKSj4yI9tQC3XL3Y3IuAJRUX2bIXzYn9DryL+zwz9aULGN1ECZ4pMHm9jlPUYgMDYmSA2rRCZPWXcSeqmV8aB2qR3k+gcCFXNGbKy73bdN87GsPsYPI7RCkgtHGyW2tpz0JpP1CQmtP3wXNBKIJKIgcxGQ3YDehGV7XlFDDUYBZyYGazXqU/fdt21gc4Jvg1xVKsj83woVmGDo+2WzPrpIJ79NJUovC8jJ+UA3QamY28Df6UaRuS3+vvgCCW9e3T5+h5hR7BQayZ9r9Ykv7h7NTxQYjsYwxfZK+OULJPFNYbcB+vc6msLAsqocPhNQTazOe4TfsSAAuaHa/2FfGGMyaWCQY5DI3tk3Pagr87L8lBhwXll9usXKslvc+sJw",
|
"ciphertext": "d7UVOK17WEVky/8hK0h3HsTQrFMEbKbfqMcl2KtyTWcI9S5gGFWK9Git5BzVRxRggvxQ0c8PDfqL+dr3zHytAMW+71BJqIPQW910vV7SX3IcGylnoUcS3doVkJZiprXytXMP89AKcgv5Dj7mS2ZdvNGE+Atro74bzZ5yot5BrE0ZE5SjoUBPLaLMMu9HopLIV+qx01Rc3F0wmkocSPo51N0nv6wvO5Cst0FiOGHDK6r1pFlgDEJLmBkOyC4e8oMVbKTJzsSQVbJ8tJ37xuhI+T5P0ZlmiqKDqYRp8uh50w+txLEixYhEUunFgCTt1DAmiS9pLNYhLyl1ggwuQjzZe+AV6timbRxNJy18/AEcPomJw7z/pxYIiNLHRKOC13Wp8kGWx9cOgfMQ5KmBuLS8psGiLTBkfWPLOfNYqjbeqAR+OGZQoS6hUjbBYU7QuFa4FOYBHkNB2UqNsdsMb9qB/qs7QGTSb8Lok5YjW1c81BUpmIyKvuqnKma0MZskrpTYGQD2eJDABFCZwLFm+LgDyUTeSiV5xguYztLrHOk8LHKo9M8dIZgoBjeFVJxyjbcXKsVS3aQkMXKCrRlKLqhZTws/ZJwVfW9DbktZ9dT+tRZQvI7tjJofojcLX61AGJDnqUf5+2Gv1tEnmUI953gIzc8NlcFabPOsDsZEODt7MdOCTPT3w29umyhKbCsslpb64LoS/AB2QRPRCgkJS7snRA",
|
||||||
"ephemeral": "oO0VX84OUIzm2i/12zAhTWOZT5IFRH5mXaKZ8fXkCgU",
|
"ephemeral": "oO0VX84OUIzm2i/12zAhTWOZT5IFRH5mXaKZ8fXkCgU",
|
||||||
"mac": "lEfHlqfJQwU"
|
"mac": "lEfHlqfJQwU"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A test clear event */
|
||||||
|
export const BOB_CLEAR_EVENT: Partial<IEvent> = {
|
||||||
|
"type": "m.room.message",
|
||||||
|
"room_id": "!room:id",
|
||||||
|
"sender": "@alice:localhost",
|
||||||
|
"content": {
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": "Hello world"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The encrypted CLEAR_EVENT by MEGOLM_SESSION_DATA */
|
||||||
|
export const BOB_ENCRYPTED_EVENT: Partial<IEvent> = {
|
||||||
|
"type": "m.room.encrypted",
|
||||||
|
"room_id": "!room:id",
|
||||||
|
"sender": "@alice:localhost",
|
||||||
|
"content": {
|
||||||
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
|
"sender_key": "FOvlmz18LLI3k/llCpqRoKT90+gFF8YhuL+v1YBXHlw",
|
||||||
|
"ciphertext": "AwgAEnA/mEqZm2lSrhoG11OpDqsohGSBJWsudbuoItLlivmpFZQHrKMbE6z/dhCTwUi76vwfRCtf4tyPMD845cqZH1nL0bowq3/awyzZ8Q263Y3WrLfkUTFBU6oPF/IULUFZZuw6kLdfd5g5+uigvqUhFFpICoj7KNHznv4sFNssd00/WgJquZ6PRt6e1v6ANFNiZPAwghIL+kBc6pb8i6MUWt9JnXilJhTqFDHdXiY4qkaKBWbwebC26PYM",
|
||||||
|
"session_id": "gywydBrIJcJWktC/ic3tunKZM1XZm1MpYiYtdbj8Rpc",
|
||||||
|
"device_id": "TEST_DEVICE"
|
||||||
|
},
|
||||||
|
"event_id": "$event1",
|
||||||
|
"origin_server_ts": 1507753886000
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -69,6 +69,7 @@ import { randomString } from "../randomstring";
|
|||||||
import { ClientStoppedError } from "../errors";
|
import { ClientStoppedError } from "../errors";
|
||||||
import { ISignatures } from "../@types/signed";
|
import { ISignatures } from "../@types/signed";
|
||||||
import { encodeBase64 } from "../common-crypto/base64";
|
import { encodeBase64 } from "../common-crypto/base64";
|
||||||
|
import { DecryptionError } from "../crypto/algorithms";
|
||||||
|
|
||||||
const ALL_VERIFICATION_METHODS = ["m.sas.v1", "m.qr_code.scan.v1", "m.qr_code.show.v1", "m.reciprocate.v1"];
|
const ALL_VERIFICATION_METHODS = ["m.sas.v1", "m.qr_code.scan.v1", "m.qr_code.show.v1", "m.reciprocate.v1"];
|
||||||
|
|
||||||
@@ -1392,6 +1393,7 @@ class EventDecryptor {
|
|||||||
// (fixes https://github.com/vector-im/element-web/issues/5001)
|
// (fixes https://github.com/vector-im/element-web/issues/5001)
|
||||||
this.addEventToPendingList(event);
|
this.addEventToPendingList(event);
|
||||||
|
|
||||||
|
try {
|
||||||
const res = (await this.olmMachine.decryptRoomEvent(
|
const res = (await this.olmMachine.decryptRoomEvent(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
event_id: event.getId(),
|
event_id: event.getId(),
|
||||||
@@ -1414,6 +1416,46 @@ class EventDecryptor {
|
|||||||
senderCurve25519Key: res.senderCurve25519Key,
|
senderCurve25519Key: res.senderCurve25519Key,
|
||||||
forwardingCurve25519KeyChain: res.forwardingCurve25519KeyChain,
|
forwardingCurve25519KeyChain: res.forwardingCurve25519KeyChain,
|
||||||
};
|
};
|
||||||
|
} catch (err) {
|
||||||
|
// We need to map back to regular decryption errors (used for analytics for example)
|
||||||
|
// The DecryptionErrors are used by react-sdk so is implicitly part of API, but poorly typed
|
||||||
|
if (err instanceof RustSdkCryptoJs.MegolmDecryptionError) {
|
||||||
|
const content = event.getWireContent();
|
||||||
|
let jsError;
|
||||||
|
switch (err.code) {
|
||||||
|
case RustSdkCryptoJs.DecryptionErrorCode.MissingRoomKey: {
|
||||||
|
jsError = new DecryptionError(
|
||||||
|
"MEGOLM_UNKNOWN_INBOUND_SESSION_ID",
|
||||||
|
"The sender's device has not sent us the keys for this message.",
|
||||||
|
{
|
||||||
|
session: content.sender_key + "|" + content.session_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RustSdkCryptoJs.DecryptionErrorCode.UnknownMessageIndex: {
|
||||||
|
jsError = new DecryptionError(
|
||||||
|
"OLM_UNKNOWN_MESSAGE_INDEX",
|
||||||
|
"The sender's device has not sent us the keys for this message at this index.",
|
||||||
|
{
|
||||||
|
session: content.sender_key + "|" + content.session_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// We don't map MismatchedIdentityKeys for now, as there is no equivalent in legacy.
|
||||||
|
// Just put it on the `UNABLE_TO_DECRYPT` bucket.
|
||||||
|
default: {
|
||||||
|
jsError = new DecryptionError("UNABLE_TO_DECRYPT", err.description, {
|
||||||
|
session: content.sender_key + "|" + content.session_id,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw jsError;
|
||||||
|
}
|
||||||
|
throw new DecryptionError("UNABLE_TO_DECRYPT", "Unknown error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user