mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-07 03:19:31 +00:00
cleaner backup changes
This commit is contained in:
parent
41bf68c886
commit
e699cb0335
1 changed files with 14 additions and 80 deletions
|
@ -28,11 +28,10 @@ class BackupService {
|
|||
: _cipher = Cryptography.instance.chacha20Poly1305Aead(),
|
||||
_correctWallets = <WalletInfo>[];
|
||||
|
||||
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<Uint8List> _exportBackupV1(String password, {String nonce = secrets.backupSalt}) async =>
|
||||
throw Exception('Deprecated. Export for backups v1 is deprecated. Please use export v2.');
|
||||
|
||||
Future<Uint8List> _exportBackupV2(String password, {bool keychainV3 = false}) async {
|
||||
Future<Uint8List> _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<Uint8List> _exportBackupV3(String password) async {
|
||||
return await _exportBackupV2(password, keychainV3: true);
|
||||
}
|
||||
|
||||
Future<void> _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<void> _importBackupV2(Uint8List data, String password, {bool keychainV3 = false}) async {
|
||||
Future<void> _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<void> _importBackupV3(Uint8List data, String password) async {
|
||||
await _importBackupV2(data, password, keychainV3: true);
|
||||
}
|
||||
|
||||
Future<void> _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<String, dynamic>;
|
||||
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<void> _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<String, dynamic>;
|
||||
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<String, dynamic>;
|
||||
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<Uint8List> _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<String> _exportPreferencesJSON() async {
|
||||
final preferences = <String, dynamic>{
|
||||
PreferencesKey.currentWalletName:
|
||||
|
@ -689,10 +629,4 @@ class BackupService {
|
|||
|
||||
Future<Uint8List> _decryptV2(Uint8List data, String passphrase) async =>
|
||||
cake_backup.decrypt(passphrase, data);
|
||||
|
||||
Future<Uint8List> _encryptV3(Uint8List data, String passphrase) async =>
|
||||
cake_backup.encrypt(passphrase, data, version: _v3);
|
||||
|
||||
Future<Uint8List> _decryptV3(Uint8List data, String passphrase) async =>
|
||||
cake_backup.decrypt(passphrase, data);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue