migrateSecretsToKey method

Future<Set<String>> migrateSecretsToKey({
  1. required OpenSSSS primaryUnlockedKey,
  2. required OpenSSSS destinationKey,
  3. String? unlockCredential,
  4. Map<String, OpenSSSS>? candidateOldKeys,
  5. bool stripKeys = false,
  6. bool stripAsDefaultKey = true,
})

Migrates available secrets from old keys to destinationKey.

Returns the set of secret types that were successfully migrated.

Implementation

Future<Set<String>> migrateSecretsToKey({
  required OpenSSSS primaryUnlockedKey,
  required OpenSSSS destinationKey,
  String? unlockCredential,
  Map<String, OpenSSSS>? candidateOldKeys,
  bool stripKeys = false,
  bool stripAsDefaultKey = true,
}) async {
  final remainingSecrets = analyzeEncryptedSecrets();
  final keyIds =
      orderedCandidateKeyIds(remainingSecrets, primaryUnlockedKey.keyId);
  if (keyIds.isEmpty) return {};

  final migratedSecretTypes = <String>{};
  Set<String> candidateSecretsForKey(String keyId) {
    return remainingSecrets.entries
        .where((entry) => entry.value.contains(keyId))
        .map((entry) => entry.key)
        .toSet();
  }

  for (final keyId in keyIds) {
    final key = keyId == primaryUnlockedKey.keyId
        ? primaryUnlockedKey
        : candidateOldKeys?[keyId] ??
            await _tryOpenAndUnlockKey(
              keyId,
              unlockCredential: unlockCredential,
            );
    if (key == null || !key.isUnlocked) continue;

    for (final secretType in candidateSecretsForKey(keyId)) {
      try {
        final secret = await key.getStored(secretType);
        await destinationKey.store(secretType, secret, add: true);
        migratedSecretTypes.add(secretType);
        remainingSecrets.remove(secretType);
      } catch (e, s) {
        Logs().v(
          'Could not migrate $secretType using SSSS key $keyId',
          e,
          s,
        );
      }
    }
    if (remainingSecrets.isEmpty) break;
  }
  if (stripKeys) {
    await _validateAndStripMigratedSecrets(
      destinationKey: destinationKey,
      migratedSecretTypes: migratedSecretTypes,
      isDefaultKey: stripAsDefaultKey,
    );
  }
  return migratedSecretTypes;
}