Merge branch 'soru/decrypt-more-events' into 'master'
Allow requesting and updating of session keys with lower index and lower forwarded chain Closes #76 See merge request famedly/famedlysdk!341
This commit is contained in:
commit
d53003c0bd
|
@ -87,6 +87,7 @@ class Encryption {
|
|||
if (event.type != EventTypes.Encrypted ||
|
||||
event.content['ciphertext'] == null) return event;
|
||||
Map<String, dynamic> decryptedPayload;
|
||||
var canRequestSession = false;
|
||||
try {
|
||||
if (event.content['algorithm'] != 'm.megolm.v1.aes-sha2') {
|
||||
throw (DecryptError.UNKNOWN_ALGORITHM);
|
||||
|
@ -96,6 +97,7 @@ class Encryption {
|
|||
final inboundGroupSession =
|
||||
keyManager.getInboundGroupSession(roomId, sessionId, senderKey);
|
||||
if (inboundGroupSession == null) {
|
||||
canRequestSession = true;
|
||||
throw (DecryptError.UNKNOWN_SESSION);
|
||||
}
|
||||
final decryptResult = inboundGroupSession.inboundGroupSession
|
||||
|
@ -122,6 +124,8 @@ class Encryption {
|
|||
roomId,
|
||||
sessionId);
|
||||
}
|
||||
// decrypt errors here may mean we have a bad session key - others might have a better one
|
||||
canRequestSession = true;
|
||||
decryptedPayload = json.decode(decryptResult.plaintext);
|
||||
} catch (exception) {
|
||||
// alright, if this was actually by our own outbound group session, we might as well clear it
|
||||
|
@ -134,13 +138,14 @@ class Encryption {
|
|||
event.content['session_id']) {
|
||||
keyManager.clearOutboundGroupSession(roomId, wipe: true);
|
||||
}
|
||||
if (exception.toString() == DecryptError.UNKNOWN_SESSION) {
|
||||
if (canRequestSession) {
|
||||
decryptedPayload = {
|
||||
'content': event.content,
|
||||
'type': EventTypes.Encrypted,
|
||||
};
|
||||
decryptedPayload['content']['body'] = exception.toString();
|
||||
decryptedPayload['content']['msgtype'] = 'm.bad.encrypted';
|
||||
decryptedPayload['content']['can_request_session'] = true;
|
||||
} else {
|
||||
decryptedPayload = {
|
||||
'content': <String, dynamic>{
|
||||
|
|
|
@ -49,9 +49,6 @@ class KeyManager {
|
|||
{bool forwarded = false}) {
|
||||
final oldSession =
|
||||
getInboundGroupSession(roomId, sessionId, senderKey, otherRooms: false);
|
||||
if (oldSession != null) {
|
||||
return;
|
||||
}
|
||||
if (content['algorithm'] != 'm.megolm.v1.aes-sha2') {
|
||||
return;
|
||||
}
|
||||
|
@ -69,15 +66,31 @@ class KeyManager {
|
|||
'[LibOlm] Could not create new InboundGroupSession: ' + e.toString());
|
||||
return;
|
||||
}
|
||||
if (!_inboundGroupSessions.containsKey(roomId)) {
|
||||
_inboundGroupSessions[roomId] = <String, SessionKey>{};
|
||||
}
|
||||
_inboundGroupSessions[roomId][sessionId] = SessionKey(
|
||||
final newSession = SessionKey(
|
||||
content: content,
|
||||
inboundGroupSession: inboundGroupSession,
|
||||
indexes: {},
|
||||
key: client.userID,
|
||||
);
|
||||
final oldFirstIndex =
|
||||
oldSession?.inboundGroupSession?.first_known_index() ?? 0;
|
||||
final newFirstIndex = newSession.inboundGroupSession.first_known_index();
|
||||
if (oldSession == null ||
|
||||
newFirstIndex < oldFirstIndex ||
|
||||
(oldFirstIndex == newFirstIndex &&
|
||||
newSession.forwardingCurve25519KeyChain.length <
|
||||
oldSession.forwardingCurve25519KeyChain.length)) {
|
||||
// use new session
|
||||
oldSession?.dispose();
|
||||
} else {
|
||||
// we are gonna keep our old session
|
||||
newSession.dispose();
|
||||
return;
|
||||
}
|
||||
if (!_inboundGroupSessions.containsKey(roomId)) {
|
||||
_inboundGroupSessions[roomId] = <String, SessionKey>{};
|
||||
}
|
||||
_inboundGroupSessions[roomId][sessionId] = newSession;
|
||||
client.database?.storeInboundGroupSession(
|
||||
client.id,
|
||||
roomId,
|
||||
|
|
|
@ -341,8 +341,8 @@ class Event extends MatrixEvent {
|
|||
Future<void> requestKey() async {
|
||||
if (type != EventTypes.Encrypted ||
|
||||
messageType != MessageTypes.BadEncrypted ||
|
||||
content['body'] != DecryptError.UNKNOWN_SESSION) {
|
||||
throw ('Session key not unknown');
|
||||
content['can_request_session'] != true) {
|
||||
throw ('Session key not requestable');
|
||||
}
|
||||
await room.requestSessionKey(content['session_id'], content['sender_key']);
|
||||
return;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:famedlysdk/matrix_api.dart';
|
||||
import 'package:famedlysdk/encryption.dart';
|
||||
import 'package:famedlysdk/famedlysdk.dart';
|
||||
import 'package:famedlysdk/src/client.dart';
|
||||
import 'package:famedlysdk/src/event.dart';
|
||||
|
@ -996,7 +995,7 @@ class Room {
|
|||
await client.database.transaction(() async {
|
||||
for (var i = 0; i < events.length; i++) {
|
||||
if (events[i].type == EventTypes.Encrypted &&
|
||||
events[i].content['body'] == DecryptError.UNKNOWN_SESSION) {
|
||||
events[i].content['can_request_session'] == true) {
|
||||
events[i] = await client.encryption
|
||||
.decryptRoomEvent(id, events[i], store: true);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:famedlysdk/matrix_api.dart';
|
||||
import 'package:famedlysdk/encryption.dart';
|
||||
|
||||
import 'event.dart';
|
||||
import 'room.dart';
|
||||
|
@ -104,7 +103,7 @@ class Timeline {
|
|||
for (var i = 0; i < events.length; i++) {
|
||||
if (events[i].type == EventTypes.Encrypted &&
|
||||
events[i].messageType == MessageTypes.BadEncrypted &&
|
||||
events[i].content['body'] == DecryptError.UNKNOWN_SESSION &&
|
||||
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);
|
||||
|
|
|
@ -216,6 +216,148 @@ void main() {
|
|||
true);
|
||||
});
|
||||
|
||||
test('setInboundGroupSession', () async {
|
||||
final session = olm.OutboundGroupSession();
|
||||
session.create();
|
||||
final inbound = olm.InboundGroupSession();
|
||||
inbound.create(session.session_key());
|
||||
final senderKey = client.identityKey;
|
||||
final roomId = '!someroom:example.org';
|
||||
final sessionId = inbound.session_id();
|
||||
// set a payload...
|
||||
var sessionPayload = <String, dynamic>{
|
||||
'algorithm': 'm.megolm.v1.aes-sha2',
|
||||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [client.identityKey],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(1),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
client.encryption.keyManager.setInboundGroupSession(
|
||||
roomId, sessionId, senderKey, sessionPayload,
|
||||
forwarded: true);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.inboundGroupSession
|
||||
.first_known_index(),
|
||||
1);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.forwardingCurve25519KeyChain
|
||||
.length,
|
||||
1);
|
||||
|
||||
// not set one with a higher first known index
|
||||
sessionPayload = <String, dynamic>{
|
||||
'algorithm': 'm.megolm.v1.aes-sha2',
|
||||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [client.identityKey],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(2),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
client.encryption.keyManager.setInboundGroupSession(
|
||||
roomId, sessionId, senderKey, sessionPayload,
|
||||
forwarded: true);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.inboundGroupSession
|
||||
.first_known_index(),
|
||||
1);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.forwardingCurve25519KeyChain
|
||||
.length,
|
||||
1);
|
||||
|
||||
// set one with a lower first known index
|
||||
sessionPayload = <String, dynamic>{
|
||||
'algorithm': 'm.megolm.v1.aes-sha2',
|
||||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [client.identityKey],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(0),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
client.encryption.keyManager.setInboundGroupSession(
|
||||
roomId, sessionId, senderKey, sessionPayload,
|
||||
forwarded: true);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.inboundGroupSession
|
||||
.first_known_index(),
|
||||
0);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.forwardingCurve25519KeyChain
|
||||
.length,
|
||||
1);
|
||||
|
||||
// not set one with a longer forwarding chain
|
||||
sessionPayload = <String, dynamic>{
|
||||
'algorithm': 'm.megolm.v1.aes-sha2',
|
||||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [client.identityKey, 'beep'],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(0),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
client.encryption.keyManager.setInboundGroupSession(
|
||||
roomId, sessionId, senderKey, sessionPayload,
|
||||
forwarded: true);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.inboundGroupSession
|
||||
.first_known_index(),
|
||||
0);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.forwardingCurve25519KeyChain
|
||||
.length,
|
||||
1);
|
||||
|
||||
// set one with a shorter forwarding chain
|
||||
sessionPayload = <String, dynamic>{
|
||||
'algorithm': 'm.megolm.v1.aes-sha2',
|
||||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(0),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
client.encryption.keyManager.setInboundGroupSession(
|
||||
roomId, sessionId, senderKey, sessionPayload,
|
||||
forwarded: true);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.inboundGroupSession
|
||||
.first_known_index(),
|
||||
0);
|
||||
expect(
|
||||
client.encryption.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId, senderKey)
|
||||
.forwardingCurve25519KeyChain
|
||||
.length,
|
||||
0);
|
||||
|
||||
inbound.free();
|
||||
session.free();
|
||||
});
|
||||
|
||||
test('dispose client', () async {
|
||||
await client.dispose(closeDatabase: true);
|
||||
});
|
||||
|
|
|
@ -237,9 +237,9 @@ void main() {
|
|||
try {
|
||||
await event.requestKey();
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
exception = e.toString();
|
||||
}
|
||||
expect(exception, 'Session key not unknown');
|
||||
expect(exception, 'Session key not requestable');
|
||||
|
||||
var event2 = Event.fromJson({
|
||||
'event_id': id,
|
||||
|
@ -251,6 +251,7 @@ void main() {
|
|||
'content': json.encode({
|
||||
'msgtype': 'm.bad.encrypted',
|
||||
'body': DecryptError.UNKNOWN_SESSION,
|
||||
'can_request_session': true,
|
||||
'algorithm': 'm.megolm.v1.aes-sha2',
|
||||
'ciphertext': 'AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...',
|
||||
'device_id': 'RJYKSTBOIE',
|
||||
|
|
Loading…
Reference in a new issue