Merge pull request #1584 from famedly/td/fixAwaitSecrets
fix: validate account_data values instead of checking them in syncUpdates
This commit is contained in:
commit
067a61ed18
|
|
@ -248,15 +248,16 @@ class SSSS {
|
|||
}()
|
||||
.firstWhere((keyId) => getKey(keyId) == null);
|
||||
|
||||
final accountDataType = EventTypes.secretStorageKey(keyId);
|
||||
final accountDataTypeKeyId = EventTypes.secretStorageKey(keyId);
|
||||
// noooow we set the account data
|
||||
final waitForAccountData = client.onSync.stream.firstWhere((syncUpdate) =>
|
||||
syncUpdate.accountData != null &&
|
||||
syncUpdate.accountData!
|
||||
.any((accountData) => accountData.type == accountDataType));
|
||||
|
||||
await client.setAccountData(
|
||||
client.userID!, accountDataType, content.toJson());
|
||||
await waitForAccountData;
|
||||
client.userID!, accountDataTypeKeyId, content.toJson());
|
||||
|
||||
while (!client.accountData.containsKey(accountDataTypeKeyId)) {
|
||||
Logs().v('Waiting accountData to have $accountDataTypeKeyId');
|
||||
await client.oneShotSync();
|
||||
}
|
||||
|
||||
final key = open(keyId);
|
||||
await key.setPrivateKey(privateKey);
|
||||
|
|
@ -327,7 +328,7 @@ class SSSS {
|
|||
}
|
||||
final enc = encryptedContent.tryGetMap<String, Object?>(keyId);
|
||||
if (enc == null) {
|
||||
throw Exception('Wrong / unknown key');
|
||||
throw Exception('Wrong / unknown key: $type, $keyId');
|
||||
}
|
||||
final ciphertext = enc.tryGet<String>('ciphertext');
|
||||
final iv = enc.tryGet<String>('iv');
|
||||
|
|
@ -750,6 +751,14 @@ class OpenSSSS {
|
|||
throw Exception('SSSS not unlocked');
|
||||
}
|
||||
await ssss.store(type, secret, keyId, privateKey, add: add);
|
||||
while (!ssss.client.accountData.containsKey(type) ||
|
||||
!(ssss.client.accountData[type]!.content
|
||||
.tryGetMap<String, Object?>('encrypted')!
|
||||
.containsKey(keyId)) ||
|
||||
await getStored(type) != secret) {
|
||||
Logs().d('Wait for secret of $type to match in accountdata');
|
||||
await ssss.client.oneShotSync();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> validateAndStripOtherKeys(String type, String secret) async {
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ class Bootstrap {
|
|||
|
||||
// cache the secret analyzing so that we don't drop stuff a different client sets during bootstrapping
|
||||
Map<String, Set<String>>? _secretsCache;
|
||||
|
||||
/// returns ssss from accountdata, eg: m.megolm_backup.v1, or your m.cross_signing stuff
|
||||
Map<String, Set<String>> analyzeSecrets() {
|
||||
final secretsCache = _secretsCache;
|
||||
if (secretsCache != null) {
|
||||
|
|
@ -292,12 +294,12 @@ class Bootstrap {
|
|||
}
|
||||
// alright, we re-encrypted all the secrets. We delete the dead weight only *after* we set our key to the default key
|
||||
}
|
||||
final updatedAccountData = client.onSync.stream.firstWhere((syncUpdate) =>
|
||||
syncUpdate.accountData != null &&
|
||||
syncUpdate.accountData!.any((accountData) =>
|
||||
accountData.type == EventTypes.SecretStorageDefaultKey));
|
||||
await encryption.ssss.setDefaultKeyId(newSsssKey!.keyId);
|
||||
await updatedAccountData;
|
||||
while (encryption.ssss.defaultKeyId != newSsssKey!.keyId) {
|
||||
Logs().v(
|
||||
'Waiting accountData to have the correct m.secret_storage.default_key');
|
||||
await client.oneShotSync();
|
||||
}
|
||||
if (oldSsssKeys != null) {
|
||||
for (final entry in secretMap!.entries) {
|
||||
Logs().v('Validate and stripe other keys ${entry.key}...');
|
||||
|
|
@ -479,33 +481,23 @@ class Bootstrap {
|
|||
));
|
||||
Logs().v('Device signing keys have been uploaded.');
|
||||
// aaaand set the SSSS secrets
|
||||
final futures = <Future<void>>[];
|
||||
if (masterKey != null) {
|
||||
futures.add(
|
||||
client.onSync.stream
|
||||
.firstWhere((syncUpdate) =>
|
||||
masterKey?.publicKey != null &&
|
||||
client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key ==
|
||||
masterKey?.publicKey)
|
||||
.then((_) => Logs().v('New Master Key was created')),
|
||||
);
|
||||
while (!(masterKey.publicKey != null &&
|
||||
client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key ==
|
||||
masterKey.publicKey)) {
|
||||
Logs().v('Waiting for master to be created');
|
||||
await client.oneShotSync();
|
||||
}
|
||||
}
|
||||
for (final entry in secretsToStore.entries) {
|
||||
futures.add(
|
||||
client.onSync.stream
|
||||
.firstWhere((syncUpdate) =>
|
||||
syncUpdate.accountData != null &&
|
||||
syncUpdate.accountData!
|
||||
.any((accountData) => accountData.type == entry.key))
|
||||
.then((_) =>
|
||||
Logs().v('New Key with type ${entry.key} was created')),
|
||||
);
|
||||
Logs().v('Store new SSSS key ${entry.key}...');
|
||||
await newSsssKey?.store(entry.key, entry.value);
|
||||
if (newSsssKey != null) {
|
||||
final storeFutures = <Future<void>>[];
|
||||
for (final entry in secretsToStore.entries) {
|
||||
storeFutures.add(newSsssKey!.store(entry.key, entry.value));
|
||||
}
|
||||
Logs().v('Store new SSSS key entries...');
|
||||
await Future.wait(storeFutures);
|
||||
}
|
||||
Logs().v(
|
||||
'Wait for MasterKey and ${secretsToStore.entries.length} keys to be created');
|
||||
await Future.wait<void>(futures);
|
||||
|
||||
final keysToSign = <SignableKey>[];
|
||||
if (masterKey != null) {
|
||||
if (client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key !=
|
||||
|
|
@ -581,14 +573,6 @@ class Bootstrap {
|
|||
);
|
||||
Logs().v('Store the secret...');
|
||||
await newSsssKey?.store(megolmKey, base64.encode(privKey));
|
||||
Logs().v('Wait for secret to come down sync');
|
||||
|
||||
if (!await encryption.keyManager.isCached()) {
|
||||
await client.onSync.stream.firstWhere((syncUpdate) =>
|
||||
syncUpdate.accountData != null &&
|
||||
syncUpdate.accountData!
|
||||
.any((accountData) => accountData.type == megolmKey));
|
||||
}
|
||||
|
||||
Logs().v(
|
||||
'And finally set all megolm keys as needing to be uploaded again...');
|
||||
|
|
|
|||
|
|
@ -107,9 +107,12 @@ void main() {
|
|||
await handle.unlock(recoveryKey: ssssKey);
|
||||
expect(handle.isUnlocked, true);
|
||||
FakeMatrixApi.calledEndpoints.clear();
|
||||
await handle.store('best animal', 'foxies');
|
||||
// alright, since we don't properly sync we will manually have to update
|
||||
// account_data for this test
|
||||
|
||||
// OpenSSSS store waits for accountdata to be updated before returning
|
||||
// but we can't update that before the below endpoint is not hit.
|
||||
await handle.ssss
|
||||
.store('best animal', 'foxies', handle.keyId, handle.privateKey!);
|
||||
|
||||
final content = FakeMatrixApi
|
||||
.calledEndpoints[
|
||||
'/client/v3/user/%40test%3AfakeServer.notExisting/account_data/best%20animal']!
|
||||
|
|
|
|||
Loading…
Reference in New Issue