chore: port the remaining encryption files to nullsafety

This commit is contained in:
Nicolas Werner 2021-10-11 18:55:07 +02:00
parent 3ae42d1a88
commit 60956bde00
16 changed files with 91 additions and 99 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
*.log *.log
*.pyc *.pyc
*.swp *.swp
*.swo
.DS_Store .DS_Store
.atom/ .atom/
.buildlog/ .buildlog/

View File

@ -1,4 +1,3 @@
// @dart=2.9
/* /*
* Famedly Matrix SDK * Famedly Matrix SDK
* Copyright (C) 2020, 2021 Famedly GmbH * Copyright (C) 2020, 2021 Famedly GmbH
@ -35,7 +34,7 @@ class CrossSigning {
final keyObj = olm.PkSigning(); final keyObj = olm.PkSigning();
try { try {
return keyObj.init_with_seed(base64.decode(secret)) == return keyObj.init_with_seed(base64.decode(secret)) ==
client.userDeviceKeys[client.userID].selfSigningKey.ed25519Key; client.userDeviceKeys[client.userID]!.selfSigningKey!.ed25519Key;
} catch (_) { } catch (_) {
return false; return false;
} finally { } finally {
@ -47,7 +46,7 @@ class CrossSigning {
final keyObj = olm.PkSigning(); final keyObj = olm.PkSigning();
try { try {
return keyObj.init_with_seed(base64.decode(secret)) == return keyObj.init_with_seed(base64.decode(secret)) ==
client.userDeviceKeys[client.userID].userSigningKey.ed25519Key; client.userDeviceKeys[client.userID]!.userSigningKey!.ed25519Key;
} catch (_) { } catch (_) {
return false; return false;
} finally { } finally {
@ -73,10 +72,10 @@ class CrossSigning {
} }
Future<void> selfSign( Future<void> selfSign(
{String passphrase, {String? passphrase,
String recoveryKey, String? recoveryKey,
String keyOrPassphrase, String? keyOrPassphrase,
OpenSSSS openSsss}) async { OpenSSSS? openSsss}) async {
var handle = openSsss; var handle = openSsss;
if (handle == null) { if (handle == null) {
handle = encryption.ssss.open(EventTypes.CrossSigningMasterKey); handle = encryption.ssss.open(EventTypes.CrossSigningMasterKey);
@ -97,13 +96,12 @@ class CrossSigning {
} finally { } finally {
keyObj.free(); keyObj.free();
} }
if (masterPubkey == null || final userDeviceKeys =
!client.userDeviceKeys.containsKey(client.userID) || client.userDeviceKeys[client.userID]?.deviceKeys[client.deviceID];
!client.userDeviceKeys[client.userID].deviceKeys if (masterPubkey == null || userDeviceKeys == null) {
.containsKey(client.deviceID)) {
throw Exception('Master or user keys not found'); throw Exception('Master or user keys not found');
} }
final masterKey = client.userDeviceKeys[client.userID].masterKey; final masterKey = client.userDeviceKeys[client.userID]?.masterKey;
if (masterKey == null || masterKey.ed25519Key != masterPubkey) { if (masterKey == null || masterKey.ed25519Key != masterPubkey) {
throw Exception('Master pubkey key doesn\'t match'); throw Exception('Master pubkey key doesn\'t match');
} }
@ -112,7 +110,7 @@ class CrossSigning {
// and now sign both our own key and our master key // and now sign both our own key and our master key
await sign([ await sign([
masterKey, masterKey,
client.userDeviceKeys[client.userID].deviceKeys[client.deviceID] userDeviceKeys,
]); ]);
} }
@ -123,20 +121,26 @@ class CrossSigning {
key.identifier != client.deviceID); key.identifier != client.deviceID);
Future<void> sign(List<SignableKey> keys) async { Future<void> sign(List<SignableKey> keys) async {
Uint8List selfSigningKey;
Uint8List userSigningKey;
final signedKeys = <MatrixSignableKey>[]; final signedKeys = <MatrixSignableKey>[];
Uint8List? selfSigningKey;
Uint8List? userSigningKey;
final userKeys = client.userDeviceKeys[client.userID];
if (userKeys == null) {
throw Exception('[sign] keys are not in cache but sign was called');
}
final addSignature = final addSignature =
(SignableKey key, SignableKey signedWith, String signature) { (SignableKey key, SignableKey signedWith, String signature) {
if (key == null || signedWith == null || signature == null) { if (key == null || signedWith == null || signature == null) {
return; return;
} }
final signedKey = key.cloneForSigning(); final signedKey = key.cloneForSigning();
signedKey.signatures[signedWith.userId] = <String, String>{}; ((signedKey.signatures ??=
signedKey.signatures[signedWith.userId] <String, Map<String, String>>{})[signedWith.userId] ??=
['ed25519:${signedWith.identifier}'] = signature; <String, String>{})['ed25519:${signedWith.identifier}'] = signature;
signedKeys.add(signedKey); signedKeys.add(signedKey);
}; };
for (final key in keys) { for (final key in keys) {
if (key.userId == client.userID) { if (key.userId == client.userID) {
// we are singing a key of ourself // we are singing a key of ourself
@ -145,11 +149,7 @@ class CrossSigning {
// okay, we'll sign our own master key // okay, we'll sign our own master key
final signature = final signature =
encryption.olmManager.signString(key.signingContent); encryption.olmManager.signString(key.signingContent);
addSignature( addSignature(key, userKeys.deviceKeys[client.deviceID]!, signature);
key,
client
.userDeviceKeys[client.userID].deviceKeys[client.deviceID],
signature);
} }
// we don't care about signing other cross-signing keys // we don't care about signing other cross-signing keys
} else { } else {
@ -159,8 +159,7 @@ class CrossSigning {
''); '');
if (selfSigningKey.isNotEmpty) { if (selfSigningKey.isNotEmpty) {
final signature = _sign(key.signingContent, selfSigningKey); final signature = _sign(key.signingContent, selfSigningKey);
addSignature(key, addSignature(key, userKeys.selfSigningKey!, signature);
client.userDeviceKeys[client.userID].selfSigningKey, signature);
} }
} }
} else if (key is CrossSigningKey && key.usage.contains('master')) { } else if (key is CrossSigningKey && key.usage.contains('master')) {
@ -170,8 +169,7 @@ class CrossSigning {
''); '');
if (userSigningKey.isNotEmpty) { if (userSigningKey.isNotEmpty) {
final signature = _sign(key.signingContent, userSigningKey); final signature = _sign(key.signingContent, userSigningKey);
addSignature(key, client.userDeviceKeys[client.userID].userSigningKey, addSignature(key, userKeys.userSigningKey!, signature);
signature);
} }
} }
} }
@ -181,19 +179,19 @@ class CrossSigning {
for (final key in signedKeys) { for (final key in signedKeys) {
if (key.identifier == null || if (key.identifier == null ||
key.signatures == null || key.signatures == null ||
key.signatures.isEmpty) { key.signatures?.isEmpty != false) {
continue; continue;
} }
if (!payload.containsKey(key.userId)) { if (!payload.containsKey(key.userId)) {
payload[key.userId] = <String, Map<String, dynamic>>{}; payload[key.userId] = <String, Map<String, dynamic>>{};
} }
if (payload[key.userId].containsKey(key.identifier)) { if (payload[key.userId]?[key.identifier]?['signatures'] != null) {
// we need to merge signature objects // we need to merge signature objects
payload[key.userId][key.identifier]['signatures'] payload[key.userId]![key.identifier]!['signatures']
.addAll(key.signatures); .addAll(key.signatures);
} else { } else {
// we can just add signatures // we can just add signatures
payload[key.userId][key.identifier] = key.toJson(); payload[key.userId]![key.identifier!] = key.toJson();
} }
} }

View File

@ -355,10 +355,10 @@ class Encryption {
final encryptedPayload = <String, dynamic>{ final encryptedPayload = <String, dynamic>{
'algorithm': AlgorithmTypes.megolmV1AesSha2, 'algorithm': AlgorithmTypes.megolmV1AesSha2,
'ciphertext': 'ciphertext':
sess!.outboundGroupSession.encrypt(json.encode(payloadContent)), sess!.outboundGroupSession!.encrypt(json.encode(payloadContent)),
'device_id': client.deviceID, 'device_id': client.deviceID,
'sender_key': identityKey, 'sender_key': identityKey,
'session_id': sess.outboundGroupSession.session_id(), 'session_id': sess.outboundGroupSession!.session_id(),
if (mRelatesTo != null) 'm.relates_to': mRelatesTo, if (mRelatesTo != null) 'm.relates_to': mRelatesTo,
}; };
await keyManager.storeOutboundGroupSession(roomId, sess); await keyManager.storeOutboundGroupSession(roomId, sess);

View File

@ -281,7 +281,7 @@ class KeyManager {
{bool wipe = false, bool use = true}) async { {bool wipe = false, bool use = true}) async {
final room = client.getRoomById(roomId); final room = client.getRoomById(roomId);
final sess = getOutboundGroupSession(roomId); final sess = getOutboundGroupSession(roomId);
if (room == null || sess == null) { if (room == null || sess == null || sess.outboundGroupSession == null) {
return true; return true;
} }
@ -292,7 +292,7 @@ class KeyManager {
final maxMessages = encryptionContent?.rotationPeriodMsgs ?? 100; final maxMessages = encryptionContent?.rotationPeriodMsgs ?? 100;
final maxAge = encryptionContent?.rotationPeriodMs ?? final maxAge = encryptionContent?.rotationPeriodMs ??
604800000; // default of one week 604800000; // default of one week
if (sess.sentMessages >= maxMessages || if ((sess.sentMessages ?? maxMessages) >= maxMessages ||
sess.creationTime sess.creationTime
.add(Duration(milliseconds: maxAge)) .add(Duration(milliseconds: maxAge))
.isBefore(DateTime.now())) { .isBefore(DateTime.now())) {
@ -301,7 +301,7 @@ class KeyManager {
} }
final inboundSess = await loadInboundGroupSession(room.id, final inboundSess = await loadInboundGroupSession(room.id,
sess.outboundGroupSession.session_id(), encryption.identityKey!); sess.outboundGroupSession!.session_id(), encryption.identityKey!);
if (inboundSess == null) { if (inboundSess == null) {
wipe = true; wipe = true;
} }
@ -371,13 +371,12 @@ class KeyManager {
return false; return false;
} }
// okay, we use the outbound group session! // okay, we use the outbound group session!
sess.sentMessages++;
sess.devices = newDeviceKeyIds; sess.devices = newDeviceKeyIds;
final rawSession = <String, dynamic>{ final rawSession = <String, dynamic>{
'algorithm': AlgorithmTypes.megolmV1AesSha2, 'algorithm': AlgorithmTypes.megolmV1AesSha2,
'room_id': room.id, 'room_id': room.id,
'session_id': sess.outboundGroupSession.session_id(), 'session_id': sess.outboundGroupSession!.session_id(),
'session_key': sess.outboundGroupSession.session_key(), 'session_key': sess.outboundGroupSession!.session_key(),
}; };
try { try {
devicesToReceive.removeWhere((k) => !k.encryptToDevice); devicesToReceive.removeWhere((k) => !k.encryptToDevice);
@ -389,17 +388,17 @@ class KeyManager {
.containsKey(device.curve25519Key) || .containsKey(device.curve25519Key) ||
inboundSess.allowedAtIndex[device.userId]![ inboundSess.allowedAtIndex[device.userId]![
device.curve25519Key]! > device.curve25519Key]! >
sess.outboundGroupSession.message_index()) { sess.outboundGroupSession!.message_index()) {
inboundSess inboundSess
.allowedAtIndex[device.userId]![device.curve25519Key!] = .allowedAtIndex[device.userId]![device.curve25519Key!] =
sess.outboundGroupSession.message_index(); sess.outboundGroupSession!.message_index();
} }
} }
if (client.database != null) { if (client.database != null) {
await client.database.updateInboundGroupSessionAllowedAtIndex( await client.database.updateInboundGroupSessionAllowedAtIndex(
json.encode(inboundSess!.allowedAtIndex), json.encode(inboundSess!.allowedAtIndex),
room.id, room.id,
sess.outboundGroupSession.session_id()); sess.outboundGroupSession!.session_id());
} }
// send out the key // send out the key
await client.sendToDeviceEncryptedChunked( await client.sendToDeviceEncryptedChunked(
@ -425,10 +424,9 @@ class KeyManager {
String roomId, OutboundGroupSession sess) async { String roomId, OutboundGroupSession sess) async {
await client.database?.storeOutboundGroupSession( await client.database?.storeOutboundGroupSession(
roomId, roomId,
sess.outboundGroupSession.pickle(client.userID), sess.outboundGroupSession!.pickle(client.userID),
json.encode(sess.devices), json.encode(sess.devices),
sess.creationTime.millisecondsSinceEpoch, sess.creationTime.millisecondsSinceEpoch);
sess.sentMessages);
} }
final Map<String, Future<OutboundGroupSession>> final Map<String, Future<OutboundGroupSession>>
@ -500,7 +498,6 @@ class KeyManager {
devices: deviceKeyIds, devices: deviceKeyIds,
creationTime: DateTime.now(), creationTime: DateTime.now(),
outboundGroupSession: outboundGroupSession, outboundGroupSession: outboundGroupSession,
sentMessages: 0,
key: client.userID, key: client.userID,
); );
try { try {

View File

@ -1,4 +1,3 @@
// @dart=2.9
/* /*
* Famedly Matrix SDK * Famedly Matrix SDK
* Copyright (C) 2020, 2021 Famedly GmbH * Copyright (C) 2020, 2021 Famedly GmbH
@ -50,10 +49,10 @@ class KeyVerificationManager {
if (request.transactionId == null) { if (request.transactionId == null) {
return; return;
} }
_requests[request.transactionId] = request; _requests[request.transactionId!] = request;
} }
KeyVerification getRequest(String requestId) => _requests[requestId]; KeyVerification? getRequest(String requestId) => _requests[requestId];
Future<void> handleToDeviceEvent(ToDeviceEvent event) async { Future<void> handleToDeviceEvent(ToDeviceEvent event) async {
if (!event.type.startsWith('m.key.verification.') || if (!event.type.startsWith('m.key.verification.') ||
@ -65,10 +64,11 @@ class KeyVerificationManager {
if (transactionId == null) { if (transactionId == null) {
return; // TODO: send cancel with unknown transaction id return; // TODO: send cancel with unknown transaction id
} }
if (_requests.containsKey(transactionId)) { final request = _requests[transactionId];
if (request != null) {
// make sure that new requests can't come from ourself // make sure that new requests can't come from ourself
if (!{EventTypes.KeyVerificationRequest}.contains(event.type)) { if (!{EventTypes.KeyVerificationRequest}.contains(event.type)) {
await _requests[transactionId].handlePayload(event.type, event.content); await request.handlePayload(event.type, event.content);
} }
} else { } else {
if (!{EventTypes.KeyVerificationRequest, EventTypes.KeyVerificationStart} if (!{EventTypes.KeyVerificationRequest, EventTypes.KeyVerificationStart}
@ -105,8 +105,8 @@ class KeyVerificationManager {
final transactionId = final transactionId =
KeyVerification.getTransactionId(event['content']) ?? event['event_id']; KeyVerification.getTransactionId(event['content']) ?? event['event_id'];
if (_requests.containsKey(transactionId)) { final req = _requests[transactionId];
final req = _requests[transactionId]; if (req != null) {
final otherDeviceId = event['content']['from_device']; final otherDeviceId = event['content']['from_device'];
if (event['sender'] != client.userID) { if (event['sender'] != client.userID) {
await req.handlePayload(type, event['content'], event['event_id']); await req.handlePayload(type, event['content'], event['event_id']);

View File

@ -145,7 +145,8 @@ class OlmManager {
bool updateDatabase = true, bool updateDatabase = true,
bool? unusedFallbackKey = false, bool? unusedFallbackKey = false,
}) async { }) async {
if (!enabled) { final _olmAccount = this._olmAccount;
if (_olmAccount == null) {
return true; return true;
} }
@ -161,22 +162,22 @@ class OlmManager {
// check if we have OTKs that still need uploading. If we do, we don't try to generate new ones, // check if we have OTKs that still need uploading. If we do, we don't try to generate new ones,
// instead we try to upload the old ones first // instead we try to upload the old ones first
final oldOTKsNeedingUpload = json final oldOTKsNeedingUpload = json
.decode(_olmAccount!.one_time_keys())['curve25519'] .decode(_olmAccount.one_time_keys())['curve25519']
.entries .entries
.length as int; .length as int;
// generate one-time keys // generate one-time keys
// we generate 2/3rds of max, so that other keys people may still have can // we generate 2/3rds of max, so that other keys people may still have can
// still be used // still be used
final oneTimeKeysCount = final oneTimeKeysCount =
(_olmAccount!.max_number_of_one_time_keys() * 2 / 3).floor() - (_olmAccount.max_number_of_one_time_keys() * 2 / 3).floor() -
oldKeyCount - oldKeyCount -
oldOTKsNeedingUpload; oldOTKsNeedingUpload;
if (oneTimeKeysCount > 0) { if (oneTimeKeysCount > 0) {
_olmAccount!.generate_one_time_keys(oneTimeKeysCount); _olmAccount.generate_one_time_keys(oneTimeKeysCount);
} }
uploadedOneTimeKeysCount = oneTimeKeysCount + oldOTKsNeedingUpload; uploadedOneTimeKeysCount = oneTimeKeysCount + oldOTKsNeedingUpload;
final Map<String, dynamic> oneTimeKeys = final Map<String, dynamic> oneTimeKeys =
json.decode(_olmAccount!.one_time_keys()); json.decode(_olmAccount.one_time_keys());
// now sign all the one-time keys // now sign all the one-time keys
for (final entry in oneTimeKeys['curve25519'].entries) { for (final entry in oneTimeKeys['curve25519'].entries) {
@ -191,8 +192,8 @@ class OlmManager {
final signedFallbackKeys = <String, dynamic>{}; final signedFallbackKeys = <String, dynamic>{};
if (encryption.isMinOlmVersion(3, 2, 0) && unusedFallbackKey == false) { if (encryption.isMinOlmVersion(3, 2, 0) && unusedFallbackKey == false) {
// we don't have an unused fallback key uploaded....so let's change that! // we don't have an unused fallback key uploaded....so let's change that!
_olmAccount!.generate_fallback_key(); _olmAccount.generate_fallback_key();
final fallbackKey = json.decode(_olmAccount!.fallback_key()); final fallbackKey = json.decode(_olmAccount.fallback_key());
// now sign all the fallback keys // now sign all the fallback keys
for (final entry in fallbackKey['curve25519'].entries) { for (final entry in fallbackKey['curve25519'].entries) {
final key = entry.key; final key = entry.key;
@ -219,7 +220,7 @@ class OlmManager {
}; };
if (uploadDeviceKeys) { if (uploadDeviceKeys) {
final Map<String, dynamic> keys = final Map<String, dynamic> keys =
json.decode(_olmAccount!.identity_keys()); json.decode(_olmAccount.identity_keys());
for (final entry in keys.entries) { for (final entry in keys.entries) {
final algorithm = entry.key; final algorithm = entry.key;
final value = entry.value; final value = entry.value;
@ -244,7 +245,7 @@ class OlmManager {
fallbackKeys: signedFallbackKeys, fallbackKeys: signedFallbackKeys,
); );
// mark the OTKs as published and save that to datbase // mark the OTKs as published and save that to datbase
_olmAccount!.mark_keys_as_published(); _olmAccount.mark_keys_as_published();
if (updateDatabase) { if (updateDatabase) {
await client.database?.updateClientKeys(pickledOlmAccount!); await client.database?.updateClientKeys(pickledOlmAccount!);
} }
@ -553,14 +554,16 @@ class OlmManager {
client.userDeviceKeys[userId]!.deviceKeys[deviceId]!.curve25519Key; client.userDeviceKeys[userId]!.deviceKeys[deviceId]!.curve25519Key;
for (final Map<String, dynamic> deviceKey for (final Map<String, dynamic> deviceKey
in deviceKeysEntry.value.values) { in deviceKeysEntry.value.values) {
if (!deviceKey.checkJsonSignature(fingerprintKey, userId, deviceId)) { if (fingerprintKey == null ||
identityKey == null ||
!deviceKey.checkJsonSignature(fingerprintKey, userId, deviceId)) {
continue; continue;
} }
Logs().v('[OlmManager] Starting session with $userId:$deviceId'); Logs().v('[OlmManager] Starting session with $userId:$deviceId');
final session = olm.Session(); final session = olm.Session();
try { try {
session.create_outbound( session.create_outbound(
_olmAccount!, identityKey!, deviceKey['key']); _olmAccount!, identityKey, deviceKey['key']);
await storeOlmSession(OlmSession( await storeOlmSession(OlmSession(
key: client.userID, key: client.userID,
identityKey: identityKey, identityKey: identityKey,
@ -666,8 +669,7 @@ class OlmManager {
'[OlmManager] Device ${device.userId}:${device.deviceId} generated a new olm session, replaying last sent message...'); '[OlmManager] Device ${device.userId}:${device.deviceId} generated a new olm session, replaying last sent message...');
final lastSentMessageRes = await client.database final lastSentMessageRes = await client.database
.getLastSentMessageUserDeviceKey(device.userId, device.deviceId!); .getLastSentMessageUserDeviceKey(device.userId, device.deviceId!);
if (lastSentMessageRes.isEmpty || if (lastSentMessageRes.isEmpty || (lastSentMessageRes.first.isEmpty)) {
(lastSentMessageRes.first?.isEmpty ?? true)) {
return; return;
} }
final lastSentMessage = json.decode(lastSentMessageRes.first); final lastSentMessage = json.decode(lastSentMessageRes.first);

View File

@ -1,4 +1,3 @@
// @dart=2.9
/* /*
* Famedly Matrix SDK * Famedly Matrix SDK
* Copyright (C) 2020, 2021 Famedly GmbH * Copyright (C) 2020, 2021 Famedly GmbH

View File

@ -143,7 +143,7 @@ class KeyVerification {
method?.dispose(); method?.dispose();
} }
static String getTransactionId(Map<String, dynamic> payload) { static String? getTransactionId(Map<String, dynamic> payload) {
return payload['transaction_id'] ?? return payload['transaction_id'] ??
(payload['m.relates_to'] is Map (payload['m.relates_to'] is Map
? payload['m.relates_to']['event_id'] ? payload['m.relates_to']['event_id']

View File

@ -1,4 +1,3 @@
// @dart=2.9
/* /*
* Famedly Matrix SDK * Famedly Matrix SDK
* Copyright (C) 2019, 2020, 2021 Famedly GmbH * Copyright (C) 2019, 2020, 2021 Famedly GmbH
@ -28,24 +27,23 @@ class OutboundGroupSession {
/// This way we can easily know if a new user is added, leaves, a new devices is added, and, /// This way we can easily know if a new user is added, leaves, a new devices is added, and,
/// very importantly, if we block a device. These are all important for determining if/when /// very importantly, if we block a device. These are all important for determining if/when
/// an outbound session needs to be rotated. /// an outbound session needs to be rotated.
Map<String, Map<String, bool>> devices; Map<String, Map<String, bool>> devices = {};
DateTime creationTime; // Default to a date, that would get this session rotated in any case to make handling easier
olm.OutboundGroupSession outboundGroupSession; DateTime creationTime = DateTime.fromMillisecondsSinceEpoch(0);
int sentMessages; olm.OutboundGroupSession? outboundGroupSession;
int? get sentMessages => outboundGroupSession?.message_index();
bool get isValid => outboundGroupSession != null; bool get isValid => outboundGroupSession != null;
final String key; final String key;
OutboundGroupSession( OutboundGroupSession(
{this.devices, {required this.devices,
this.creationTime, required this.creationTime,
this.outboundGroupSession, required this.outboundGroupSession,
this.sentMessages, required this.key});
this.key});
OutboundGroupSession.fromJson(Map<String, dynamic> dbEntry, String key) OutboundGroupSession.fromJson(Map<String, dynamic> dbEntry, String key)
: key = key { : key = key {
try { try {
devices = {};
for (final entry in json.decode(dbEntry['device_ids']).entries) { for (final entry in json.decode(dbEntry['device_ids']).entries) {
devices[entry.key] = Map<String, bool>.from(entry.value); devices[entry.key] = Map<String, bool>.from(entry.value);
} }
@ -58,10 +56,9 @@ class OutboundGroupSession {
} }
outboundGroupSession = olm.OutboundGroupSession(); outboundGroupSession = olm.OutboundGroupSession();
try { try {
outboundGroupSession.unpickle(key, dbEntry['pickle']); outboundGroupSession!.unpickle(key, dbEntry['pickle']);
creationTime = creationTime =
DateTime.fromMillisecondsSinceEpoch(dbEntry['creation_time']); DateTime.fromMillisecondsSinceEpoch(dbEntry['creation_time']);
sentMessages = dbEntry['sent_messages'];
} catch (e, s) { } catch (e, s) {
dispose(); dispose();
Logs().e('[LibOlm] Unable to unpickle outboundGroupSession', e, s); Logs().e('[LibOlm] Unable to unpickle outboundGroupSession', e, s);

View File

@ -1,4 +1,3 @@
// @dart=2.9
/* /*
* Famedly Matrix SDK * Famedly Matrix SDK
* Copyright (C) 2021 Famedly GmbH * Copyright (C) 2021 Famedly GmbH
@ -29,15 +28,15 @@ class StoredInboundGroupSession {
final String senderClaimedKeys; final String senderClaimedKeys;
StoredInboundGroupSession({ StoredInboundGroupSession({
this.roomId, required this.roomId,
this.sessionId, required this.sessionId,
this.pickle, required this.pickle,
this.content, required this.content,
this.indexes, required this.indexes,
this.allowedAtIndex, required this.allowedAtIndex,
this.uploaded, required this.uploaded,
this.senderKey, required this.senderKey,
this.senderClaimedKeys, required this.senderClaimedKeys,
}); });
factory StoredInboundGroupSession.fromJson(Map<String, dynamic> json) => factory StoredInboundGroupSession.fromJson(Map<String, dynamic> json) =>

View File

@ -146,7 +146,6 @@ abstract class DatabaseApi {
String pickle, String pickle,
String deviceIds, String deviceIds,
int creationTime, int creationTime,
int sentMessages,
); );
Future updateClientKeys( Future updateClientKeys(

View File

@ -1028,14 +1028,13 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
} }
@override @override
Future<void> storeOutboundGroupSession(String roomId, String pickle, Future<void> storeOutboundGroupSession(
String deviceIds, int creationTime, int sentMessages) async { String roomId, String pickle, String deviceIds, int creationTime) async {
await _outboundGroupSessionsBox.put(roomId.toHiveKey, <String, dynamic>{ await _outboundGroupSessionsBox.put(roomId.toHiveKey, <String, dynamic>{
'room_id': roomId, 'room_id': roomId,
'pickle': pickle, 'pickle': pickle,
'device_ids': deviceIds, 'device_ids': deviceIds,
'creation_time': creationTime, 'creation_time': creationTime,
'sent_messages': sentMessages,
}); });
return; return;
} }

View File

@ -299,7 +299,7 @@ abstract class SignableKey extends MatrixSignableKey {
// or else we just recurse into that key and chack if it works out // or else we just recurse into that key and chack if it works out
final haveChain = key.hasValidSignatureChain( final haveChain = key.hasValidSignatureChain(
verifiedOnly: verifiedOnly, verifiedOnly: verifiedOnly,
visited: visited, visited: visited_,
onlyValidateUserIds: onlyValidateUserIds); onlyValidateUserIds: onlyValidateUserIds);
if (haveChain) { if (haveChain) {
return true; return true;

View File

@ -342,7 +342,6 @@ void testDatabase(
'pickle', 'pickle',
'{}', '{}',
0, 0,
0,
); );
final session = await database.getOutboundGroupSession( final session = await database.getOutboundGroupSession(
'!testroom:example.com', '!testroom:example.com',

View File

@ -99,7 +99,7 @@ void main() {
]); ]);
final body = json.decode(FakeMatrixApi final body = json.decode(FakeMatrixApi
.calledEndpoints['/client/r0/keys/signatures/upload'].first); .calledEndpoints['/client/r0/keys/signatures/upload'].first);
expect(body['@test:fakeServer.notExisting'].containsKey('OTHERDEVICE'), expect(body['@test:fakeServer.notExisting']?.containsKey('OTHERDEVICE'),
true); true);
expect( expect(
body['@test:fakeServer.notExisting'].containsKey( body['@test:fakeServer.notExisting'].containsKey(

View File

@ -124,7 +124,9 @@ void main() {
0); 0);
// rotate after too many messages // rotate after too many messages
sess.sentMessages = 300; Iterable.generate(300).forEach((_) {
sess.outboundGroupSession.encrypt('some string');
});
await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId); await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId);
expect( expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null, client.encryption.keyManager.getOutboundGroupSession(roomId) != null,