ios/mac secure storage pin migration (potential fix) (#1205)

* ios/mac secure storage pin migration

* function call was incorrect

* Update default_settings_migration.dart

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
Matthew Fosse 2023-11-30 16:39:09 -05:00 committed by GitHub
parent 2bddeb6ac2
commit 3760285a64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 36 deletions

View file

@ -1,5 +1,6 @@
import 'dart:io' show Directory, File, Platform; import 'dart:io' show Directory, File, Platform;
import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/entities/encrypt.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pathForWallet.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
@ -82,8 +83,7 @@ Future<void> defaultSettingsMigration(
sharedPreferences: sharedPreferences, nodes: nodes); sharedPreferences: sharedPreferences, nodes: nodes);
await changeLitecoinCurrentElectrumServerToDefault( await changeLitecoinCurrentElectrumServerToDefault(
sharedPreferences: sharedPreferences, nodes: nodes); sharedPreferences: sharedPreferences, nodes: nodes);
await changeHavenCurrentNodeToDefault( await changeHavenCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
sharedPreferences: sharedPreferences, nodes: nodes);
await changeBitcoinCashCurrentNodeToDefault( await changeBitcoinCashCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes); sharedPreferences: sharedPreferences, nodes: nodes);
@ -175,6 +175,9 @@ Future<void> defaultSettingsMigration(
await changeBitcoinCurrentElectrumServerToDefault( await changeBitcoinCurrentElectrumServerToDefault(
sharedPreferences: sharedPreferences, nodes: nodes); sharedPreferences: sharedPreferences, nodes: nodes);
break; break;
case 25:
await rewriteSecureStoragePin(secureStorage: secureStorage);
break;
default: default:
break; break;
@ -340,9 +343,9 @@ Node? getNanoDefaultPowNode({required Box<Node> nodes}) {
} }
Node? getBitcoinCashDefaultElectrumServer({required Box<Node> nodes}) { Node? getBitcoinCashDefaultElectrumServer({required Box<Node> nodes}) {
return nodes.values.firstWhereOrNull( return nodes.values
(Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri) .firstWhereOrNull((Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri) ??
?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash); nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash);
} }
Node getMoneroDefaultNode({required Box<Node> nodes}) { Node getMoneroDefaultNode({required Box<Node> nodes}) {
@ -364,6 +367,37 @@ Node getMoneroDefaultNode({required Box<Node> nodes}) {
} }
} }
Future<void> rewriteSecureStoragePin({required FlutterSecureStorage secureStorage}) async {
// the bug only affects ios/mac:
if (!Platform.isIOS && !Platform.isMacOS) {
return;
}
// first, get the encoded pin:
final keyForPinCode = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
String? encodedPin;
try {
encodedPin = await secureStorage.read(key: keyForPinCode);
} catch (e) {
// either we don't have a pin, or we can't read it (maybe even because of the bug!)
// the only option here is to abort the migration or we risk losing the pin and locking the user out
return;
}
if (encodedPin == null) {
return;
}
// ensure we overwrite by deleting the old key first:
await secureStorage.delete(key: keyForPinCode);
await secureStorage.write(
key: keyForPinCode,
value: encodedPin,
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
);
}
Future<void> changeBitcoinCurrentElectrumServerToDefault( Future<void> changeBitcoinCurrentElectrumServerToDefault(
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async { {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final server = getBitcoinDefaultElectrumServer(nodes: nodes); final server = getBitcoinDefaultElectrumServer(nodes: nodes);
@ -381,8 +415,7 @@ Future<void> changeLitecoinCurrentElectrumServerToDefault(
} }
Future<void> changeBitcoinCashCurrentNodeToDefault( Future<void> changeBitcoinCashCurrentNodeToDefault(
{required SharedPreferences sharedPreferences, {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
required Box<Node> nodes}) async {
final server = getBitcoinCashDefaultElectrumServer(nodes: nodes); final server = getBitcoinCashDefaultElectrumServer(nodes: nodes);
final serverId = server?.key as int ?? 0; final serverId = server?.key as int ?? 0;
@ -538,34 +571,30 @@ Future<void> checkCurrentNodes(
final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
final currentBitcoinElectrumSeverId = final currentBitcoinElectrumSeverId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
final currentLitecoinElectrumSeverId = sharedPreferences final currentLitecoinElectrumSeverId =
.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
final currentHavenNodeId = sharedPreferences final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
.getInt(PreferencesKey.currentHavenNodeIdKey); final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
final currentEthereumNodeId = sharedPreferences final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
.getInt(PreferencesKey.currentEthereumNodeIdKey); final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey);
final currentNanoNodeId = sharedPreferences final currentBitcoinCashNodeId =
.getInt(PreferencesKey.currentNanoNodeIdKey); sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
final currentNanoPowNodeId = sharedPreferences final currentMoneroNode =
.getInt(PreferencesKey.currentNanoPowNodeIdKey); nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId);
final currentBitcoinCashNodeId = sharedPreferences final currentBitcoinElectrumServer =
.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinElectrumSeverId);
final currentMoneroNode = nodeSource.values.firstWhereOrNull( final currentLitecoinElectrumServer =
(node) => node.key == currentMoneroNodeId); nodeSource.values.firstWhereOrNull((node) => node.key == currentLitecoinElectrumSeverId);
final currentBitcoinElectrumServer = nodeSource.values.firstWhereOrNull( final currentHavenNodeServer =
(node) => node.key == currentBitcoinElectrumSeverId); nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId);
final currentLitecoinElectrumServer = nodeSource.values.firstWhereOrNull( final currentEthereumNodeServer =
(node) => node.key == currentLitecoinElectrumSeverId); nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId);
final currentHavenNodeServer = nodeSource.values.firstWhereOrNull(
(node) => node.key == currentHavenNodeId);
final currentEthereumNodeServer = nodeSource.values.firstWhereOrNull(
(node) => node.key == currentEthereumNodeId);
final currentNanoNodeServer = final currentNanoNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId); nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId);
final currentNanoPowNodeServer = final currentNanoPowNodeServer =
powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId); powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId);
final currentBitcoinCashNodeServer = nodeSource.values.firstWhereOrNull( final currentBitcoinCashNodeServer =
(node) => node.key == currentBitcoinCashNodeId); nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId);
if (currentMoneroNode == null) { if (currentMoneroNode == null) {
final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero); final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
await nodeSource.add(newCakeWalletNode); await nodeSource.add(newCakeWalletNode);
@ -617,8 +646,7 @@ Future<void> checkCurrentNodes(
if (currentBitcoinCashNodeServer == null) { if (currentBitcoinCashNodeServer == null) {
final node = Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash); final node = Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash);
await nodeSource.add(node); await nodeSource.add(node);
await sharedPreferences.setInt( await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
} }
} }

View file

@ -163,7 +163,7 @@ Future<void> initializeAppConfigs() async {
transactionDescriptions: transactionDescriptions, transactionDescriptions: transactionDescriptions,
secureStorage: secureStorage, secureStorage: secureStorage,
anonpayInvoiceInfo: anonpayInvoiceInfo, anonpayInvoiceInfo: anonpayInvoiceInfo,
initialMigrationVersion: 23); initialMigrationVersion: 25);
} }
Future<void> initialSetup( Future<void> initialSetup(