From c68baf72447001490ce691b0143cf6c992dfca65 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Tue, 1 Aug 2023 14:52:03 +0200 Subject: [PATCH] CW-423 Use SensitiveClipboard for sensitive Stings (#1013) * CW-423 Use SensitiveClipboard for sensitive Stings * CW-423 Bump Android Target and Min SDK * CW-423 Use Helper function for sensitive Clipboard --- android/app/build.gradle | 4 +- lib/src/screens/backup/backup_page.dart | 40 +++++++++---------- lib/src/screens/seed/pre_seed_page.dart | 12 +++--- lib/src/screens/seed/wallet_seed_page.dart | 6 +-- .../screens/setup_2fa/setup_2fa_qr_page.dart | 19 +++++---- .../screens/wallet_keys/wallet_keys_page.dart | 17 ++++---- lib/utils/clipboard_util.dart | 15 +++++++ pubspec_base.yaml | 1 + 8 files changed, 67 insertions(+), 47 deletions(-) create mode 100644 lib/utils/clipboard_util.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 00cef6393..946c53697 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -45,8 +45,8 @@ android { defaultConfig { applicationId appProperties['id'] - minSdkVersion 21 - targetSdkVersion 31 + minSdkVersion 24 + targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/lib/src/screens/backup/backup_page.dart b/lib/src/screens/backup/backup_page.dart index 6f720ed9a..1b3b7e3d9 100644 --- a/lib/src/screens/backup/backup_page.dart +++ b/lib/src/screens/backup/backup_page.dart @@ -1,21 +1,22 @@ import 'dart:io'; +import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/trail_button.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/utils/clipboard_util.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/share_util.dart'; +import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/backup_view_model.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/utils/show_bar.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/src/widgets/trail_button.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cake_wallet/view_model/backup_view_model.dart'; -import 'package:cake_wallet/core/execution_state.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:permission_handler/permission_handler.dart'; class BackupPage extends BasePage { @@ -52,7 +53,7 @@ class BackupPage extends BasePage { child: Observer( builder: (_) => GestureDetector( onTap: () { - Clipboard.setData( + ClipboardUtil.setSensitiveDataToClipboard( ClipboardData(text: backupViewModelBase.backupPassword)); showBar( context, @@ -75,15 +76,14 @@ class BackupPage extends BasePage { ]))), Positioned( child: Observer( - builder: (_) => LoadingPrimaryButton( - isLoading: backupViewModelBase.state is IsExecutingState, - onPressed: () => onExportBackup(context), - text: S.of(context).export_backup, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, - textColor: Colors.white)), + builder: (_) => LoadingPrimaryButton( + isLoading: backupViewModelBase.state is IsExecutingState, + onPressed: () => onExportBackup(context), + text: S.of(context).export_backup, + color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + textColor: Colors.white, + ), + ), bottom: 24, left: 24, right: 24, diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index 6a8b6aa82..11bae8ac9 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -1,11 +1,11 @@ -import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cw_core/wallet_type.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; class PreSeedPage extends BasePage { PreSeedPage(this.type) @@ -61,7 +61,7 @@ class PreSeedPage extends BasePage { onPressed: () => Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true), text: S.of(context).pre_seed_button_text, - color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, + color: Theme.of(context).accentTextTheme.bodyLarge!.color!, textColor: Colors.white) ], ), diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart index f37a24dcd..b3128375c 100644 --- a/lib/src/screens/seed/wallet_seed_page.dart +++ b/lib/src/screens/seed/wallet_seed_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/utils/clipboard_util.dart'; import 'package:cake_wallet/utils/share_util.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; @@ -92,8 +93,7 @@ class WalletSeedPage extends BasePage { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ConstrainedBox( - constraints: - BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), + constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), child: AspectRatio(aspectRatio: 1, child: image), ), Observer(builder: (_) { @@ -159,7 +159,7 @@ class WalletSeedPage extends BasePage { child: Builder( builder: (context) => PrimaryButton( onPressed: () { - Clipboard.setData( + ClipboardUtil.setSensitiveDataToClipboard( ClipboardData(text: walletSeedViewModel.seed)); showBar(context, S.of(context).copied_to_clipboard); }, diff --git a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart index 90a83041f..b00d0eed8 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -1,16 +1,18 @@ import 'package:cake_wallet/core/totp_request_details.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/utils/clipboard_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:qr_flutter/qr_flutter.dart' as qr; -import '../../../palette.dart'; -import '../../widgets/primary_button.dart'; -import '../../widgets/standard_list.dart'; + class Setup2FAQRPage extends BasePage { Setup2FAQRPage({required this.setup2FAViewModel}); @@ -106,7 +108,8 @@ class Setup2FAQRPage extends BasePage { height: 32, child: InkWell( onTap: () { - Clipboard.setData(ClipboardData(text: '${setup2FAViewModel.secretKey}')); + ClipboardUtil.setSensitiveDataToClipboard( + ClipboardData(text: '${setup2FAViewModel.secretKey}')); showBar(context, S.of(context).copied_to_clipboard); }, child: Container( diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart index 5142fb2c2..63efdc5f9 100644 --- a/lib/src/screens/wallet_keys/wallet_keys_page.dart +++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart @@ -1,16 +1,17 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/src/widgets/section_divider.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/utils/clipboard_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:cake_wallet/view_model/wallet_keys_view_model.dart'; import 'package:device_display_brightness/device_display_brightness.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/list_row.dart'; -import 'package:cake_wallet/view_model/wallet_keys_view_model.dart'; -import 'package:cake_wallet/routes.dart'; import 'package:qr_flutter/qr_flutter.dart'; class WalletKeysPage extends BasePage { @@ -56,7 +57,7 @@ class WalletKeysPage extends BasePage { width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(12.0), - color: Theme.of(context).accentTextTheme!.bodySmall!.color!, + color: Theme.of(context).accentTextTheme.bodySmall!.color!, ), child: Center( child: Padding( @@ -84,7 +85,7 @@ class WalletKeysPage extends BasePage { separatorBuilder: (context, index) => Container( height: 1, padding: EdgeInsets.only(left: 24), - color: Theme.of(context).accentTextTheme!.titleLarge!.backgroundColor!, + color: Theme.of(context).accentTextTheme.titleLarge!.backgroundColor!, child: const SectionDivider(), ), itemCount: walletKeysViewModel.items.length, @@ -93,7 +94,7 @@ class WalletKeysPage extends BasePage { return GestureDetector( onTap: () { - Clipboard.setData(ClipboardData(text: item.value)); + ClipboardUtil.setSensitiveDataToClipboard(ClipboardData(text: item.value)); showBar(context, S.of(context).copied_key_to_clipboard(item.title)); }, child: ListRow( diff --git a/lib/utils/clipboard_util.dart b/lib/utils/clipboard_util.dart new file mode 100644 index 000000000..2874e30ef --- /dev/null +++ b/lib/utils/clipboard_util.dart @@ -0,0 +1,15 @@ +import 'package:flutter/services.dart'; + +import 'package:cake_wallet/utils/device_info.dart'; +import 'package:sensitive_clipboard/sensitive_clipboard.dart'; + +class ClipboardUtil { + static Future setSensitiveDataToClipboard(ClipboardData data) async { + if (DeviceInfo.instance.isMobile) { + await SensitiveClipboard.copy(data.text); + return; + } + + return Clipboard.setData(data); + } +} diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 9355dc739..6c0ef5405 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -81,6 +81,7 @@ dependencies: path_provider_android: 2.0.24 shared_preferences_android: 2.0.17 url_launcher_android: 6.0.24 + sensitive_clipboard: ^1.0.0 bitcoin_flutter: git: url: https://github.com/cake-tech/bitcoin_flutter.git