fix: Remove potential race conditions and database issues with OTK upload
This commit is contained in:
parent
b5ac500136
commit
2c7ae759f8
|
@ -68,7 +68,7 @@ class Encryption {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeviceOneTimeKeysCount(Map<String, int> countJson) {
|
void handleDeviceOneTimeKeysCount(Map<String, int> countJson) {
|
||||||
olmManager.handleDeviceOneTimeKeysCount(countJson);
|
Zone.root.run(() => olmManager.handleDeviceOneTimeKeysCount(countJson));
|
||||||
}
|
}
|
||||||
|
|
||||||
void onSync() {
|
void onSync() {
|
||||||
|
|
|
@ -130,6 +130,8 @@ class OlmManager {
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _uploadKeysLock = false;
|
||||||
|
|
||||||
/// Generates new one time keys, signs everything and upload it to the server.
|
/// Generates new one time keys, signs everything and upload it to the server.
|
||||||
Future<bool> uploadKeys(
|
Future<bool> uploadKeys(
|
||||||
{bool uploadDeviceKeys = false, int oldKeyCount = 0}) async {
|
{bool uploadDeviceKeys = false, int oldKeyCount = 0}) async {
|
||||||
|
@ -137,62 +139,71 @@ class OlmManager {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate one-time keys
|
if (_uploadKeysLock) {
|
||||||
// we generate 2/3rds of max, so that other keys people may still have can
|
return false;
|
||||||
// still be used
|
|
||||||
final oneTimeKeysCount =
|
|
||||||
(_olmAccount.max_number_of_one_time_keys() * 2 / 3).floor() -
|
|
||||||
oldKeyCount;
|
|
||||||
_olmAccount.generate_one_time_keys(oneTimeKeysCount);
|
|
||||||
final Map<String, dynamic> oneTimeKeys =
|
|
||||||
json.decode(_olmAccount.one_time_keys());
|
|
||||||
|
|
||||||
// now sign all the one-time keys
|
|
||||||
final signedOneTimeKeys = <String, dynamic>{};
|
|
||||||
for (final entry in oneTimeKeys['curve25519'].entries) {
|
|
||||||
final key = entry.key;
|
|
||||||
final value = entry.value;
|
|
||||||
signedOneTimeKeys['signed_curve25519:$key'] = <String, dynamic>{};
|
|
||||||
signedOneTimeKeys['signed_curve25519:$key'] = signJson({
|
|
||||||
'key': value,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
_uploadKeysLock = true;
|
||||||
|
|
||||||
// and now generate the payload to upload
|
try {
|
||||||
final keysContent = <String, dynamic>{
|
// generate one-time keys
|
||||||
if (uploadDeviceKeys)
|
// we generate 2/3rds of max, so that other keys people may still have can
|
||||||
'device_keys': {
|
// still be used
|
||||||
'user_id': client.userID,
|
final oneTimeKeysCount =
|
||||||
'device_id': client.deviceID,
|
(_olmAccount.max_number_of_one_time_keys() * 2 / 3).floor() -
|
||||||
'algorithms': [
|
oldKeyCount;
|
||||||
'm.olm.v1.curve25519-aes-sha2',
|
_olmAccount.generate_one_time_keys(oneTimeKeysCount);
|
||||||
'm.megolm.v1.aes-sha2'
|
final Map<String, dynamic> oneTimeKeys =
|
||||||
],
|
json.decode(_olmAccount.one_time_keys());
|
||||||
'keys': <String, dynamic>{},
|
|
||||||
},
|
// now sign all the one-time keys
|
||||||
};
|
final signedOneTimeKeys = <String, dynamic>{};
|
||||||
if (uploadDeviceKeys) {
|
for (final entry in oneTimeKeys['curve25519'].entries) {
|
||||||
final Map<String, dynamic> keys =
|
final key = entry.key;
|
||||||
json.decode(_olmAccount.identity_keys());
|
|
||||||
for (final entry in keys.entries) {
|
|
||||||
final algorithm = entry.key;
|
|
||||||
final value = entry.value;
|
final value = entry.value;
|
||||||
keysContent['device_keys']['keys']['$algorithm:${client.deviceID}'] =
|
signedOneTimeKeys['signed_curve25519:$key'] = <String, dynamic>{};
|
||||||
value;
|
signedOneTimeKeys['signed_curve25519:$key'] = signJson({
|
||||||
|
'key': value,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
keysContent['device_keys'] =
|
|
||||||
signJson(keysContent['device_keys'] as Map<String, dynamic>);
|
|
||||||
}
|
|
||||||
|
|
||||||
final response = await client.uploadDeviceKeys(
|
// and now generate the payload to upload
|
||||||
deviceKeys: uploadDeviceKeys
|
final keysContent = <String, dynamic>{
|
||||||
? MatrixDeviceKeys.fromJson(keysContent['device_keys'])
|
if (uploadDeviceKeys)
|
||||||
: null,
|
'device_keys': {
|
||||||
oneTimeKeys: signedOneTimeKeys,
|
'user_id': client.userID,
|
||||||
);
|
'device_id': client.deviceID,
|
||||||
_olmAccount.mark_keys_as_published();
|
'algorithms': [
|
||||||
await client.database?.updateClientKeys(pickledOlmAccount, client.id);
|
'm.olm.v1.curve25519-aes-sha2',
|
||||||
return response['signed_curve25519'] == oneTimeKeysCount;
|
'm.megolm.v1.aes-sha2'
|
||||||
|
],
|
||||||
|
'keys': <String, dynamic>{},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (uploadDeviceKeys) {
|
||||||
|
final Map<String, dynamic> keys =
|
||||||
|
json.decode(_olmAccount.identity_keys());
|
||||||
|
for (final entry in keys.entries) {
|
||||||
|
final algorithm = entry.key;
|
||||||
|
final value = entry.value;
|
||||||
|
keysContent['device_keys']['keys']['$algorithm:${client.deviceID}'] =
|
||||||
|
value;
|
||||||
|
}
|
||||||
|
keysContent['device_keys'] =
|
||||||
|
signJson(keysContent['device_keys'] as Map<String, dynamic>);
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await client.uploadDeviceKeys(
|
||||||
|
deviceKeys: uploadDeviceKeys
|
||||||
|
? MatrixDeviceKeys.fromJson(keysContent['device_keys'])
|
||||||
|
: null,
|
||||||
|
oneTimeKeys: signedOneTimeKeys,
|
||||||
|
);
|
||||||
|
_olmAccount.mark_keys_as_published();
|
||||||
|
await client.database?.updateClientKeys(pickledOlmAccount, client.id);
|
||||||
|
return response['signed_curve25519'] == oneTimeKeysCount;
|
||||||
|
} finally {
|
||||||
|
_uploadKeysLock = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeviceOneTimeKeysCount(Map<String, int> countJson) {
|
void handleDeviceOneTimeKeysCount(Map<String, int> countJson) {
|
||||||
|
|
Loading…
Reference in a new issue