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>

Matthew Fosse committed Nov 30, 2023 at 16:39 UTC 3760285a64405935fafe7aeeb051fd25d850585b
2 files changed +64 -36
lib/entities/default_settings_migration.dart
+63 -35
@@ -1,5 +1,6 @@
1 import 'dart:io' show Directory, File, Platform;
2 import 'package:cake_wallet/bitcoin/bitcoin.dart';
3 +import 'package:cake_wallet/entities/encrypt.dart';
4 import 'package:cake_wallet/entities/exchange_api_mode.dart';
5 import 'package:cw_core/pathForWallet.dart';
6 import 'package:cake_wallet/entities/secret_store_key.dart';
@@ -82,8 +83,7 @@ Future<void> defaultSettingsMigration(
83 sharedPreferences: sharedPreferences, nodes: nodes);
84 await changeLitecoinCurrentElectrumServerToDefault(
85 sharedPreferences: sharedPreferences, nodes: nodes);
85 - await changeHavenCurrentNodeToDefault(
86 - sharedPreferences: sharedPreferences, nodes: nodes);
86 + await changeHavenCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
87 await changeBitcoinCashCurrentNodeToDefault(
88 sharedPreferences: sharedPreferences, nodes: nodes);
89
@@ -175,6 +175,9 @@ Future<void> defaultSettingsMigration(
175 await changeBitcoinCurrentElectrumServerToDefault(
176 sharedPreferences: sharedPreferences, nodes: nodes);
177 break;
178 + case 25:
179 + await rewriteSecureStoragePin(secureStorage: secureStorage);
180 + break;
181
182 default:
183 break;
@@ -340,9 +343,9 @@ Node? getNanoDefaultPowNode({required Box<Node> nodes}) {
343 }
344
345 Node? getBitcoinCashDefaultElectrumServer({required Box<Node> nodes}) {
343 - return nodes.values.firstWhereOrNull(
344 - (Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri)
345 - ?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash);
346 + return nodes.values
347 + .firstWhereOrNull((Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri) ??
348 + nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash);
349 }
350
351 Node getMoneroDefaultNode({required Box<Node> nodes}) {
@@ -364,6 +367,37 @@ Node getMoneroDefaultNode({required Box<Node> nodes}) {
367 }
368 }
369
370 +Future<void> rewriteSecureStoragePin({required FlutterSecureStorage secureStorage}) async {
371 + // the bug only affects ios/mac:
372 + if (!Platform.isIOS && !Platform.isMacOS) {
373 + return;
374 + }
375 +
376 + // first, get the encoded pin:
377 + final keyForPinCode = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
378 + String? encodedPin;
379 + try {
380 + encodedPin = await secureStorage.read(key: keyForPinCode);
381 + } catch (e) {
382 + // either we don't have a pin, or we can't read it (maybe even because of the bug!)
383 + // the only option here is to abort the migration or we risk losing the pin and locking the user out
384 + return;
385 + }
386 +
387 + if (encodedPin == null) {
388 + return;
389 + }
390 +
391 + // ensure we overwrite by deleting the old key first:
392 + await secureStorage.delete(key: keyForPinCode);
393 + await secureStorage.write(
394 + key: keyForPinCode,
395 + value: encodedPin,
396 + iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
397 + mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
398 + );
399 +}
400 +
401 Future<void> changeBitcoinCurrentElectrumServerToDefault(
402 {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
403 final server = getBitcoinDefaultElectrumServer(nodes: nodes);
@@ -381,8 +415,7 @@ Future<void> changeLitecoinCurrentElectrumServerToDefault(
415 }
416
417 Future<void> changeBitcoinCashCurrentNodeToDefault(
384 - {required SharedPreferences sharedPreferences,
385 - required Box<Node> nodes}) async {
418 + {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
419 final server = getBitcoinCashDefaultElectrumServer(nodes: nodes);
420 final serverId = server?.key as int ?? 0;
421
@@ -538,34 +571,30 @@ Future<void> checkCurrentNodes(
571 final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
572 final currentBitcoinElectrumSeverId =
573 sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
541 - final currentLitecoinElectrumSeverId = sharedPreferences
542 - .getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
543 - final currentHavenNodeId = sharedPreferences
544 - .getInt(PreferencesKey.currentHavenNodeIdKey);
545 - final currentEthereumNodeId = sharedPreferences
546 - .getInt(PreferencesKey.currentEthereumNodeIdKey);
547 - final currentNanoNodeId = sharedPreferences
548 - .getInt(PreferencesKey.currentNanoNodeIdKey);
549 - final currentNanoPowNodeId = sharedPreferences
550 - .getInt(PreferencesKey.currentNanoPowNodeIdKey);
551 - final currentBitcoinCashNodeId = sharedPreferences
552 - .getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
553 - final currentMoneroNode = nodeSource.values.firstWhereOrNull(
554 - (node) => node.key == currentMoneroNodeId);
555 - final currentBitcoinElectrumServer = nodeSource.values.firstWhereOrNull(
556 - (node) => node.key == currentBitcoinElectrumSeverId);
557 - final currentLitecoinElectrumServer = nodeSource.values.firstWhereOrNull(
558 - (node) => node.key == currentLitecoinElectrumSeverId);
559 - final currentHavenNodeServer = nodeSource.values.firstWhereOrNull(
560 - (node) => node.key == currentHavenNodeId);
561 - final currentEthereumNodeServer = nodeSource.values.firstWhereOrNull(
562 - (node) => node.key == currentEthereumNodeId);
574 + final currentLitecoinElectrumSeverId =
575 + sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
576 + final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
577 + final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
578 + final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
579 + final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey);
580 + final currentBitcoinCashNodeId =
581 + sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
582 + final currentMoneroNode =
583 + nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId);
584 + final currentBitcoinElectrumServer =
585 + nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinElectrumSeverId);
586 + final currentLitecoinElectrumServer =
587 + nodeSource.values.firstWhereOrNull((node) => node.key == currentLitecoinElectrumSeverId);
588 + final currentHavenNodeServer =
589 + nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId);
590 + final currentEthereumNodeServer =
591 + nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId);
592 final currentNanoNodeServer =
564 - nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId);
593 + nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId);
594 final currentNanoPowNodeServer =
566 - powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId);
567 - final currentBitcoinCashNodeServer = nodeSource.values.firstWhereOrNull(
568 - (node) => node.key == currentBitcoinCashNodeId);
595 + powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId);
596 + final currentBitcoinCashNodeServer =
597 + nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId);
598 if (currentMoneroNode == null) {
599 final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
600 await nodeSource.add(newCakeWalletNode);
@@ -617,8 +646,7 @@ Future<void> checkCurrentNodes(
646 if (currentBitcoinCashNodeServer == null) {
647 final node = Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash);
648 await nodeSource.add(node);
620 - await sharedPreferences.setInt(
621 - PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
649 + await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
650 }
651 }
652
lib/main.dart
+1 -1
@@ -163,7 +163,7 @@ Future<void> initializeAppConfigs() async {
163 transactionDescriptions: transactionDescriptions,
164 secureStorage: secureStorage,
165 anonpayInvoiceInfo: anonpayInvoiceInfo,
166 - initialMigrationVersion: 23);
166 + initialMigrationVersion: 25);
167 }
168
169 Future<void> initialSetup(