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

View file

@ -150,9 +150,14 @@ class KeyManager {
.markInboundGroupSessionAsUploaded(client.id, roomId, sessionId); .markInboundGroupSessionAsUploaded(client.id, roomId, sessionId);
} }
}); });
// TODO: somehow try to decrypt last message again
final room = client.getRoomById(roomId); final room = client.getRoomById(roomId);
if (room != null) { 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); room.onSessionKeyReceived.add(sessionId);
} }
} }

View file

@ -272,7 +272,15 @@ class Room {
var lastEvent = lastEvents.isEmpty var lastEvent = lastEvents.isEmpty
? null ? 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) { if (lastEvent == null) {
states.forEach((final String key, final entry) { states.forEach((final String key, final entry) {
if (!entry.containsKey('')) return; if (!entry.containsKey('')) return;

View file

@ -118,7 +118,6 @@ class Timeline {
for (var i = 0; i < events.length; i++) { for (var i = 0; i < events.length; i++) {
if (events[i].type == EventTypes.Encrypted && if (events[i].type == EventTypes.Encrypted &&
events[i].messageType == MessageTypes.BadEncrypted && events[i].messageType == MessageTypes.BadEncrypted &&
events[i].content['can_request_session'] == true &&
events[i].content['session_id'] == sessionId) { events[i].content['session_id'] == sessionId) {
events[i] = await room.client.encryption events[i] = await room.client.encryption
.decryptRoomEvent(room.id, events[i], store: true); .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/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import 'dart:convert';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:famedlysdk/src/utils/logs.dart'; import 'package:famedlysdk/src/utils/logs.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
@ -249,6 +251,30 @@ void main() {
final senderKey = client.identityKey; final senderKey = client.identityKey;
final roomId = '!someroom:example.org'; final roomId = '!someroom:example.org';
final sessionId = inbound.session_id(); 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... // set a payload...
var sessionPayload = <String, dynamic>{ var sessionPayload = <String, dynamic>{
'algorithm': 'm.megolm.v1.aes-sha2', 'algorithm': 'm.megolm.v1.aes-sha2',
@ -379,6 +405,10 @@ void main() {
.length, .length,
0); 0);
// test that it decrypted the last event
expect(room.lastEvent.type, 'm.room.message');
expect(room.lastEvent.content['body'], 'foxies');
inbound.free(); inbound.free();
session.free(); session.free();
}); });

View file

@ -179,6 +179,31 @@ void main() {
expect(room.timeCreated, room.lastEvent.originServerTs); 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 { test('sendReadReceipt', () async {
await room.sendReadReceipt('§1234:fakeServer.notExisting'); await room.sendReadReceipt('§1234:fakeServer.notExisting');
}); });