stack_wallet/lib/utilities/desktop_password_service.dart

168 lines
4.3 KiB
Dart
Raw Normal View History

2022-11-09 22:43:26 +00:00
import 'package:hive/hive.dart';
2022-11-04 19:32:02 +00:00
import 'package:stack_wallet_backup/secure_storage.dart';
2022-11-09 22:43:26 +00:00
import 'package:stackwallet/hive/db.dart';
2022-11-04 19:32:02 +00:00
import 'package:stackwallet/utilities/logger.dart';
const String _kKeyBlobKey = "swbKeyBlobKeyStringID";
String _getMessageFromException(Object exception) {
if (exception is IncorrectPassphrase) {
return exception.errMsg();
}
if (exception is BadDecryption) {
return exception.errMsg();
}
if (exception is InvalidLength) {
return exception.errMsg();
}
if (exception is EncodingError) {
return exception.errMsg();
}
return exception.toString();
}
class DPS {
StorageCryptoHandler? _handler;
StorageCryptoHandler get handler {
if (_handler == null) {
throw Exception(
"DPS: attempted to access handler without proper authentication");
}
return _handler!;
}
2022-11-09 22:43:26 +00:00
DPS();
2022-11-04 19:32:02 +00:00
Future<void> initFromNew(String passphrase) async {
if (_handler != null) {
throw Exception("DPS: attempted to re initialize with new passphrase");
}
try {
_handler = await StorageCryptoHandler.fromNewPassphrase(passphrase);
2022-11-09 22:43:26 +00:00
final box = await Hive.openBox<String>(DB.boxNameDesktopData);
await DB.instance.put<String>(
boxName: DB.boxNameDesktopData,
2022-11-04 19:32:02 +00:00
key: _kKeyBlobKey,
value: await _handler!.getKeyBlob(),
);
2022-11-09 22:43:26 +00:00
await box.close();
2022-11-04 19:32:02 +00:00
} catch (e, s) {
Logging.instance.log(
"${_getMessageFromException(e)}\n$s",
level: LogLevel.Error,
);
rethrow;
}
}
Future<void> initFromExisting(String passphrase) async {
if (_handler != null) {
throw Exception(
"DPS: attempted to re initialize with existing passphrase");
}
2022-11-09 22:43:26 +00:00
final box = await Hive.openBox<String>(DB.boxNameDesktopData);
final keyBlob = DB.instance.get<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
);
await box.close();
2022-11-04 19:32:02 +00:00
if (keyBlob == null) {
throw Exception(
"DPS: failed to find keyBlob while attempting to initialize with existing passphrase");
}
try {
_handler = await StorageCryptoHandler.fromExisting(passphrase, keyBlob);
} catch (e, s) {
Logging.instance.log(
"${_getMessageFromException(e)}\n$s",
level: LogLevel.Error,
);
throw Exception(_getMessageFromException(e));
2022-11-04 19:32:02 +00:00
}
}
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 {
await StorageCryptoHandler.fromExisting(passphrase, keyBlob);
// existing passphrase matches key blob
return true;
} catch (e, s) {
Logging.instance.log(
"${_getMessageFromException(e)}\n$s",
level: LogLevel.Warning,
);
// password is wrong or some other error
return false;
}
}
Future<bool> changePassphrase(
String passphraseOld,
String passphraseNew,
) 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;
}
try {
await _handler!.resetPassphrase(passphraseNew);
final box = await Hive.openBox<String>(DB.boxNameDesktopData);
await DB.instance.put<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
value: await _handler!.getKeyBlob(),
);
await box.close();
// successfully updated passphrase
return true;
} catch (e, s) {
Logging.instance.log(
"${_getMessageFromException(e)}\n$s",
level: LogLevel.Warning,
);
return false;
}
}
2022-11-04 19:32:02 +00:00
Future<bool> hasPassword() async {
2022-11-09 22:43:26 +00:00
final keyBlob = DB.instance.get<String>(
boxName: DB.boxNameDesktopData,
key: _kKeyBlobKey,
);
return keyBlob != null;
2022-11-04 19:32:02 +00:00
}
}