Skip to content

Commit

Permalink
Merge pull request #449 from DanXi-Dev/upgrade-secure-storage
Browse files Browse the repository at this point in the history
Upgrade secure storage and fix regression issue introduced by migration logic
  • Loading branch information
w568w authored Nov 27, 2024
2 parents 56c29c8 + 33b4edb commit 469b54a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 29 deletions.
11 changes: 5 additions & 6 deletions lib/page/subpage_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,7 @@ class SettingsSubpageState extends PlatformSubpageState<SettingsSubpage> {
"https://github.com/50431040/device_identity"),
LicenseItem("tutorial_coach_mark", LICENSE_MIT,
"https://github.com/RafaelBarbosatec/tutorial_coach_mark"),
LicenseItem("toml", LICENSE_MIT,
"https://github.com/just95/toml.dart"),
LicenseItem("toml", LICENSE_MIT, "https://github.com/just95/toml.dart"),
LicenseItem("pub_semver", LICENSE_BSD_3_0_CLAUSE,
"https://github.com/dart-lang/pub_semver"),
];
Expand All @@ -252,10 +251,10 @@ class SettingsSubpageState extends PlatformSubpageState<SettingsSubpage> {
await ForumRepository.getInstance().logout();
} finally {
progressDialog.dismiss(showAnim: false);
SettingsProvider.getInstance()
.preferences
?.clear()
.then((value) => FlutterApp.restartApp(context));
await SettingsProvider.getInstance().preferences?.clear();
if (mounted) {
FlutterApp.restartApp(context);
}
}
}

Expand Down
48 changes: 44 additions & 4 deletions lib/util/shared_preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* along with thFlutterSecureStorageis program. If not, see <https://www.gnu.org/licenses/>.
*/

import 'package:encrypt/encrypt.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:math';

Expand All @@ -35,7 +37,9 @@ class XSharedPreferences {
final FlutterSecureStorage _keyStore;
late final EncryptedSharedPreferences _preferences;

XSharedPreferences._() : _keyStore = const FlutterSecureStorage();
XSharedPreferences._() : _keyStore = const FlutterSecureStorage(
wOptions: WindowsOptions(useBackwardCompatibility: true),
);

static XSharedPreferences? _instance;

Expand Down Expand Up @@ -67,7 +71,7 @@ class XSharedPreferences {
}
String key = (await _instance!._keyStore.read(key: KEY_CIPHER))!;
// initialize the encrypted preferences.
await EncryptedSharedPreferences.initialize(key);
await EncryptedSharedPreferences.initialize(key, encryptor: LegacyAESEncryptor());
_instance!._preferences = EncryptedSharedPreferences.getInstance();
// migrate the data from [SharedPreferences] to [EncryptedSharedPreferences]
// if the data has not been flagged as migrated.
Expand Down Expand Up @@ -97,11 +101,18 @@ class XSharedPreferences {

// Proxy methods for [EncryptedSharedPreferences]

Future<bool> clear() => _preferences.clear();
Future<bool> clear() async {
bool success = await _preferences.clear();
if (success) {
// mark the data as migrated after clearing. Or the data written after clearing will be re-migrated.
await _instance!.setBool(KEY_MIGRATED, true);
}
return success;
}

Future<bool> remove(String key) => _preferences.remove(key);

Future<Set<String>> getKeys() => _preferences.getKeys();
FutureOr<Set<String>> getKeys() => _preferences.getKeys();

Future<bool> setString(String dataKey, String? dataValue) =>
_preferences.setString(dataKey, dataValue);
Expand Down Expand Up @@ -141,3 +152,32 @@ class XSharedPreferences {
}
}
}


/// @w568w (2024-11-26):
/// encrypt_shared_preferences quietly changed the default AES Encryptor to use SIC mode from CBC mode.
/// This is obviously a breaking change, but it is mentioned nowhere in the changelog. Average noob developer.
///
/// So this class is an implementation of the legacy AES Encryptor.
class LegacyAESEncryptor extends IEncryptor{
@override
String encrypt(String key, String plainText) {
assert(key.length == 16);
final cipherKey = Key.fromUtf8(key);
final encryptService = Encrypter(AES(cipherKey, mode: AESMode.cbc));
final initVector = IV.fromUtf8(key);

Encrypted encryptedData = encryptService.encrypt(plainText, iv: initVector);
return encryptedData.base64;
}

@override
String decrypt(String key, String encryptedData) {
assert(key.length == 16);
final cipherKey = Key.fromUtf8(key);
final encryptService = Encrypter(AES(cipherKey, mode: AESMode.cbc));
final initVector = IV.fromUtf8(key);

return encryptService.decrypt(Encrypted.fromBase64(encryptedData), iv: initVector);
}
}
26 changes: 13 additions & 13 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ packages:
source: hosted
version: "2.0.0"
encrypt:
dependency: transitive
dependency: "direct main"
description:
name: encrypt
sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2"
Expand All @@ -442,10 +442,10 @@ packages:
dependency: "direct main"
description:
name: encrypt_shared_preferences
sha256: "83324f4350442d4b19994b22e5d87766eed9ee87b8211626b3b0d84bce1e98b9"
sha256: "6d9496f5873ab38d8cbea52dfeafc5e361a61193cc4d9f2da5f0f092b5ddab1a"
url: "https://pub.dev"
source: hosted
version: "0.3.8"
version: "0.8.1"
equatable:
dependency: transitive
description:
Expand Down Expand Up @@ -498,10 +498,10 @@ packages:
dependency: transitive
description:
name: file_selector_linux
sha256: b2b91daf8a68ecfa4a01b778a6f52edef9b14ecd506e771488ea0f2e0784198b
sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33"
url: "https://pub.dev"
source: hosted
version: "0.9.3+1"
version: "0.9.3+2"
file_selector_macos:
dependency: transitive
description:
Expand Down Expand Up @@ -789,10 +789,10 @@ packages:
dependency: "direct main"
description:
name: flutter_secure_storage
sha256: "22dbf16f23a4bcf9d35e51be1c84ad5bb6f627750565edd70dab70f3ff5fff8f"
sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0"
url: "https://pub.dev"
source: hosted
version: "8.1.0"
version: "9.2.2"
flutter_secure_storage_linux:
dependency: transitive
description:
Expand Down Expand Up @@ -829,10 +829,10 @@ packages:
dependency: transitive
description:
name: flutter_secure_storage_windows
sha256: "38f9501c7cb6f38961ef0e1eacacee2b2d4715c63cc83fe56449c4d3d0b47255"
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "3.1.2"
flutter_svg:
dependency: transitive
description:
Expand Down Expand Up @@ -1378,10 +1378,10 @@ packages:
dependency: transitive
description:
name: path_provider_android
sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
sha256: "8c4967f8b7cb46dc914e178daa29813d83ae502e0529d7b0478330616a691ef7"
url: "https://pub.dev"
source: hosted
version: "2.2.12"
version: "2.2.14"
path_provider_foundation:
dependency: transitive
description:
Expand Down Expand Up @@ -2152,10 +2152,10 @@ packages:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: ab9ff38fc771e9ee1139320adbe3d18a60327370c218c60752068ebee4b49ab1
sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad"
url: "https://pub.dev"
source: hosted
version: "1.1.15"
version: "1.1.16"
vector_math:
dependency: transitive
description:
Expand Down
9 changes: 3 additions & 6 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,9 @@ dependencies:
git:
url: https://github.com/w568w/receive_intent.git

# These two libraries are used to encrypt shared preferences.
# They introduced breaking changes in their latest versions,
# making them unable to read the old encrypted data.
# Therefore, we have to pin them at the these versions.
flutter_secure_storage: ^8.0.0
encrypt_shared_preferences: ^0.3.5
flutter_secure_storage: ^9.0.0
encrypt_shared_preferences: ^0.8.1
encrypt: any
device_identity: ^1.0.0
tutorial_coach_mark: ^1.2.9
flutter_platform_widgets: ^7.0.0
Expand Down

0 comments on commit 469b54a

Please sign in to comment.