Merge pull request #2018 from famedly/krille/make-share-keys-with-configurable

feat: (BREAKING) Make share keys with logic configurable
This commit is contained in:
td 2025-02-05 14:24:09 +01:00 committed by GitHub
commit a3d33eee65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 56 additions and 6 deletions

View File

@ -90,7 +90,7 @@ class Client extends MatrixApi {
final bool mxidLocalPartFallback;
bool shareKeysWithUnverifiedDevices;
ShareKeysWith shareKeysWith;
Future<void> Function(Client client)? onSoftLogout;
@ -219,7 +219,7 @@ class Client extends MatrixApi {
Duration defaultNetworkRequestTimeout = const Duration(seconds: 35),
this.sendTimelineEventTimeout = const Duration(minutes: 1),
this.customImageResizer,
this.shareKeysWithUnverifiedDevices = true,
this.shareKeysWith = ShareKeysWith.crossVerifiedIfEnabled,
this.enableDehydratedDevices = false,
this.receiptsPublicByDefault = true,
@ -4082,3 +4082,25 @@ enum InitState {
/// Initialization has been completed with an error.
error,
}
/// Sets the security level with which devices keys should be shared with
enum ShareKeysWith {
/// Keys are shared with all devices if they are not explicitely blocked
all,
/// Once a user has enabled cross signing, keys are no longer shared with
/// devices which are not cross verified by the cross signing keys of this
/// user. This does not require that the user needs to be verified.
crossVerifiedIfEnabled,
/// Keys are only shared with cross verified devices. If a user has not
/// enabled cross signing, then all devices must be verified manually first.
/// This does not require that the user needs to be verified.
crossVerified,
/// Keys are only shared with direct verified devices. So either the device
/// or the user must be manually verified first, before keys are shared. By
/// using cross signing, it is enough to verify the user and then the user
/// can verify their devices.
directlyVerifiedOnly,
}

View File

@ -163,7 +163,17 @@ abstract class SignableKey extends MatrixSignableKey {
if (identifier == null || ed25519Key == null) return false;
return client.shareKeysWithUnverifiedDevices || verified;
switch (client.shareKeysWith) {
case ShareKeysWith.all:
return true;
case ShareKeysWith.crossVerifiedIfEnabled:
if (client.userDeviceKeys[userId]?.masterKey == null) return true;
return hasValidSignatureChain(verifiedByTheirMasterKey: true);
case ShareKeysWith.crossVerified:
return hasValidSignatureChain(verifiedByTheirMasterKey: true);
case ShareKeysWith.directlyVerifiedOnly:
return directVerified;
}
}
void setDirectVerified(bool isVerified) {

View File

@ -150,11 +150,29 @@ void main() {
},
client,
);
expect(client.shareKeysWithUnverifiedDevices, true);
client.shareKeysWith = ShareKeysWith.all;
expect(key.encryptToDevice, true);
client.shareKeysWithUnverifiedDevices = false;
client.shareKeysWith = ShareKeysWith.directlyVerifiedOnly;
expect(key.encryptToDevice, false);
client.shareKeysWithUnverifiedDevices = true;
await key.setVerified(true);
expect(key.encryptToDevice, true);
await key.setVerified(false);
client.shareKeysWith = ShareKeysWith.crossVerified;
expect(key.encryptToDevice, true);
client.shareKeysWith = ShareKeysWith.crossVerified;
// Disable cross signing for this user manually so encryptToDevice should return `false`
final dropUserDeviceKeys = client.userDeviceKeys.remove(key.userId);
expect(key.encryptToDevice, false);
// But crossVerifiedIfEnabled should return `true` now:
client.shareKeysWith = ShareKeysWith.crossVerifiedIfEnabled;
expect(key.encryptToDevice, true);
client.userDeviceKeys[key.userId] = dropUserDeviceKeys!;
client.shareKeysWith = ShareKeysWith.all;
final masterKey = client.userDeviceKeys[client.userID]!.masterKey!;
masterKey.setDirectVerified(true);
// we need to populate the ssss cache to be able to test signing easily