diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index ea4575dc7..7b4e862e8 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -28,11 +28,10 @@ class BackupService { : _cipher = Cryptography.instance.chacha20Poly1305Aead(), _correctWallets = []; - static const currentVersion = _v3; + static const currentVersion = _v2; static const _v1 = 1; static const _v2 = 2; - static const _v3 = 3; final Cipher _cipher; final FlutterSecureStorage _flutterSecureStorage; @@ -54,9 +53,6 @@ class BackupService { case _v2: await _importBackupV2(data, password); break; - case _v3: - await _importBackupV3(data, password); - break; default: break; } @@ -69,8 +65,6 @@ class BackupService { return await _exportBackupV1(password, nonce: nonce); case _v2: return await _exportBackupV2(password); - case _v3: - return await _exportBackupV3(password); default: throw Exception('Incorrect version: $version for exportBackup'); } @@ -80,16 +74,14 @@ class BackupService { Future _exportBackupV1(String password, {String nonce = secrets.backupSalt}) async => throw Exception('Deprecated. Export for backups v1 is deprecated. Please use export v2.'); - Future _exportBackupV2(String password, {bool keychainV3 = false}) async { + Future _exportBackupV2(String password) async { final zipEncoder = ZipFileEncoder(); final appDir = await getApplicationDocumentsDirectory(); final now = DateTime.now(); final tmpDir = Directory('${appDir.path}/~_BACKUP_TMP'); final archivePath = '${tmpDir.path}/backup_${now.toString()}.zip'; final fileEntities = appDir.listSync(recursive: false); - final keychainDump = keychainV3 - ? (await _exportKeychainDumpV2(password)) - : (await _exportKeychainDumpV3(password)); + final keychainDump = await _exportKeychainDumpV2(password); final preferencesDump = await _exportPreferencesJSON(); final preferencesDumpFile = File('${tmpDir.path}/~_preferences_dump_TMP'); final keychainDumpFile = File('${tmpDir.path}/~_keychain_dump_TMP'); @@ -123,10 +115,6 @@ class BackupService { return await _encryptV2(content, password); } - Future _exportBackupV3(String password) async { - return await _exportBackupV2(password, keychainV3: true); - } - Future _importBackupV1(Uint8List data, String password, {required String nonce}) async { final appDir = await getApplicationDocumentsDirectory(); final decryptedData = await _decryptV1(data, password, nonce); @@ -150,7 +138,7 @@ class BackupService { await _importPreferencesDump(); } - Future _importBackupV2(Uint8List data, String password, {bool keychainV3 = false}) async { + Future _importBackupV2(Uint8List data, String password) async { final appDir = await getApplicationDocumentsDirectory(); final decryptedData = await _decryptV2(data, password); final zip = ZipDecoder().decodeBytes(decryptedData); @@ -169,18 +157,10 @@ class BackupService { }); await _verifyWallets(); - if (keychainV3) { - await _importKeychainDumpV3(password); - } else { - await _importKeychainDumpV2(password); - } + await _importKeychainDumpV2(password); await _importPreferencesDump(); } - Future _importBackupV3(Uint8List data, String password) async { - await _importBackupV2(data, password, keychainV3: true); - } - Future _verifyWallets() async { final walletInfoSource = await _reloadHiveWalletInfoBox(); _correctWallets = @@ -465,6 +445,7 @@ class BackupService { }); await _flutterSecureStorage.delete(key: pinCodeKey); + // we know it's the old pin format since it's a v1 import: await _flutterSecureStorage.write( key: pinCodeKey, value: (await argon2Hash(password: decodedPin))); @@ -480,7 +461,7 @@ class BackupService { final keychainJSON = json.decode(utf8.decode(decryptedKeychainDumpFileData)) as Map; final keychainWalletsInfo = keychainJSON['wallets'] as List; - final decodedPin = keychainJSON['pin'] as String; + final potentiallyDecodedPin = keychainJSON['pin'] as String; final pinCodeKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; @@ -493,34 +474,13 @@ class BackupService { await importWalletKeychainInfo(info); }); - await _flutterSecureStorage.delete(key: pinCodeKey); - await _flutterSecureStorage.write( - key: pinCodeKey, value: (await argon2Hash(password: decodedPin))); - - keychainDumpFile.deleteSync(); - } - - Future _importKeychainDumpV3(String password, - {String keychainSalt = secrets.backupKeychainSalt}) async { - final appDir = await getApplicationDocumentsDirectory(); - final keychainDumpFile = File('${appDir.path}/~_keychain_dump'); - final decryptedKeychainDumpFileData = - await _decryptV3(keychainDumpFile.readAsBytesSync(), '$keychainSalt$password'); - final keychainJSON = - json.decode(utf8.decode(decryptedKeychainDumpFileData)) as Map; - final keychainWalletsInfo = keychainJSON['wallets'] as List; - final encodedPin = keychainJSON['pin'] as String; - final pinCodeKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); - final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); - final backupPassword = keychainJSON[backupPasswordKey] as String; - - await _flutterSecureStorage.delete(key: backupPasswordKey); - await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword); - - keychainWalletsInfo.forEach((dynamic rawInfo) async { - final info = rawInfo as Map; - await importWalletKeychainInfo(info); - }); + late String encodedPin; + // not a formal check but an argon2 hash is always going to be > 10 characters long (and decoded pins either 4 or 6) + if (potentiallyDecodedPin.length < 10) { + encodedPin = await argon2Hash(password: potentiallyDecodedPin); + } else { + encodedPin = potentiallyDecodedPin; + } await _flutterSecureStorage.delete(key: pinCodeKey); await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPin); @@ -561,26 +521,6 @@ class BackupService { return encrypted; } - Future _exportKeychainDumpV3(String password, - {String keychainSalt = secrets.backupKeychainSalt}) async { - final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); - final encodedPin = await _flutterSecureStorage.read(key: key); - final wallets = await Future.wait(_walletInfoSource.values.map((walletInfo) async { - return { - 'name': walletInfo.name, - 'type': walletInfo.type.toString(), - 'password': await _keyService.getWalletPassword(walletName: walletInfo.name) - }; - })); - final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); - final backupPassword = await _flutterSecureStorage.read(key: backupPasswordKey); - final data = utf8.encode( - json.encode({'pin': encodedPin, 'wallets': wallets, backupPasswordKey: backupPassword})); - final encrypted = await _encryptV3(Uint8List.fromList(data), '$keychainSalt$password'); - - return encrypted; - } - Future _exportPreferencesJSON() async { final preferences = { PreferencesKey.currentWalletName: @@ -689,10 +629,4 @@ class BackupService { Future _decryptV2(Uint8List data, String passphrase) async => cake_backup.decrypt(passphrase, data); - - Future _encryptV3(Uint8List data, String passphrase) async => - cake_backup.encrypt(passphrase, data, version: _v3); - - Future _decryptV3(Uint8List data, String passphrase) async => - cake_backup.decrypt(passphrase, data); }