Merge branch 'krille/share-keys-with-unknown-devices' into 'main'

feat: Calc encryption health state and allow key sharing with unknown devices

Closes #307

See merge request famedly/company/frontend/famedlysdk!1072
This commit is contained in:
Krille Fear 2022-07-09 07:50:32 +00:00
commit 2a280cec98
5 changed files with 48 additions and 8 deletions

View File

@ -83,6 +83,8 @@ class Client extends MatrixApi {
final bool mxidLocalPartFallback; final bool mxidLocalPartFallback;
bool shareKeysWithUnverifiedDevices;
// For CommandsClientExtension // For CommandsClientExtension
final Map<String, FutureOr<String?> Function(CommandArgs)> commands = {}; final Map<String, FutureOr<String?> Function(CommandArgs)> commands = {};
final Filter syncFilter; final Filter syncFilter;
@ -167,6 +169,7 @@ class Client extends MatrixApi {
Filter? syncFilter, Filter? syncFilter,
this.sendTimelineEventTimeout = const Duration(minutes: 1), this.sendTimelineEventTimeout = const Duration(minutes: 1),
this.customImageResizer, this.customImageResizer,
this.shareKeysWithUnverifiedDevices = true,
}) : syncFilter = syncFilter ?? }) : syncFilter = syncFilter ??
Filter( Filter(
room: RoomFilter( room: RoomFilter(

View File

@ -852,6 +852,26 @@ class Room {
return eventId; return eventId;
} }
/// Calculates how secure the communication is. When all devices are blocked or
/// verified, then this returns [EncryptionHealthState.allVerified]. When at
/// least one device is not verified, then it returns
/// [EncryptionHealthState.unverifiedDevices]. Apps should display this health
/// state next to the input text field to inform the user about the current
/// encryption security level.
Future<EncryptionHealthState> calcEncryptionHealthState() async {
final users = await requestParticipants();
users.removeWhere((u) =>
!{Membership.invite, Membership.join}.contains(u.membership) ||
!client.userDeviceKeys.containsKey(u.id));
if (users.any((u) =>
client.userDeviceKeys[u.id]!.verified != UserVerifiedStatus.verified)) {
return EncryptionHealthState.unverifiedDevices;
}
return EncryptionHealthState.allVerified;
}
Future<String?> _sendContent( Future<String?> _sendContent(
String type, String type,
Map<String, dynamic> content, { Map<String, dynamic> content, {
@ -1977,3 +1997,8 @@ class Room {
@override @override
bool operator ==(dynamic other) => (other is Room && other.id == id); bool operator ==(dynamic other) => (other is Room && other.id == id);
} }
enum EncryptionHealthState {
allVerified,
unverifiedDevices,
}

View File

@ -151,13 +151,13 @@ abstract class SignableKey extends MatrixSignableKey {
bool get blocked => _blocked ?? false; bool get blocked => _blocked ?? false;
set blocked(bool b) => _blocked = b; set blocked(bool b) => _blocked = b;
bool get encryptToDevice => bool get encryptToDevice {
!(blocked) && if (blocked) return false;
identifier != null &&
ed25519Key != null && if (identifier == null || ed25519Key == null) return false;
(client.userDeviceKeys[userId]?.masterKey?.verified ?? false
? verified return client.shareKeysWithUnverifiedDevices || verified;
: true); }
void setDirectVerified(bool v) { void setDirectVerified(bool v) {
_verified = v; _verified = v;

View File

@ -156,6 +156,11 @@ void main() {
}, },
}, },
}, client); }, client);
expect(client.shareKeysWithUnverifiedDevices, true);
expect(key.encryptToDevice, true);
client.shareKeysWithUnverifiedDevices = false;
expect(key.encryptToDevice, false);
client.shareKeysWithUnverifiedDevices = true;
final masterKey = client.userDeviceKeys[client.userID]!.masterKey!; final masterKey = client.userDeviceKeys[client.userID]!.masterKey!;
masterKey.setDirectVerified(true); masterKey.setDirectVerified(true);
// we need to populate the ssss cache to be able to test signing easily // we need to populate the ssss cache to be able to test signing easily
@ -175,7 +180,7 @@ void main() {
expect( expect(
client.userDeviceKeys[client.userID]?.deviceKeys['UNSIGNEDDEVICE'] client.userDeviceKeys[client.userID]?.deviceKeys['UNSIGNEDDEVICE']
?.encryptToDevice, ?.encryptToDevice,
false); true);
expect(masterKey.verified, true); expect(masterKey.verified, true);
await masterKey.setBlocked(true); await masterKey.setBlocked(true);

View File

@ -349,6 +349,13 @@ void main() {
expect(user.room.id, '!localpart:server.abc'); expect(user.room.id, '!localpart:server.abc');
}); });
test('calcEncryptionHealthState', () async {
expect(
await room.calcEncryptionHealthState(),
EncryptionHealthState.unverifiedDevices,
);
});
test('getEventByID', () async { test('getEventByID', () async {
final event = await room.getEventById('1234'); final event = await room.getEventById('1234');
expect(event?.eventId, '143273582443PhrSn:example.org'); expect(event?.eventId, '143273582443PhrSn:example.org');