feat: Calc encryption health state and allow key sharing with unknown devices
In order to allow key sharing with unknown devices (master key has been verified but this device is not signed by this master key) the user should at least be informed. This makes it possible to set in the client constructor whether the app should share keys with unverified devices or unknown devices.
This commit is contained in:
parent
01e16506dc
commit
28231936b1
|
|
@ -83,6 +83,8 @@ class Client extends MatrixApi {
|
|||
|
||||
final bool mxidLocalPartFallback;
|
||||
|
||||
bool shareKeysWithUnverifiedDevices;
|
||||
|
||||
// For CommandsClientExtension
|
||||
final Map<String, FutureOr<String?> Function(CommandArgs)> commands = {};
|
||||
final Filter syncFilter;
|
||||
|
|
@ -167,6 +169,7 @@ class Client extends MatrixApi {
|
|||
Filter? syncFilter,
|
||||
this.sendTimelineEventTimeout = const Duration(minutes: 1),
|
||||
this.customImageResizer,
|
||||
this.shareKeysWithUnverifiedDevices = true,
|
||||
}) : syncFilter = syncFilter ??
|
||||
Filter(
|
||||
room: RoomFilter(
|
||||
|
|
|
|||
|
|
@ -852,6 +852,26 @@ class Room {
|
|||
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(
|
||||
String type,
|
||||
Map<String, dynamic> content, {
|
||||
|
|
@ -1977,3 +1997,8 @@ class Room {
|
|||
@override
|
||||
bool operator ==(dynamic other) => (other is Room && other.id == id);
|
||||
}
|
||||
|
||||
enum EncryptionHealthState {
|
||||
allVerified,
|
||||
unverifiedDevices,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,13 +151,13 @@ abstract class SignableKey extends MatrixSignableKey {
|
|||
bool get blocked => _blocked ?? false;
|
||||
set blocked(bool b) => _blocked = b;
|
||||
|
||||
bool get encryptToDevice =>
|
||||
!(blocked) &&
|
||||
identifier != null &&
|
||||
ed25519Key != null &&
|
||||
(client.userDeviceKeys[userId]?.masterKey?.verified ?? false
|
||||
? verified
|
||||
: true);
|
||||
bool get encryptToDevice {
|
||||
if (blocked) return false;
|
||||
|
||||
if (identifier == null || ed25519Key == null) return false;
|
||||
|
||||
return client.shareKeysWithUnverifiedDevices || verified;
|
||||
}
|
||||
|
||||
void setDirectVerified(bool v) {
|
||||
_verified = v;
|
||||
|
|
|
|||
|
|
@ -156,6 +156,11 @@ void main() {
|
|||
},
|
||||
},
|
||||
}, 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!;
|
||||
masterKey.setDirectVerified(true);
|
||||
// we need to populate the ssss cache to be able to test signing easily
|
||||
|
|
@ -175,7 +180,7 @@ void main() {
|
|||
expect(
|
||||
client.userDeviceKeys[client.userID]?.deviceKeys['UNSIGNEDDEVICE']
|
||||
?.encryptToDevice,
|
||||
false);
|
||||
true);
|
||||
|
||||
expect(masterKey.verified, true);
|
||||
await masterKey.setBlocked(true);
|
||||
|
|
|
|||
|
|
@ -349,6 +349,13 @@ void main() {
|
|||
expect(user.room.id, '!localpart:server.abc');
|
||||
});
|
||||
|
||||
test('calcEncryptionHealthState', () async {
|
||||
expect(
|
||||
await room.calcEncryptionHealthState(),
|
||||
EncryptionHealthState.unverifiedDevices,
|
||||
);
|
||||
});
|
||||
|
||||
test('getEventByID', () async {
|
||||
final event = await room.getEventById('1234');
|
||||
expect(event?.eventId, '143273582443PhrSn:example.org');
|
||||
|
|
|
|||
Loading…
Reference in New Issue