self contained desktop password service refactor that does not keep its db open when not in use

This commit is contained in:
julian 2023-07-03 15:06:28 -06:00
parent 9513b203a9
commit 6fb526efe5

View file

@ -10,9 +10,9 @@
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:stack_wallet_backup/secure_storage.dart'; import 'package:stack_wallet_backup/secure_storage.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
const String kBoxNameDesktopData = "desktopData";
const String _kKeyBlobKey = "swbKeyBlobKeyStringID"; const String _kKeyBlobKey = "swbKeyBlobKeyStringID";
const String _kKeyBlobVersionKey = "swbKeyBlobVersionKeyStringID"; const String _kKeyBlobVersionKey = "swbKeyBlobVersionKeyStringID";
@ -62,14 +62,8 @@ class DPS {
kLatestBlobVersion, kLatestBlobVersion,
); );
final box = await Hive.openBox<String>(DB.boxNameDesktopData); await _put(key: _kKeyBlobKey, value: await _handler!.getKeyBlob());
await DB.instance.put<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
value: await _handler!.getKeyBlob(),
);
await _updateStoredKeyBlobVersion(kLatestBlobVersion); await _updateStoredKeyBlobVersion(kLatestBlobVersion);
await box.close();
} catch (e, s) { } catch (e, s) {
Logging.instance.log( Logging.instance.log(
"${_getMessageFromException(e)}\n$s", "${_getMessageFromException(e)}\n$s",
@ -85,19 +79,13 @@ class DPS {
"DPS: attempted to re initialize with existing passphrase"); "DPS: attempted to re initialize with existing passphrase");
} }
final box = await Hive.openBox<String>(DB.boxNameDesktopData);
final keyBlob = DB.instance.get<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
);
await box.close();
if (keyBlob == null) {
throw Exception(
"DPS: failed to find keyBlob while attempting to initialize with existing passphrase");
}
try { try {
final keyBlob = await _get(key: _kKeyBlobKey);
if (keyBlob == null) {
throw Exception(
"DPS: failed to find keyBlob while attempting to initialize with existing passphrase");
}
final blobVersion = await _getStoredKeyBlobVersion(); final blobVersion = await _getStoredKeyBlobVersion();
_handler = await StorageCryptoHandler.fromExisting( _handler = await StorageCryptoHandler.fromExisting(
passphrase, passphrase,
@ -107,14 +95,8 @@ class DPS {
if (blobVersion < kLatestBlobVersion) { if (blobVersion < kLatestBlobVersion) {
// update blob // update blob
await _handler!.resetPassphrase(passphrase, kLatestBlobVersion); await _handler!.resetPassphrase(passphrase, kLatestBlobVersion);
final box = await Hive.openBox<String>(DB.boxNameDesktopData); await _put(key: _kKeyBlobKey, value: await _handler!.getKeyBlob());
await DB.instance.put<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
value: await _handler!.getKeyBlob(),
);
await _updateStoredKeyBlobVersion(kLatestBlobVersion); await _updateStoredKeyBlobVersion(kLatestBlobVersion);
await box.close();
} }
} catch (e, s) { } catch (e, s) {
Logging.instance.log( Logging.instance.log(
@ -126,19 +108,13 @@ class DPS {
} }
Future<bool> verifyPassphrase(String passphrase) async { Future<bool> verifyPassphrase(String passphrase) async {
final box = await Hive.openBox<String>(DB.boxNameDesktopData);
final keyBlob = DB.instance.get<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
);
await box.close();
if (keyBlob == null) {
// no passphrase key blob found so any passphrase is technically bad
return false;
}
try { try {
final keyBlob = await _get(key: _kKeyBlobKey);
if (keyBlob == null) {
// no passphrase key blob found so any passphrase is technically bad
return false;
}
final blobVersion = await _getStoredKeyBlobVersion(); final blobVersion = await _getStoredKeyBlobVersion();
await StorageCryptoHandler.fromExisting(passphrase, keyBlob, blobVersion); await StorageCryptoHandler.fromExisting(passphrase, keyBlob, blobVersion);
// existing passphrase matches key blob // existing passphrase matches key blob
@ -157,35 +133,25 @@ class DPS {
String passphraseOld, String passphraseOld,
String passphraseNew, String passphraseNew,
) async { ) async {
final box = await Hive.openBox<String>(DB.boxNameDesktopData);
final keyBlob = DB.instance.get<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
);
await box.close();
if (keyBlob == null) {
// no passphrase key blob found so any passphrase is technically bad
return false;
}
if (!(await verifyPassphrase(passphraseOld))) {
return false;
}
final blobVersion = await _getStoredKeyBlobVersion();
try { try {
await _handler!.resetPassphrase(passphraseNew, blobVersion); final keyBlob = await _get(key: _kKeyBlobKey);
final box = await Hive.openBox<String>(DB.boxNameDesktopData); if (keyBlob == null) {
await DB.instance.put<String>( // no passphrase key blob found so any passphrase is technically bad
boxName: DB.boxNameDesktopData, return false;
}
if (!(await verifyPassphrase(passphraseOld))) {
return false;
}
final blobVersion = await _getStoredKeyBlobVersion();
await _handler!.resetPassphrase(passphraseNew, blobVersion);
await _put(
key: _kKeyBlobKey, key: _kKeyBlobKey,
value: await _handler!.getKeyBlob(), value: await _handler!.getKeyBlob(),
); );
await _updateStoredKeyBlobVersion(blobVersion); await _updateStoredKeyBlobVersion(blobVersion);
await box.close();
// successfully updated passphrase // successfully updated passphrase
return true; return true;
@ -199,28 +165,48 @@ class DPS {
} }
Future<bool> hasPassword() async { Future<bool> hasPassword() async {
final keyBlob = DB.instance.get<String>( final keyBlob = await _get(key: _kKeyBlobKey);
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
);
return keyBlob != null; return keyBlob != null;
} }
Future<int> _getStoredKeyBlobVersion() async { Future<int> _getStoredKeyBlobVersion() async {
final box = await Hive.openBox<String>(DB.boxNameDesktopData); final keyBlobVersionString = await _get(key: _kKeyBlobVersionKey);
final keyBlobVersionString = DB.instance.get<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobVersionKey,
);
await box.close();
return int.tryParse(keyBlobVersionString ?? "1") ?? 1; return int.tryParse(keyBlobVersionString ?? "1") ?? 1;
} }
Future<void> _updateStoredKeyBlobVersion(int version) async { Future<void> _updateStoredKeyBlobVersion(int version) async {
await DB.instance.put<String>( await _put(key: _kKeyBlobVersionKey, value: version.toString());
boxName: DB.boxNameDesktopData, }
key: _kKeyBlobVersionKey,
value: version.toString(), Future<void> _put({required String key, required String value}) async {
); Box<String>? box;
try {
box = await Hive.openBox<String>(kBoxNameDesktopData);
await box.put(key, value);
} catch (e, s) {
Logging.instance.log(
"DPS failed put($key): $e\n$s",
level: LogLevel.Fatal,
);
} finally {
await box?.close();
}
}
Future<String?> _get({required String key}) async {
String? value;
Box<String>? box;
try {
box = await Hive.openBox<String>(kBoxNameDesktopData);
value = box.get(key);
} catch (e, s) {
Logging.instance.log(
"DPS failed get($key): $e\n$s",
level: LogLevel.Fatal,
);
} finally {
await box?.close();
}
return value;
} }
} }