refactor: Migrate megolm to vodozemac
This commit is contained in:
parent
31a32b0145
commit
98fcd683a6
|
|
@ -227,7 +227,7 @@ class Encryption {
|
|||
canRequestSession = false;
|
||||
|
||||
// we can't have the key be an int, else json-serializing will fail, thus we need it to be a string
|
||||
final messageIndexKey = 'key-${decryptResult.message_index}';
|
||||
final messageIndexKey = 'key-${decryptResult.messageIndex}';
|
||||
final messageIndexValue =
|
||||
'${event.eventId}|${event.originServerTs.millisecondsSinceEpoch}';
|
||||
final haveIndex =
|
||||
|
|
@ -255,13 +255,14 @@ class Encryption {
|
|||
.onError((e, _) => Logs().e('Ignoring error for updating indexes'));
|
||||
}
|
||||
decryptedPayload = json.decode(decryptResult.plaintext);
|
||||
} catch (exception) {
|
||||
} catch (exception, stackTrace) {
|
||||
Logs().w('Could not decrypt event', exception, stackTrace);
|
||||
// alright, if this was actually by our own outbound group session, we might as well clear it
|
||||
if (exception.toString() != DecryptException.unknownSession &&
|
||||
(keyManager
|
||||
.getOutboundGroupSession(event.room.id)
|
||||
?.outboundGroupSession
|
||||
?.session_id() ??
|
||||
?.sessionId ??
|
||||
'') ==
|
||||
content.sessionId) {
|
||||
runInRoot(
|
||||
|
|
@ -409,7 +410,7 @@ class Encryption {
|
|||
// they're deprecated. Just left here for compatibility
|
||||
'device_id': client.deviceID,
|
||||
'sender_key': identityKey,
|
||||
'session_id': sess.outboundGroupSession!.session_id(),
|
||||
'session_id': sess.outboundGroupSession!.sessionId,
|
||||
if (mRelatesTo != null) 'm.relates_to': mRelatesTo,
|
||||
};
|
||||
await keyManager.storeOutboundGroupSession(roomId, sess);
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption/encryption.dart';
|
||||
import 'package:matrix/encryption/utils/base64_unpadded.dart';
|
||||
import 'package:matrix/encryption/utils/outbound_group_session.dart';
|
||||
import 'package:matrix/encryption/utils/pickle_key.dart';
|
||||
import 'package:matrix/encryption/utils/session_key.dart';
|
||||
import 'package:matrix/encryption/utils/stored_inbound_group_session.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
@ -118,16 +118,15 @@ class KeyManager {
|
|||
if (content['algorithm'] != AlgorithmTypes.megolmV1AesSha2) {
|
||||
return;
|
||||
}
|
||||
late olm.InboundGroupSession inboundGroupSession;
|
||||
late vod.InboundGroupSession inboundGroupSession;
|
||||
try {
|
||||
inboundGroupSession = olm.InboundGroupSession();
|
||||
if (forwarded) {
|
||||
inboundGroupSession.import_session(content['session_key']);
|
||||
inboundGroupSession =
|
||||
vod.InboundGroupSession.import(content['session_key']);
|
||||
} else {
|
||||
inboundGroupSession.create(content['session_key']);
|
||||
inboundGroupSession = vod.InboundGroupSession(content['session_key']);
|
||||
}
|
||||
} catch (e, s) {
|
||||
inboundGroupSession.free();
|
||||
Logs().e('[LibOlm] Could not create new InboundGroupSession', e, s);
|
||||
return Future.value();
|
||||
}
|
||||
|
|
@ -142,19 +141,16 @@ class KeyManager {
|
|||
senderClaimedKeys: senderClaimedKeys_,
|
||||
allowedAtIndex: allowedAtIndex_,
|
||||
);
|
||||
final oldFirstIndex =
|
||||
oldSession?.inboundGroupSession?.first_known_index() ?? 0;
|
||||
final newFirstIndex = newSession.inboundGroupSession!.first_known_index();
|
||||
final oldFirstIndex = oldSession?.inboundGroupSession?.firstKnownIndex ?? 0;
|
||||
final newFirstIndex = newSession.inboundGroupSession!.firstKnownIndex;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +165,7 @@ class KeyManager {
|
|||
.storeInboundGroupSession(
|
||||
roomId,
|
||||
sessionId,
|
||||
inboundGroupSession.pickle(userId),
|
||||
inboundGroupSession.toPickleEncrypted(userId.toPickleKey()),
|
||||
json.encode(content),
|
||||
json.encode({}),
|
||||
json.encode(allowedAtIndex_),
|
||||
|
|
@ -344,7 +340,7 @@ class KeyManager {
|
|||
|
||||
final inboundSess = await loadInboundGroupSession(
|
||||
room.id,
|
||||
sess.outboundGroupSession!.session_id(),
|
||||
sess.outboundGroupSession!.sessionId,
|
||||
);
|
||||
if (inboundSess == null) {
|
||||
Logs().w('No inbound megolm session found for outbound session!');
|
||||
|
|
@ -436,8 +432,8 @@ class KeyManager {
|
|||
final rawSession = <String, dynamic>{
|
||||
'algorithm': AlgorithmTypes.megolmV1AesSha2,
|
||||
'room_id': room.id,
|
||||
'session_id': sess.outboundGroupSession!.session_id(),
|
||||
'session_key': sess.outboundGroupSession!.session_key(),
|
||||
'session_id': sess.outboundGroupSession!.sessionId,
|
||||
'session_key': sess.outboundGroupSession!.sessionKey,
|
||||
};
|
||||
try {
|
||||
devicesToReceive.removeWhere((k) => !k.encryptToDevice);
|
||||
|
|
@ -449,16 +445,16 @@ class KeyManager {
|
|||
.containsKey(device.curve25519Key) ||
|
||||
inboundSess.allowedAtIndex[device.userId]![
|
||||
device.curve25519Key]! >
|
||||
sess.outboundGroupSession!.message_index()) {
|
||||
sess.outboundGroupSession!.messageIndex) {
|
||||
inboundSess
|
||||
.allowedAtIndex[device.userId]![device.curve25519Key!] =
|
||||
sess.outboundGroupSession!.message_index();
|
||||
sess.outboundGroupSession!.messageIndex;
|
||||
}
|
||||
}
|
||||
await client.database.updateInboundGroupSessionAllowedAtIndex(
|
||||
json.encode(inboundSess!.allowedAtIndex),
|
||||
room.id,
|
||||
sess.outboundGroupSession!.session_id(),
|
||||
sess.outboundGroupSession!.sessionId,
|
||||
);
|
||||
// send out the key
|
||||
await client.sendToDeviceEncryptedChunked(
|
||||
|
|
@ -477,7 +473,6 @@ class KeyManager {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
sess.dispose();
|
||||
_outboundGroupSessions.remove(roomId);
|
||||
await client.database.removeOutboundGroupSession(roomId);
|
||||
return true;
|
||||
|
|
@ -492,7 +487,7 @@ class KeyManager {
|
|||
if (userID == null) return;
|
||||
await client.database.storeOutboundGroupSession(
|
||||
roomId,
|
||||
sess.outboundGroupSession!.pickle(userID),
|
||||
sess.outboundGroupSession!.toPickleEncrypted(userID.toPickleKey()),
|
||||
json.encode(sess.devices),
|
||||
sess.creationTime.millisecondsSinceEpoch,
|
||||
);
|
||||
|
|
@ -553,19 +548,13 @@ class KeyManager {
|
|||
final deviceKeys = await room.getUserDeviceKeys();
|
||||
final deviceKeyIds = _getDeviceKeyIdMap(deviceKeys);
|
||||
deviceKeys.removeWhere((k) => !k.encryptToDevice);
|
||||
final outboundGroupSession = olm.OutboundGroupSession();
|
||||
try {
|
||||
outboundGroupSession.create();
|
||||
} catch (e, s) {
|
||||
outboundGroupSession.free();
|
||||
Logs().e('[LibOlm] Unable to create new outboundGroupSession', e, s);
|
||||
rethrow;
|
||||
}
|
||||
final outboundGroupSession = vod.GroupSession();
|
||||
|
||||
final rawSession = <String, dynamic>{
|
||||
'algorithm': AlgorithmTypes.megolmV1AesSha2,
|
||||
'room_id': room.id,
|
||||
'session_id': outboundGroupSession.session_id(),
|
||||
'session_key': outboundGroupSession.session_key(),
|
||||
'session_id': outboundGroupSession.sessionId,
|
||||
'session_key': outboundGroupSession.sessionKey,
|
||||
};
|
||||
final allowedAtIndex = <String, Map<String, int>>{};
|
||||
for (final device in deviceKeys) {
|
||||
|
|
@ -575,7 +564,7 @@ class KeyManager {
|
|||
}
|
||||
allowedAtIndex[device.userId] ??= <String, int>{};
|
||||
allowedAtIndex[device.userId]![device.curve25519Key!] =
|
||||
outboundGroupSession.message_index();
|
||||
outboundGroupSession.messageIndex;
|
||||
}
|
||||
await setInboundGroupSession(
|
||||
roomId,
|
||||
|
|
@ -604,7 +593,6 @@ class KeyManager {
|
|||
e,
|
||||
s,
|
||||
);
|
||||
sess.dispose();
|
||||
rethrow;
|
||||
}
|
||||
return sess;
|
||||
|
|
@ -1163,14 +1151,6 @@ class KeyManager {
|
|||
void dispose() {
|
||||
// ignore: discarded_futures
|
||||
_uploadKeysOnSync?.cancel();
|
||||
for (final sess in _outboundGroupSessions.values) {
|
||||
sess.dispose();
|
||||
}
|
||||
for (final entries in _inboundGroupSessions.values) {
|
||||
for (final sess in entries.values) {
|
||||
sess.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1233,8 +1213,8 @@ class RoomKeyRequest extends ToDeviceEvent {
|
|||
(session.forwardingCurve25519KeyChain.isEmpty
|
||||
? keyManager.encryption.fingerprintKey
|
||||
: null);
|
||||
message['session_key'] = session.inboundGroupSession!.export_session(
|
||||
index ?? session.inboundGroupSession!.first_known_index(),
|
||||
message['session_key'] = session.inboundGroupSession!.exportAt(
|
||||
index ?? session.inboundGroupSession!.firstKnownIndex,
|
||||
);
|
||||
// send the actual reply of the key back to the requester
|
||||
await keyManager.client.sendToDeviceEncrypted(
|
||||
|
|
@ -1269,8 +1249,7 @@ RoomKeys generateUploadKeysImplementation(GenerateUploadKeysArgs args) {
|
|||
'forwarding_curve25519_key_chain': sess.forwardingCurve25519KeyChain,
|
||||
'sender_key': sess.senderKey,
|
||||
'sender_claimed_keys': sess.senderClaimedKeys,
|
||||
'session_key': sess.inboundGroupSession!
|
||||
.export_session(sess.inboundGroupSession!.first_known_index()),
|
||||
'session_key': sess.inboundGroupSession!.exportAtFirstKnownIndex(),
|
||||
};
|
||||
// encrypt the content
|
||||
final encrypted = enc.encrypt(json.encode(payload));
|
||||
|
|
@ -1278,7 +1257,7 @@ RoomKeys generateUploadKeysImplementation(GenerateUploadKeysArgs args) {
|
|||
//final device = args.client.getUserDeviceKeysByCurve25519Key(sess.senderKey);
|
||||
// aaaand finally add the session key to our payload
|
||||
roomKeyBackup.sessions[sess.sessionId] = KeyBackupData(
|
||||
firstMessageIndex: sess.inboundGroupSession!.first_known_index(),
|
||||
firstMessageIndex: sess.inboundGroupSession!.firstKnownIndex,
|
||||
forwardedCount: sess.forwardingCurve25519KeyChain.length,
|
||||
isVerified: dbSession.verified, //device?.verified ?? false,
|
||||
sessionData: {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption/utils/pickle_key.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
class OutboundGroupSession {
|
||||
|
|
@ -30,8 +31,8 @@ class OutboundGroupSession {
|
|||
Map<String, Map<String, bool>> devices = {};
|
||||
// Default to a date, that would get this session rotated in any case to make handling easier
|
||||
DateTime creationTime = DateTime.fromMillisecondsSinceEpoch(0);
|
||||
olm.OutboundGroupSession? outboundGroupSession;
|
||||
int? get sentMessages => outboundGroupSession?.message_index();
|
||||
vod.GroupSession? outboundGroupSession;
|
||||
int? get sentMessages => outboundGroupSession?.messageIndex;
|
||||
bool get isValid => outboundGroupSession != null;
|
||||
final String key;
|
||||
|
||||
|
|
@ -54,19 +55,24 @@ class OutboundGroupSession {
|
|||
);
|
||||
return;
|
||||
}
|
||||
outboundGroupSession = olm.OutboundGroupSession();
|
||||
|
||||
creationTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(dbEntry['creation_time']);
|
||||
|
||||
try {
|
||||
outboundGroupSession!.unpickle(key, dbEntry['pickle']);
|
||||
creationTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(dbEntry['creation_time']);
|
||||
outboundGroupSession = vod.GroupSession.fromPickleEncrypted(
|
||||
pickleKey: key.toPickleKey(),
|
||||
pickle: dbEntry['pickle'],
|
||||
);
|
||||
} catch (e, s) {
|
||||
dispose();
|
||||
Logs().e('[LibOlm] Unable to unpickle outboundGroupSession', e, s);
|
||||
try {
|
||||
outboundGroupSession = vod.GroupSession.fromOlmPickleEncrypted(
|
||||
pickleKey: utf8.encode(key),
|
||||
pickle: dbEntry['pickle'],
|
||||
);
|
||||
} catch (_) {
|
||||
Logs().e('[LibOlm] Unable to unpickle outboundGroupSession', e, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
outboundGroupSession?.free();
|
||||
outboundGroupSession = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
extension PickleKeyStringExtension on String {
|
||||
Uint8List toPickleKey() {
|
||||
final bytes = Uint8List.fromList(codeUnits);
|
||||
final missing = 32 - bytes.length;
|
||||
if (missing > 0) {
|
||||
return Uint8List.fromList([
|
||||
...bytes,
|
||||
...List.filled(missing, 0),
|
||||
]);
|
||||
}
|
||||
return Uint8List.fromList(bytes.getRange(0, 32).toList());
|
||||
}
|
||||
}
|
||||
|
|
@ -16,8 +16,11 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption/utils/pickle_key.dart';
|
||||
import 'package:matrix/encryption/utils/stored_inbound_group_session.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
|
|
@ -33,7 +36,7 @@ class SessionKey {
|
|||
Map<String, Map<String, int>> allowedAtIndex;
|
||||
|
||||
/// Underlying olm [InboundGroupSession] object
|
||||
olm.InboundGroupSession? inboundGroupSession;
|
||||
vod.InboundGroupSession? inboundGroupSession;
|
||||
|
||||
/// Key for libolm pickle / unpickle
|
||||
final String key;
|
||||
|
|
@ -81,8 +84,7 @@ class SessionKey {
|
|||
.catchMap((k, v) => MapEntry(k, Map<String, int>.from(v))),
|
||||
roomId = dbEntry.roomId,
|
||||
sessionId = dbEntry.sessionId,
|
||||
senderKey = dbEntry.senderKey,
|
||||
inboundGroupSession = olm.InboundGroupSession() {
|
||||
senderKey = dbEntry.senderKey {
|
||||
final parsedSenderClaimedKeys =
|
||||
Event.getMapFromPayload(dbEntry.senderClaimedKeys)
|
||||
.catchMap((k, v) => MapEntry<String, String>(k, v));
|
||||
|
|
@ -99,15 +101,20 @@ class SessionKey {
|
|||
: <String, String>{}));
|
||||
|
||||
try {
|
||||
inboundGroupSession!.unpickle(key, dbEntry.pickle);
|
||||
inboundGroupSession = vod.InboundGroupSession.fromPickleEncrypted(
|
||||
pickle: dbEntry.pickle,
|
||||
pickleKey: key.toPickleKey(),
|
||||
);
|
||||
} catch (e, s) {
|
||||
dispose();
|
||||
Logs().e('[LibOlm] Unable to unpickle inboundGroupSession', e, s);
|
||||
try {
|
||||
inboundGroupSession = vod.InboundGroupSession.fromOlmPickleEncrypted(
|
||||
pickle: dbEntry.pickle,
|
||||
pickleKey: utf8.encode(key),
|
||||
);
|
||||
} catch (_) {
|
||||
Logs().e('[LibOlm] Unable to unpickle inboundGroupSession', e, s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
inboundGroupSession?.free();
|
||||
inboundGroupSession = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,15 +68,8 @@ void main() {
|
|||
group('client mem', tags: 'olm', () {
|
||||
late Client matrix;
|
||||
|
||||
Future? vodInit;
|
||||
|
||||
/// Check if all Elements get created
|
||||
setUp(() async {
|
||||
vodInit ??= vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await vodInit;
|
||||
matrix = await getClient();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'dart:convert';
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'fake_client.dart';
|
||||
|
|
@ -47,6 +48,10 @@ void main() {
|
|||
}
|
||||
|
||||
test('setupClient', () async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
client = await getClient();
|
||||
room = Room(id: '!1234:fakeServer.notExisting', client: client);
|
||||
room.setState(
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ void main() {
|
|||
);
|
||||
var inbound = client.encryption!.keyManager.getInboundGroupSession(
|
||||
roomId,
|
||||
sess.outboundGroupSession!.session_id(),
|
||||
sess.outboundGroupSession!.sessionId,
|
||||
);
|
||||
expect(inbound != null, true);
|
||||
expect(
|
||||
|
|
@ -157,7 +157,7 @@ void main() {
|
|||
// lazy-create if it would rotate
|
||||
sess = await client.encryption!.keyManager
|
||||
.createOutboundGroupSession(roomId);
|
||||
final oldSessKey = sess.outboundGroupSession!.session_key();
|
||||
final oldSessKey = sess.outboundGroupSession!.sessionKey;
|
||||
client.userDeviceKeys['@alice:example.com']!.deviceKeys['JLAFKJWSCS']!
|
||||
.blocked = true;
|
||||
await client.encryption!.keyManager.prepareOutboundGroupSession(roomId);
|
||||
|
|
@ -169,7 +169,7 @@ void main() {
|
|||
client.encryption!.keyManager
|
||||
.getOutboundGroupSession(roomId)!
|
||||
.outboundGroupSession!
|
||||
.session_key() !=
|
||||
.sessionKey !=
|
||||
oldSessKey,
|
||||
true,
|
||||
);
|
||||
|
|
@ -241,7 +241,7 @@ void main() {
|
|||
);
|
||||
inbound = client.encryption!.keyManager.getInboundGroupSession(
|
||||
roomId,
|
||||
sess.outboundGroupSession!.session_id(),
|
||||
sess.outboundGroupSession!.sessionId,
|
||||
);
|
||||
expect(
|
||||
inbound!.allowedAtIndex['@alice:example.com']
|
||||
|
|
@ -358,13 +358,13 @@ void main() {
|
|||
});
|
||||
|
||||
test('setInboundGroupSession', () async {
|
||||
final session = olm.OutboundGroupSession();
|
||||
session.create();
|
||||
final inbound = olm.InboundGroupSession();
|
||||
inbound.create(session.session_key());
|
||||
final session = vod.GroupSession();
|
||||
|
||||
final inbound = vod.InboundGroupSession(session.sessionKey);
|
||||
|
||||
final senderKey = client.identityKey;
|
||||
final roomId = '!someroom:example.org';
|
||||
final sessionId = inbound.session_id();
|
||||
final sessionId = inbound.sessionId;
|
||||
final room = Room(id: roomId, client: client);
|
||||
final nextSyncUpdateFuture = client.onSync.stream
|
||||
.firstWhere((update) => update.rooms != null)
|
||||
|
|
@ -413,7 +413,7 @@ void main() {
|
|||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [client.identityKey],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(1),
|
||||
'session_key': inbound.exportAt(1),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
|
|
@ -428,7 +428,7 @@ void main() {
|
|||
client.encryption!.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId)
|
||||
?.inboundGroupSession
|
||||
?.first_known_index(),
|
||||
?.firstKnownIndex,
|
||||
1,
|
||||
);
|
||||
expect(
|
||||
|
|
@ -445,7 +445,7 @@ void main() {
|
|||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [client.identityKey],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(2),
|
||||
'session_key': inbound.exportAt(2),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
|
|
@ -460,7 +460,7 @@ void main() {
|
|||
client.encryption!.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId)
|
||||
?.inboundGroupSession
|
||||
?.first_known_index(),
|
||||
?.firstKnownIndex,
|
||||
1,
|
||||
);
|
||||
expect(
|
||||
|
|
@ -477,7 +477,7 @@ void main() {
|
|||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [client.identityKey],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(0),
|
||||
'session_key': inbound.exportAt(0),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
|
|
@ -492,7 +492,7 @@ void main() {
|
|||
client.encryption!.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId)
|
||||
?.inboundGroupSession
|
||||
?.first_known_index(),
|
||||
?.firstKnownIndex,
|
||||
0,
|
||||
);
|
||||
expect(
|
||||
|
|
@ -509,7 +509,7 @@ void main() {
|
|||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [client.identityKey, 'beep'],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(0),
|
||||
'session_key': inbound.exportAt(0),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
|
|
@ -524,7 +524,7 @@ void main() {
|
|||
client.encryption!.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId)
|
||||
?.inboundGroupSession
|
||||
?.first_known_index(),
|
||||
?.firstKnownIndex,
|
||||
0,
|
||||
);
|
||||
expect(
|
||||
|
|
@ -541,7 +541,7 @@ void main() {
|
|||
'room_id': roomId,
|
||||
'forwarding_curve25519_key_chain': [],
|
||||
'session_id': sessionId,
|
||||
'session_key': inbound.export_session(0),
|
||||
'session_key': inbound.exportAt(0),
|
||||
'sender_key': senderKey,
|
||||
'sender_claimed_ed25519_key': client.fingerprintKey,
|
||||
};
|
||||
|
|
@ -556,7 +556,7 @@ void main() {
|
|||
client.encryption!.keyManager
|
||||
.getInboundGroupSession(roomId, sessionId)
|
||||
?.inboundGroupSession
|
||||
?.first_known_index(),
|
||||
?.firstKnownIndex,
|
||||
0,
|
||||
);
|
||||
expect(
|
||||
|
|
@ -575,9 +575,6 @@ void main() {
|
|||
// decrypted last event
|
||||
final syncUpdate = await nextSyncUpdateFuture;
|
||||
expect(syncUpdate.rooms?.join?.containsKey(room.id), true);
|
||||
|
||||
inbound.free();
|
||||
session.free();
|
||||
});
|
||||
|
||||
test('Reused deviceID attack', () async {
|
||||
|
|
|
|||
|
|
@ -314,8 +314,7 @@ void main() {
|
|||
|
||||
final session = (await matrix.encryption!.keyManager
|
||||
.loadInboundGroupSession(requestRoom.id, validSessionId))!;
|
||||
final sessionKey = session.inboundGroupSession!
|
||||
.export_session(session.inboundGroupSession!.first_known_index());
|
||||
final sessionKey = session.inboundGroupSession!.exportAtFirstKnownIndex();
|
||||
matrix.encryption!.keyManager.clearInboundGroupSessions();
|
||||
var event = ToDeviceEvent(
|
||||
sender: '@alice:example.com',
|
||||
|
|
|
|||
|
|
@ -17,10 +17,12 @@
|
|||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'package:matrix/encryption/utils/base64_unpadded.dart';
|
||||
import 'package:matrix/encryption/utils/pickle_key.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
void main() {
|
||||
|
|
@ -84,4 +86,27 @@ void main() {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('toPickleKey', () {
|
||||
test('toPickleKey', () {
|
||||
const shortKey = 'abcd';
|
||||
var pickleKey = shortKey.toPickleKey();
|
||||
expect(pickleKey.length, 32, reason: 'Pickle key should be 32 bytes');
|
||||
expect(
|
||||
shortKey,
|
||||
String.fromCharCodes(pickleKey.take(4)),
|
||||
reason: 'Pickle key should match the first 32 bytes of the input',
|
||||
);
|
||||
|
||||
const longKey =
|
||||
'abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890';
|
||||
pickleKey = longKey.toPickleKey();
|
||||
expect(pickleKey.length, 32, reason: 'Pickle key should be 32 bytes');
|
||||
expect(
|
||||
pickleKey,
|
||||
Uint8List.fromList(longKey.codeUnits.take(32).toList()),
|
||||
reason: 'Pickle key should match the first 32 bytes of the input',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
import 'fake_database.dart';
|
||||
|
||||
const ssssPassphrase = 'nae7ahDiequ7ohniufah3ieS2je1thohX4xeeka7aixohsho9O';
|
||||
|
|
@ -26,11 +27,22 @@ const ssssKey = 'EsT9 RzbW VhPW yqNp cC7j ViiW 5TZB LuY4 ryyv 9guN Ysmr WDPH';
|
|||
const pickledOlmAccount =
|
||||
'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtuyg3RxViwdNxs3718fyAqQ/VSwbXsY0Nl+qQbF+nlVGHenGqk5SuNl1P6e1PzZxcR0IfXA94Xij1Ob5gDv5YH4UCn9wRMG0abZsQP0YzpDM0FLaHSCyo9i5JD/vMlhH+nZWrgAzPPCTNGYewNV8/h3c+VyJh8ZTx/fVi6Yq46Fv+27Ga2ETRZ3Qn+Oyx6dLBjnBZ9iUvIhqpe2XqaGA1PopOz8iDnaZitw';
|
||||
|
||||
Future? vodInit;
|
||||
|
||||
/// only use `path` if you explicitly if you need a db on path instead of in mem
|
||||
Future<Client> getClient({
|
||||
Duration sendTimelineEventTimeout = const Duration(minutes: 1),
|
||||
String? databasePath,
|
||||
}) async {
|
||||
try {
|
||||
vodInit ??= vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await vodInit;
|
||||
} catch (_) {
|
||||
Logs().d('Encryption via Vodozemac not enabled');
|
||||
}
|
||||
final client = Client(
|
||||
logLevel: Level.verbose,
|
||||
'testclient',
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ void main() async {
|
|||
final inboundSession =
|
||||
client.encryption!.keyManager.getInboundGroupSession(
|
||||
roomid,
|
||||
outboundSession!.outboundGroupSession!.session_id(),
|
||||
outboundSession!.outboundGroupSession!.sessionId,
|
||||
)!;
|
||||
|
||||
// ensure encryption is "enabled"
|
||||
|
|
|
|||
|
|
@ -675,13 +675,9 @@ void main() {
|
|||
test(
|
||||
'calcEncryptionHealthState',
|
||||
() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
expect(
|
||||
await room.calcEncryptionHealthState(),
|
||||
EncryptionHealthState.allVerified,
|
||||
EncryptionHealthState.unverifiedDevices,
|
||||
);
|
||||
},
|
||||
tags: 'olm',
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ void main() => group(
|
|||
var currentSessionIdA = room.client.encryption!.keyManager
|
||||
.getOutboundGroupSession(room.id)!
|
||||
.outboundGroupSession!
|
||||
.session_id();
|
||||
.sessionId;
|
||||
/*expect(room.client.encryption.keyManager
|
||||
.getInboundGroupSession(room.id, currentSessionIdA, '') !=
|
||||
null);*/
|
||||
|
|
@ -289,7 +289,7 @@ void main() => group(
|
|||
room.client.encryption!.keyManager
|
||||
.getOutboundGroupSession(room.id)!
|
||||
.outboundGroupSession!
|
||||
.session_id(),
|
||||
.sessionId,
|
||||
currentSessionIdA,
|
||||
);
|
||||
/*expect(room.client.encryption.keyManager
|
||||
|
|
@ -320,7 +320,7 @@ void main() => group(
|
|||
room.client.encryption!.keyManager
|
||||
.getOutboundGroupSession(room.id)!
|
||||
.outboundGroupSession!
|
||||
.session_id(),
|
||||
.sessionId,
|
||||
currentSessionIdA,
|
||||
);
|
||||
final inviteRoomOutboundGroupSession = inviteRoom
|
||||
|
|
@ -330,12 +330,12 @@ void main() => group(
|
|||
expect(inviteRoomOutboundGroupSession.isValid, isTrue);
|
||||
/*expect(inviteRoom.client.encryption.keyManager.getInboundGroupSession(
|
||||
inviteRoom.id,
|
||||
inviteRoomOutboundGroupSession.outboundGroupSession.session_id(),
|
||||
inviteRoomOutboundGroupSession.outboundGroupSession.sessionId,
|
||||
'') !=
|
||||
null);
|
||||
expect(room.client.encryption.keyManager.getInboundGroupSession(
|
||||
room.id,
|
||||
inviteRoomOutboundGroupSession.outboundGroupSession.session_id(),
|
||||
inviteRoomOutboundGroupSession.outboundGroupSession.sessionId,
|
||||
'') !=
|
||||
null);*/
|
||||
expect(inviteRoom.lastEvent!.body, testMessage3);
|
||||
|
|
@ -397,7 +397,7 @@ void main() => group(
|
|||
room.client.encryption!.keyManager
|
||||
.getOutboundGroupSession(room.id)!
|
||||
.outboundGroupSession!
|
||||
.session_id(),
|
||||
.sessionId,
|
||||
currentSessionIdA,
|
||||
);
|
||||
/*expect(inviteRoom.client.encryption.keyManager
|
||||
|
|
@ -445,14 +445,14 @@ void main() => group(
|
|||
room.client.encryption!.keyManager
|
||||
.getOutboundGroupSession(room.id)!
|
||||
.outboundGroupSession!
|
||||
.session_id(),
|
||||
.sessionId,
|
||||
isNot(currentSessionIdA),
|
||||
);
|
||||
}
|
||||
currentSessionIdA = room.client.encryption!.keyManager
|
||||
.getOutboundGroupSession(room.id)!
|
||||
.outboundGroupSession!
|
||||
.session_id();
|
||||
.sessionId;
|
||||
/*expect(inviteRoom.client.encryption.keyManager
|
||||
.getInboundGroupSession(inviteRoom.id, currentSessionIdA, '') !=
|
||||
null);*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue