diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 17c68a639..4a27652ae 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -511,7 +511,7 @@ class BackupService { return { 'name': walletInfo.name, 'type': walletInfo.type.toString(), - 'password': await _keyService.getWalletPassword(walletName: walletInfo.name) + 'password': await _keyService.getWalletPasswordV2(walletName: walletInfo.name) }; })); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); diff --git a/lib/core/key_service.dart b/lib/core/key_service.dart index fce254ea2..a2ffed4cc 100644 --- a/lib/core/key_service.dart +++ b/lib/core/key_service.dart @@ -7,25 +7,41 @@ class KeyService { final FlutterSecureStorage _secureStorage; - Future getWalletPassword({required String walletName}) async { - final key = generateStoreKeyFor( - key: SecretStoreKey.moneroWalletPassword, walletName: walletName); + Future getWalletPasswordV2({required String walletName}) async { + final key = + generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName); final encodedPassword = await _secureStorage.read(key: key); - return decodeWalletPassword(password: encodedPassword!); + return decodeWalletPasswordV2(password: encodedPassword!); } - Future saveWalletPassword({required String walletName, required String password}) async { - final key = generateStoreKeyFor( - key: SecretStoreKey.moneroWalletPassword, walletName: walletName); - final encodedPassword = encodeWalletPassword(password: password); + Future saveWalletPasswordV2({required String walletName, required String password}) async { + final key = + generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName); + final encodedPassword = await encodeWalletPasswordV2(password: password); + + await _secureStorage.delete(key: key); + await _secureStorage.write(key: key, value: encodedPassword); + } + + Future getWalletPasswordV1({required String walletName}) async { + final key = + generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName); + final encodedPassword = await _secureStorage.read(key: key); + return decodeWalletPasswordV1(password: encodedPassword!); + } + + Future saveWalletPasswordV1({required String walletName, required String password}) async { + final key = + generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName); + final encodedPassword = encodeWalletPasswordV1(password: password); await _secureStorage.delete(key: key); await _secureStorage.write(key: key, value: encodedPassword); } Future deleteWalletPassword({required String walletName}) async { - final key = generateStoreKeyFor( - key: SecretStoreKey.moneroWalletPassword, walletName: walletName); + final key = + generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName); await _secureStorage.delete(key: key); } diff --git a/lib/core/wallet_loading_service.dart b/lib/core/wallet_loading_service.dart index 3323e7831..c71a5a88c 100644 --- a/lib/core/wallet_loading_service.dart +++ b/lib/core/wallet_loading_service.dart @@ -17,10 +17,10 @@ class WalletLoadingService { Future renameWallet( WalletType type, String name, String newName) async { final walletService = walletServiceFactory.call(type); - final password = await keyService.getWalletPassword(walletName: name); + final password = await keyService.getWalletPasswordV2(walletName: name); // Save the current wallet's password to the new wallet name's key - await keyService.saveWalletPassword( + await keyService.saveWalletPasswordV2( walletName: newName, password: password); // Delete previous wallet name from keyService to keep only new wallet's name // otherwise keeps duplicate (old and new names) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 0314031ee..eae134249 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,5 +1,6 @@ import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cw_core/pathForWallet.dart'; @@ -187,7 +188,8 @@ Future defaultSettingsMigration( await rewriteSecureStoragePin(secureStorage: secureStorage); break; case 26: - await pinEncryptionMigration(secureStorage: secureStorage); + await pinEncryptionMigration( + secureStorage: secureStorage, walletInfoSource: walletInfoSource); break; default: break; @@ -382,7 +384,9 @@ Node getMoneroDefaultNode({required Box nodes}) { } } -Future pinEncryptionMigration({required FlutterSecureStorage secureStorage}) async { +Future pinEncryptionMigration( + {required FlutterSecureStorage secureStorage, + required Box walletInfoSource}) async { try { // first, get the encoded pin: final keyForPinCode = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); @@ -407,6 +411,14 @@ Future pinEncryptionMigration({required FlutterSecureStorage secureStorage iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock), mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock), ); + + KeyService keyService = KeyService(secureStorage); + + // now do the same for all wallet passwords: + await Future.forEach(walletInfoSource.values, (WalletInfo walletInfo) async { + String walletPassword = await keyService.getWalletPasswordV1(walletName: walletInfo.name); + await keyService.saveWalletPasswordV2(walletName: walletInfo.name, password: walletPassword); + }); } catch (e) { // failure isn't really an option since we'll be updating how pins are stored and used print("pinEncryptionMigration: $e"); diff --git a/lib/entities/encrypt.dart b/lib/entities/encrypt.dart index 9f41cb111..76ce49cc0 100644 --- a/lib/entities/encrypt.dart +++ b/lib/entities/encrypt.dart @@ -1,7 +1,11 @@ +import 'dart:convert'; +import 'dart:typed_data'; + import 'package:encrypt/encrypt.dart'; // import 'package:password/password.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:dargon2_flutter/dargon2_flutter.dart'; +import 'package:cake_backup/backup.dart' as cake_backup; Future argon2Hash({required String password}) async { final result = await argon2.hashPasswordString(password, salt: Salt.newSalt()); @@ -13,6 +17,16 @@ Future verifyArgon2Hash({required String password, required String hash}) return argon2.verifyHashString(password, hash); } +Future encodeWalletPasswordV2({required String password}) async { + final _key = secrets.shortKey + secrets.walletSalt; + return utf8.decode(await cake_backup.encrypt(password, Uint8List.fromList(utf8.encode(_key)))); +} + +Future decodeWalletPasswordV2({required String password}) async { + final _key = secrets.shortKey + secrets.walletSalt; + return utf8.decode(await cake_backup.decrypt(password, Uint8List.fromList(utf8.encode(_key)))); +} + // @@@@@@@@@@@@@@@ OLD (kept for reference purposes, do not use!) @@@@@@@@@@@@@ String encrypt({required String source, required String key}) { @@ -50,13 +64,13 @@ String decodedPinCode({required String pin}) { return decrypted.substring(secrets.key.length, decrypted.length); } -String encodeWalletPassword({required String password}) { +String encodeWalletPasswordV1({required String password}) { final source = password; final _key = secrets.shortKey + secrets.walletSalt; return encrypt(source: source, key: _key); } -String decodeWalletPassword({required String password}) { +String decodeWalletPasswordV1({required String password}) { final source = password; final _key = secrets.shortKey + secrets.walletSalt; return decrypt(source: source, key: _key);