fix: Decrypt last message on received megolm key

This commit is contained in:
Sorunome 2020-10-23 16:25:15 +02:00 committed by Christian Pauly
parent ad0192e8e1
commit 343c26b3ed
6 changed files with 73 additions and 6 deletions

View file

@ -238,6 +238,9 @@ class Encryption {
{bool store = false,
EventUpdateType updateType = EventUpdateType.timeline}) async {
final doStore = () async {
if (updateType != EventUpdateType.history) {
event.room?.setState(event);
}
await client.database?.storeEventUpdate(
client.id,
EventUpdate(
@ -248,9 +251,6 @@ class Encryption {
sortOrder: event.sortOrder,
),
);
if (updateType != EventUpdateType.history) {
event.room?.setState(event);
}
};
if (event.type != EventTypes.Encrypted) {
return event;

View file

@ -150,9 +150,14 @@ class KeyManager {
.markInboundGroupSessionAsUploaded(client.id, roomId, sessionId);
}
});
// TODO: somehow try to decrypt last message again
final room = client.getRoomById(roomId);
if (room != null) {
// attempt to decrypt the last event
final event = room.getState(EventTypes.Encrypted);
if (event != null && event.content['session_id'] == sessionId) {
encryption.decryptRoomEvent(roomId, event, store: true);
}
// and finally broadcast the new session
room.onSessionKeyReceived.add(sessionId);
}
}

View file

@ -272,7 +272,15 @@ class Room {
var lastEvent = lastEvents.isEmpty
? null
: lastEvents.reduce((a, b) => a.sortOrder > b.sortOrder ? a : b);
: lastEvents.reduce((a, b) {
if (a.sortOrder == b.sortOrder) {
// if two events have the same sort order we want to give encrypted events a lower priority
// This is so that if the same event exists in the state both encrypted *and* unencrypted,
// the unencrypted one is picked
return a.type == EventTypes.Encrypted ? b : a;
}
return a.sortOrder > b.sortOrder ? a : b;
});
if (lastEvent == null) {
states.forEach((final String key, final entry) {
if (!entry.containsKey('')) return;

View file

@ -118,7 +118,6 @@ class Timeline {
for (var i = 0; i < events.length; i++) {
if (events[i].type == EventTypes.Encrypted &&
events[i].messageType == MessageTypes.BadEncrypted &&
events[i].content['can_request_session'] == true &&
events[i].content['session_id'] == sessionId) {
events[i] = await room.client.encryption
.decryptRoomEvent(room.id, events[i], store: true);

View file

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'dart:convert';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:famedlysdk/src/utils/logs.dart';
import 'package:test/test.dart';
@ -249,6 +251,30 @@ void main() {
final senderKey = client.identityKey;
final roomId = '!someroom:example.org';
final sessionId = inbound.session_id();
final room = Room(id: roomId, client: client);
client.rooms.add(room);
// we build up an encrypted message so that we can test if it successfully decrypted afterwards
room.states['m.room.encrypted'] = Event(
senderId: '@test:example.com',
type: 'm.room.encrypted',
roomId: room.id,
room: room,
eventId: '12345',
originServerTs: DateTime.now(),
content: {
'algorithm': 'm.megolm.v1.aes-sha2',
'ciphertext': session.encrypt(json.encode({
'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'foxies'},
})),
'device_id': client.deviceID,
'sender_key': client.identityKey,
'session_id': sessionId,
},
stateKey: '',
sortOrder: 42.0,
);
expect(room.lastEvent.type, 'm.room.encrypted');
// set a payload...
var sessionPayload = <String, dynamic>{
'algorithm': 'm.megolm.v1.aes-sha2',
@ -379,6 +405,10 @@ void main() {
.length,
0);
// test that it decrypted the last event
expect(room.lastEvent.type, 'm.room.message');
expect(room.lastEvent.content['body'], 'foxies');
inbound.free();
session.free();
});

View file

@ -179,6 +179,31 @@ void main() {
expect(room.timeCreated, room.lastEvent.originServerTs);
});
test('multiple last event with same sort order', () {
room.states['m.room.encrypted'] = Event(
senderId: '@test:example.com',
type: 'm.room.encrypted',
roomId: room.id,
room: room,
eventId: '12345',
originServerTs: DateTime.now(),
content: {'msgtype': 'm.text', 'body': 'test'},
stateKey: '',
sortOrder: 42.0);
expect(room.lastEvent.type, 'm.room.encrypted');
room.states['m.room.messge'] = Event(
senderId: '@test:example.com',
type: 'm.room.messge',
roomId: room.id,
room: room,
eventId: '12345',
originServerTs: DateTime.now(),
content: {'msgtype': 'm.text', 'body': 'test'},
stateKey: '',
sortOrder: 42.0);
expect(room.lastEvent.type, 'm.room.encrypted');
});
test('sendReadReceipt', () async {
await room.sendReadReceipt('§1234:fakeServer.notExisting');
});