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:
commit
2a280cec98
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue