Merge branch 'event-enhance-decryption' into 'master'

[Event] Enhance decryption

See merge request famedly/famedlysdk!215
This commit is contained in:
Christian Pauly 2020-02-21 08:44:05 +00:00
commit f6379597ed
3 changed files with 60 additions and 23 deletions

View file

@ -1192,10 +1192,10 @@ class Client {
type: type, type: type,
content: event, content: event,
); );
this.store?.storeEventUpdate(update);
if (event["type"] == "m.room.encrypted") { if (event["type"] == "m.room.encrypted") {
update = update.decrypt(this.getRoomById(update.roomID)); update = update.decrypt(this.getRoomById(update.roomID));
} }
this.store?.storeEventUpdate(update);
_updateRoomsByEventUpdate(update); _updateRoomsByEventUpdate(update);
onEvent.add(update); onEvent.add(update);

View file

@ -384,6 +384,10 @@ class Event {
content['m.relates_to']['m.in_reply_to']['event_id']; content['m.relates_to']['m.in_reply_to']['event_id'];
return await timeline.getEventById(replyEventId); return await timeline.getEventById(replyEventId);
} }
/// Trys to decrypt this event. Returns a m.bad.encrypted event
/// if it fails and does nothing if the event was not encrypted.
Event get decrypted => room.decryptGroupMessage(this);
} }
enum MessageTypes { enum MessageTypes {

View file

@ -186,6 +186,14 @@ class Room {
/// Adds the [state] to this room and overwrites a state with the same /// Adds the [state] to this room and overwrites a state with the same
/// typeKey/stateKey key pair if there is one. /// typeKey/stateKey key pair if there is one.
void setState(Event state) { void setState(Event state) {
// Decrypt if necessary
if (state.type == EventTypes.Encrypted) {
try {
state = decryptGroupMessage(state);
} catch (e) {
print("[LibOlm] Could not decrypt room state: " + e.toString());
}
}
// Check if this is a member change and we need to clear the outboundGroupSession. // Check if this is a member change and we need to clear the outboundGroupSession.
if (encrypted && if (encrypted &&
outboundGroupSession != null && outboundGroupSession != null &&
@ -708,8 +716,8 @@ class Room {
roomID: id, roomID: id,
eventType: resp["state"][i]["type"], eventType: resp["state"][i]["type"],
content: resp["state"][i], content: resp["state"][i],
); ).decrypt(this);
client.onEvent.add(eventUpdate.decrypt(this)); client.onEvent.add(eventUpdate);
client.store.storeEventUpdate(eventUpdate); client.store.storeEventUpdate(eventUpdate);
} }
return; return;
@ -721,8 +729,8 @@ class Room {
roomID: id, roomID: id,
eventType: resp["state"][i]["type"], eventType: resp["state"][i]["type"],
content: resp["state"][i], content: resp["state"][i],
); ).decrypt(this);
client.onEvent.add(eventUpdate.decrypt(this)); client.onEvent.add(eventUpdate);
} }
} }
} }
@ -735,8 +743,8 @@ class Room {
roomID: id, roomID: id,
eventType: history[i]["type"], eventType: history[i]["type"],
content: history[i], content: history[i],
); ).decrypt(this);
client.onEvent.add(eventUpdate.decrypt(this)); client.onEvent.add(eventUpdate);
client.store.storeEventUpdate(eventUpdate); client.store.storeEventUpdate(eventUpdate);
client.store.setRoomPrevBatch(id, resp["end"]); client.store.setRoomPrevBatch(id, resp["end"]);
} }
@ -749,8 +757,8 @@ class Room {
roomID: id, roomID: id,
eventType: history[i]["type"], eventType: history[i]["type"],
content: history[i], content: history[i],
); ).decrypt(this);
client.onEvent.add(eventUpdate.decrypt(this)); client.onEvent.add(eventUpdate);
} }
} }
client.onRoomUpdate.add( client.onRoomUpdate.add(
@ -908,15 +916,28 @@ class Room {
onTimelineInsertCallback onInsert}) async { onTimelineInsertCallback onInsert}) async {
List<Event> events = List<Event> events =
client.store != null ? await client.store.getEventList(this) : []; client.store != null ? await client.store.getEventList(this) : [];
if (this.encrypted) {
// Try again to decrypt encrypted events and update the database.
if (this.encrypted && client.store != null) {
await client.store.transaction(() {
for (int i = 0; i < events.length; i++) { for (int i = 0; i < events.length; i++) {
try { if (events[i].type == EventTypes.Encrypted) {
events[i] = decryptGroupMessage(events[i]); events[i] = events[i].decrypted;
} catch (e) { if (events[i].type == EventTypes.Encrypted) {
print("[LibOlm] Could not decrypt group message: " + e.toString()); client.store.storeEventUpdate(
EventUpdate(
eventType: events[i].typeKey,
content: events[i].toJson(),
roomID: events[i].roomId,
type: "timeline",
),
);
} }
} }
} }
});
}
Timeline timeline = Timeline( Timeline timeline = Timeline(
room: this, room: this,
events: events, events: events,
@ -1503,6 +1524,8 @@ class Room {
} }
/// Decrypts the given [event] with one of the available ingoingGroupSessions. /// Decrypts the given [event] with one of the available ingoingGroupSessions.
/// Returns a m.bad.encrypted event if it fails and does nothing if the event
/// was not encrypted.
Event decryptGroupMessage(Event event) { Event decryptGroupMessage(Event event) {
if (event.type != EventTypes.Encrypted) return event; if (event.type != EventTypes.Encrypted) return event;
Map<String, dynamic> decryptedPayload; Map<String, dynamic> decryptedPayload;
@ -1537,14 +1560,24 @@ class Room {
decryptedPayload = json.decode(decryptResult.plaintext); decryptedPayload = json.decode(decryptResult.plaintext);
} catch (exception) { } catch (exception) {
if (exception.toString() ==
"The sender has not sent us the session key.") {
decryptedPayload = {
"content": event.content,
"type": "m.room.encrypted",
};
decryptedPayload["content"]["body"] = exception.toString();
decryptedPayload["content"]["msgtype"] = "m.bad.encrypted";
} else {
decryptedPayload = { decryptedPayload = {
"content": { "content": {
"msgtype": "m.bad.encrypted", "msgtype": "m.bad.encrypted",
"body": exception.toString(), "body": exception.toString(),
}, },
"type": "m.room.message", "type": "m.room.encrypted",
}; };
} }
}
return Event( return Event(
content: decryptedPayload["content"], content: decryptedPayload["content"],
typeKey: decryptedPayload["type"], typeKey: decryptedPayload["type"],