diff --git a/lib/provider/authentication_provider.dart b/lib/provider/authentication_provider.dart index 057ddda26..c09cb1999 100644 --- a/lib/provider/authentication_provider.dart +++ b/lib/provider/authentication_provider.dart @@ -79,7 +79,7 @@ class AuthenticationNotifier bool get isLoggedIn => state != null; - AuthenticationNotifier() : super(null, "authentication"); + AuthenticationNotifier() : super(null, "authentication", encrypted: true); Timer? _refreshTimer; diff --git a/lib/utils/persisted_state_notifier.dart b/lib/utils/persisted_state_notifier.dart index 78219051a..f509f4393 100644 --- a/lib/utils/persisted_state_notifier.dart +++ b/lib/utils/persisted_state_notifier.dart @@ -1,22 +1,70 @@ import 'dart:async'; +import 'dart:convert'; +import 'dart:typed_data'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; +import 'package:spotube/utils/primitive_utils.dart'; + +const secureStorage = FlutterSecureStorage(); abstract class PersistedStateNotifier extends StateNotifier { final String cacheKey; + final bool encrypted; FutureOr onInit() {} PersistedStateNotifier( super.state, - this.cacheKey, - ) { + this.cacheKey, { + this.encrypted = false, + }) { _load().then((_) => onInit()); } Future _load() async { - final box = await Hive.openLazyBox("spotube_cache"); + final LazyBox box; + + if (encrypted) { + String? boxName = + await secureStorage.read(key: "oss.krtirtho.spotube.box_name"); + + if (boxName == null) { + await secureStorage.write( + key: "oss.krtirtho.spotube.box_name", + value: ".spotube-${PrimitiveUtils.uuid.v4()}", + ); + boxName = + await secureStorage.read(key: "oss.krtirtho.spotube.box_name"); + } else { + boxName = ".spotube-$boxName"; + } + + final rawKey = + await secureStorage.read(key: "oss.krtirtho.spotube.$boxName"); + + Uint8List? encryptionKey = + rawKey == null ? null : base64Url.decode(rawKey); + + if (encryptionKey == null) { + await secureStorage.write( + key: "oss.krtirtho.spotube.$boxName", + value: base64UrlEncode(Hive.generateSecureKey()), + ); + encryptionKey = base64Url.decode( + (await secureStorage.read(key: "oss.krtirtho.spotube.$boxName"))!, + ); + } + + box = await Hive.openLazyBox( + boxName!, + encryptionCipher: HiveAesCipher(encryptionKey), + ); + } else { + box = await Hive.openLazyBox("spotube_cache"); + } + final json = await box.get(cacheKey); if (json != null) {