From fb0d938cb54a8b571a5c6d03c047e991c94d1f16 Mon Sep 17 00:00:00 2001 From: Aman Raj Singh Mourya Date: Fri, 12 Jul 2024 15:58:23 +0530 Subject: [PATCH] [mob][auth] Implemented Pin/Password hashing using ente_crypto --- auth/lib/events/app_lock_update_event.dart | 14 +++ .../local_authentication_service.dart | 19 +++- .../lock_screen/custom_pin_keypad.dart | 1 - .../lock_screen/lock_screen_confirm_pin.dart | 17 +-- .../lock_screen/lock_screen_options.dart | 71 +++++++++--- .../lock_screen/lock_screen_password.dart | 52 ++++++--- .../settings/lock_screen/lock_screen_pin.dart | 71 ++++++------ .../ui/settings/security_section_widget.dart | 18 ++- auth/lib/utils/auth_util.dart | 4 +- auth/lib/utils/lock_screen_settings.dart | 106 ++++++++++-------- 10 files changed, 233 insertions(+), 140 deletions(-) create mode 100644 auth/lib/events/app_lock_update_event.dart diff --git a/auth/lib/events/app_lock_update_event.dart b/auth/lib/events/app_lock_update_event.dart new file mode 100644 index 0000000000..3c83cde08b --- /dev/null +++ b/auth/lib/events/app_lock_update_event.dart @@ -0,0 +1,14 @@ +import "package:ente_auth/events/event.dart"; + +enum AppLockUpdateType { + none, + device, + pin, + password, +} + +class AppLockUpdateEvent extends Event { + final AppLockUpdateType type; + + AppLockUpdateEvent(this.type); +} diff --git a/auth/lib/services/local_authentication_service.dart b/auth/lib/services/local_authentication_service.dart index a1f016b7a9..9ca1636997 100644 --- a/auth/lib/services/local_authentication_service.dart +++ b/auth/lib/services/local_authentication_service.dart @@ -25,7 +25,11 @@ class LocalAuthenticationService { ) async { if (await _isLocalAuthSupportedOnDevice()) { AppLock.of(context)!.setEnabled(false); - final result = await requestAuthentication(context, infoMessage); + final result = await requestAuthentication( + context, + infoMessage, + isAuthenticatingForInAppChange: true, + ); AppLock.of(context)!.setEnabled( await Configuration.instance.shouldShowLockScreen(), ); @@ -43,15 +47,17 @@ class LocalAuthenticationService { BuildContext context, String? savedPin, String? savedPassword, { - bool isOnOpeningApp = false, + bool isAuthenticatingOnAppLaunch = false, + bool isAuthenticatingForInAppChange = false, }) async { if (savedPassword != null) { final result = await Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) { return LockScreenPassword( - isAuthenticating: true, - isOnOpeningApp: isOnOpeningApp, + isChangingLockScreenSettings: true, + isAuthenticatingForInAppChange: isAuthenticatingForInAppChange, + isAuthenticatingOnAppLaunch: isAuthenticatingOnAppLaunch, authPass: savedPassword, ); }, @@ -66,8 +72,9 @@ class LocalAuthenticationService { MaterialPageRoute( builder: (BuildContext context) { return LockScreenPin( - isAuthenticating: true, - isOnOpeningApp: isOnOpeningApp, + isChangingLockScreenSettings: true, + isAuthenticatingForInAppChange: isAuthenticatingForInAppChange, + isAuthenticatingOnAppLaunch: isAuthenticatingOnAppLaunch, authPin: savedPin, ); }, diff --git a/auth/lib/ui/settings/lock_screen/custom_pin_keypad.dart b/auth/lib/ui/settings/lock_screen/custom_pin_keypad.dart index a7edce4c61..3bdf091f16 100644 --- a/auth/lib/ui/settings/lock_screen/custom_pin_keypad.dart +++ b/auth/lib/ui/settings/lock_screen/custom_pin_keypad.dart @@ -10,7 +10,6 @@ class CustomPinKeypad extends StatelessWidget { return SafeArea( child: Container( padding: const EdgeInsets.all(2), - // color: getEnteColorScheme(context).strokeFainter, child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ diff --git a/auth/lib/ui/settings/lock_screen/lock_screen_confirm_pin.dart b/auth/lib/ui/settings/lock_screen/lock_screen_confirm_pin.dart index 124e38328a..508710a869 100644 --- a/auth/lib/ui/settings/lock_screen/lock_screen_confirm_pin.dart +++ b/auth/lib/ui/settings/lock_screen/lock_screen_confirm_pin.dart @@ -71,22 +71,13 @@ class _LockScreenConfirmPinState extends State { ), floatingActionButton: CustomPinKeypad(controller: _confirmPinController), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - // body: OrientationBuilder( - // builder: (context, orientation) { - // return orientation == Orientation.portrait - // ? _getBody(colorTheme, textTheme, isPortrait: true) - // : SingleChildScrollView( - // child: _getBody(colorTheme, textTheme, isPortrait: false), - // ); - // }, - // ), body: SingleChildScrollView( - child: _getBody(colorTheme, textTheme, isPortrait: true), + child: _getBody(colorTheme, textTheme), ), ); } - Widget _getBody(colorTheme, textTheme, {required bool isPortrait}) { + Widget _getBody(colorTheme, textTheme) { return Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, @@ -200,10 +191,6 @@ class _LockScreenConfirmPinState extends State { await _confirmPinMatch(); }, ), - // isPortrait - // ? const Spacer() - // : const Padding(padding: EdgeInsets.all(12)), - // CustomPinKeypad(controller: _confirmPinController), ], ), ); diff --git a/auth/lib/ui/settings/lock_screen/lock_screen_options.dart b/auth/lib/ui/settings/lock_screen/lock_screen_options.dart index 18a967b515..ff34b5ef85 100644 --- a/auth/lib/ui/settings/lock_screen/lock_screen_options.dart +++ b/auth/lib/ui/settings/lock_screen/lock_screen_options.dart @@ -1,6 +1,8 @@ import "dart:async"; import "package:ente_auth/core/configuration.dart"; +import "package:ente_auth/core/event_bus.dart"; +import "package:ente_auth/events/app_lock_update_event.dart"; import "package:ente_auth/theme/ente_theme.dart"; import "package:ente_auth/ui/components/captioned_text_widget.dart"; import "package:ente_auth/ui/components/divider_widget.dart"; @@ -29,15 +31,11 @@ class _LockScreenOptionsState extends State { late bool appLock; bool isPinEnabled = false; bool isPasswordEnabled = false; - late String autoLockTime; + late int autoLockTimeInMilliseconds; @override void initState() { super.initState(); - autoLockTime = _formatTime( - Duration( - milliseconds: _lockscreenSetting.getAutoLockTime(), - ), - ); + autoLockTimeInMilliseconds = _lockscreenSetting.getAutoLockTime(); _initializeSettings(); appLock = isPinEnabled || isPasswordEnabled || @@ -56,6 +54,12 @@ class _LockScreenOptionsState extends State { Future _deviceLock() async { await _lockscreenSetting.removePinAndPassword(); await _initializeSettings(); + await _lockscreenSetting.setAppLockType("Device lock"); + Bus.instance.fire( + AppLockUpdateEvent( + AppLockUpdateType.device, + ), + ); } Future _pinLock() async { @@ -69,6 +73,12 @@ class _LockScreenOptionsState extends State { setState(() { _initializeSettings(); if (result) { + Bus.instance.fire( + AppLockUpdateEvent( + AppLockUpdateType.pin, + ), + ); + _lockscreenSetting.setAppLockType("Pin"); appLock = isPinEnabled || isPasswordEnabled || _configuration.shouldShowSystemLockScreen(); @@ -87,6 +97,12 @@ class _LockScreenOptionsState extends State { setState(() { _initializeSettings(); if (result) { + Bus.instance.fire( + AppLockUpdateEvent( + AppLockUpdateType.password, + ), + ); + _lockscreenSetting.setAppLockType("Password"); appLock = isPinEnabled || isPasswordEnabled || _configuration.shouldShowSystemLockScreen(); @@ -98,6 +114,12 @@ class _LockScreenOptionsState extends State { AppLock.of(context)!.setEnabled(!appLock); await _configuration.setSystemLockScreen(!appLock); await _lockscreenSetting.removePinAndPassword(); + await _lockscreenSetting.setAppLockType(appLock ? "None" : "Device lock"); + Bus.instance.fire( + AppLockUpdateEvent( + appLock ? AppLockUpdateType.none : AppLockUpdateType.device, + ), + ); setState(() { _initializeSettings(); appLock = !appLock; @@ -111,11 +133,7 @@ class _LockScreenOptionsState extends State { ).then( (value) { setState(() { - autoLockTime = _formatTime( - Duration( - milliseconds: _lockscreenSetting.getAutoLockTime(), - ), - ); + autoLockTimeInMilliseconds = _lockscreenSetting.getAutoLockTime(); }); }, ); @@ -123,11 +141,11 @@ class _LockScreenOptionsState extends State { String _formatTime(Duration duration) { if (duration.inHours != 0) { - return "${duration.inHours}hr"; + return "in ${duration.inHours} hour${duration.inHours > 1 ? 's' : ''}"; } else if (duration.inMinutes != 0) { - return "${duration.inMinutes}m"; + return "in ${duration.inMinutes} minute${duration.inMinutes > 1 ? 's' : ''}"; } else if (duration.inSeconds != 0) { - return "${duration.inSeconds}s"; + return "in ${duration.inSeconds} second${duration.inSeconds > 1 ? 's' : ''}"; } else { return "Disable"; } @@ -191,6 +209,7 @@ class _LockScreenOptionsState extends State { ), appLock ? Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ MenuItemWidget( captionedTextWidget: @@ -249,14 +268,32 @@ class _LockScreenOptionsState extends State { ), MenuItemWidget( captionedTextWidget: CaptionedTextWidget( - title: "Auto-lock", - subTitle: autoLockTime, + title: "Auto lock", + subTitle: _formatTime( + Duration( + milliseconds: + autoLockTimeInMilliseconds, + ), + ), ), - singleBorderRadius: 8, alignCaptionedTextToLeft: true, + singleBorderRadius: 8, menuItemColor: colorTheme.fillFaint, + trailingIconColor: colorTheme.textBase, onTap: () => _onAutoLock(), ), + Padding( + padding: const EdgeInsets.only( + top: 14, + left: 14, + right: 12, + ), + child: Text( + "Require ${_lockscreenSetting.getAppLockType()} if away for some time .", + style: textTheme.miniFaint, + textAlign: TextAlign.left, + ), + ), ], ) : Container(), diff --git a/auth/lib/ui/settings/lock_screen/lock_screen_password.dart b/auth/lib/ui/settings/lock_screen/lock_screen_password.dart index 6ea0a61d61..1c43ff8229 100644 --- a/auth/lib/ui/settings/lock_screen/lock_screen_password.dart +++ b/auth/lib/ui/settings/lock_screen/lock_screen_password.dart @@ -1,3 +1,5 @@ +import "dart:convert"; + import "package:ente_auth/theme/ente_theme.dart"; import "package:ente_auth/ui/common/dynamic_fab.dart"; import "package:ente_auth/ui/components/buttons/icon_button_widget.dart"; @@ -5,20 +7,32 @@ import "package:ente_auth/ui/components/text_input_widget.dart"; import "package:ente_auth/ui/settings/lock_screen/lock_screen_confirm_password.dart"; import "package:ente_auth/ui/settings/lock_screen/lock_screen_options.dart"; import "package:ente_auth/utils/lock_screen_settings.dart"; +import "package:ente_crypto_dart/ente_crypto_dart.dart"; import "package:flutter/material.dart"; import "package:flutter/services.dart"; +/// [isChangingLockScreenSettings] Authentication required for changing lock screen settings. +/// Set to true when the app requires the user to authenticate before allowing +/// changes to the lock screen settings. + +/// [isAuthenticatingOnAppLaunch] Authentication required on app launch. +/// Set to true when the app requires the user to authenticate immediately upon opening. + +/// [isAuthenticatingForInAppChange] Authentication required for in-app changes (e.g., email, password). +/// Set to true when the app requires the to authenticate for sensitive actions like email, password changes. + class LockScreenPassword extends StatefulWidget { const LockScreenPassword({ super.key, - this.isAuthenticating = false, - this.isOnOpeningApp = false, + this.isChangingLockScreenSettings = false, + this.isAuthenticatingOnAppLaunch = false, + this.isAuthenticatingForInAppChange = false, this.authPass, }); - //Is false when setting a new password - final bool isAuthenticating; - final bool isOnOpeningApp; + final bool isChangingLockScreenSettings; + final bool isAuthenticatingOnAppLaunch; + final bool isAuthenticatingForInAppChange; final String? authPass; @override State createState() => _LockScreenPasswordState(); @@ -149,7 +163,9 @@ class _LockScreenPasswordState extends State { ), ), Text( - widget.isAuthenticating ? "Enter Password" : "Set new Password", + widget.isChangingLockScreenSettings + ? "Enter Password" + : "Set new Password", textAlign: TextAlign.center, style: textTheme.bodyBold, ), @@ -181,17 +197,19 @@ class _LockScreenPasswordState extends State { } Future _confirmPasswordAuth(String inputtedPassword) async { - // final Uint8List? salt = await _lockscreenSetting.getSalt(); - // final hash = cryptoPwHash({ - // "password": utf8.encode(inputtedPassword), - // "salt": salt, - // "opsLimit": Sodium.cryptoPwhashOpslimitInteractive, - // "memLimit": Sodium.cryptoPwhashMemlimitInteractive, - // }); - if (widget.authPass == inputtedPassword) { + final Uint8List? salt = await _lockscreenSetting.getSalt(); + final hash = cryptoPwHash( + utf8.encode(inputtedPassword), + salt!, + sodium.crypto.pwhash.memLimitSensitive, + sodium.crypto.pwhash.opsLimitSensitive, + sodium, + ); + if (widget.authPass == base64Encode(hash)) { await _lockscreenSetting.setInvalidAttemptCount(0); - widget.isOnOpeningApp + widget.isAuthenticatingOnAppLaunch || + widget.isAuthenticatingForInAppChange ? Navigator.of(context).pop(true) : Navigator.of(context).pushReplacement( MaterialPageRoute( @@ -200,7 +218,7 @@ class _LockScreenPasswordState extends State { ); return true; } else { - if (widget.isOnOpeningApp) { + if (widget.isAuthenticatingOnAppLaunch) { invalidAttemptsCount++; await _lockscreenSetting.setInvalidAttemptCount(invalidAttemptsCount); if (invalidAttemptsCount > 4) { @@ -214,7 +232,7 @@ class _LockScreenPasswordState extends State { } Future _confirmPassword() async { - if (widget.isAuthenticating) { + if (widget.isChangingLockScreenSettings) { await _confirmPasswordAuth(_passwordController.text); return; } else { diff --git a/auth/lib/ui/settings/lock_screen/lock_screen_pin.dart b/auth/lib/ui/settings/lock_screen/lock_screen_pin.dart index 05fee3ac2e..e45ec75ac0 100644 --- a/auth/lib/ui/settings/lock_screen/lock_screen_pin.dart +++ b/auth/lib/ui/settings/lock_screen/lock_screen_pin.dart @@ -1,3 +1,5 @@ +import "dart:convert"; + import "package:ente_auth/theme/colors.dart"; import "package:ente_auth/theme/ente_theme.dart"; import "package:ente_auth/theme/text_style.dart"; @@ -5,21 +7,33 @@ import "package:ente_auth/ui/settings/lock_screen/custom_pin_keypad.dart"; import "package:ente_auth/ui/settings/lock_screen/lock_screen_confirm_pin.dart"; import "package:ente_auth/ui/settings/lock_screen/lock_screen_options.dart"; import "package:ente_auth/utils/lock_screen_settings.dart"; +import "package:ente_crypto_dart/ente_crypto_dart.dart"; import "package:flutter/material.dart"; import "package:flutter/services.dart"; import 'package:pinput/pinput.dart'; +/// [isChangingLockScreenSettings] Authentication required for changing lock screen settings. +/// Set to true when the app requires the user to authenticate before allowing +/// changes to the lock screen settings. + +/// [isAuthenticatingOnAppLaunch] Authentication required on app launch. +/// Set to true when the app requires the user to authenticate immediately upon opening. + +/// [isAuthenticatingForInAppChange] Authentication required for in-app changes (e.g., email, password). +/// Set to true when the app requires the to authenticate for sensitive actions like email, password changes. + class LockScreenPin extends StatefulWidget { const LockScreenPin({ super.key, - this.isAuthenticating = false, - this.isOnOpeningApp = false, + this.isChangingLockScreenSettings = false, + this.isAuthenticatingOnAppLaunch = false, + this.isAuthenticatingForInAppChange = false, this.authPin, }); - //Is false when setting a new password - final bool isAuthenticating; - final bool isOnOpeningApp; + final bool isAuthenticatingOnAppLaunch; + final bool isChangingLockScreenSettings; + final bool isAuthenticatingForInAppChange; final String? authPin; @override State createState() => _LockScreenPinState(); @@ -45,18 +59,19 @@ class _LockScreenPinState extends State { } Future confirmPinAuth(String inputtedPin) async { - // final Uint8List? salt = await _lockscreenSetting.getSalt(); - // final hash = cryptoPwHash({ - // "password": utf8.encode(code), - // "salt": salt, - // "opsLimit": Sodium.cryptoPwhashOpslimitInteractive, - // "memLimit": Sodium.cryptoPwhashMemlimitInteractive, - // }); - // final String hashedPin = base64Encode(hash); - if (widget.authPin == inputtedPin) { + final Uint8List? salt = await _lockscreenSetting.getSalt(); + final hash = cryptoPwHash( + utf8.encode(inputtedPin), + salt!, + sodium.crypto.pwhash.memLimitSensitive, + sodium.crypto.pwhash.opsLimitSensitive, + sodium, + ); + if (widget.authPin == base64Encode(hash)) { invalidAttemptsCount = 0; await _lockscreenSetting.setInvalidAttemptCount(0); - widget.isOnOpeningApp + widget.isAuthenticatingOnAppLaunch || + widget.isAuthenticatingForInAppChange ? Navigator.of(context).pop(true) : Navigator.of(context).pushReplacement( MaterialPageRoute( @@ -75,7 +90,7 @@ class _LockScreenPinState extends State { isPinValid = false; }); - if (widget.isOnOpeningApp) { + if (widget.isAuthenticatingOnAppLaunch) { invalidAttemptsCount++; await _lockscreenSetting.setInvalidAttemptCount(invalidAttemptsCount); if (invalidAttemptsCount > 4) { @@ -87,7 +102,7 @@ class _LockScreenPinState extends State { } Future _confirmPin(String inputtedPin) async { - if (widget.isAuthenticating) { + if (widget.isChangingLockScreenSettings) { await confirmPinAuth(inputtedPin); return; } else { @@ -130,26 +145,16 @@ class _LockScreenPinState extends State { ), floatingActionButton: CustomPinKeypad(controller: _pinController), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - // body: OrientationBuilder( - // builder: (context, orientation) { - // return orientation == Orientation.portrait - // ? _getBody(colorTheme, textTheme, isPortrait: true) - // : SingleChildScrollView( - // child: _getBody(colorTheme, textTheme, isPortrait: false), - // ); - // }, - // ), body: SingleChildScrollView( - child: _getBody(colorTheme, textTheme, isPortrait: true), + child: _getBody(colorTheme, textTheme), ), ); } Widget _getBody( EnteColorScheme colorTheme, - EnteTextTheme textTheme, { - required bool isPortrait, - }) { + EnteTextTheme textTheme, + ) { return Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, @@ -219,7 +224,7 @@ class _LockScreenPinState extends State { ), ), Text( - widget.isAuthenticating ? "Enter PIN" : "Set new PIN", + widget.isChangingLockScreenSettings ? "Enter PIN" : "Set new PIN", style: textTheme.bodyBold, ), const Padding(padding: EdgeInsets.all(12)), @@ -263,10 +268,6 @@ class _LockScreenPinState extends State { await _confirmPin(_pinController.text); }, ), - // isPortrait - // ? const Spacer() - // : const Padding(padding: EdgeInsets.all(12)), - // CustomPinKeypad(controller: _pinController), ], ), ); diff --git a/auth/lib/ui/settings/security_section_widget.dart b/auth/lib/ui/settings/security_section_widget.dart index 8fa3249bf5..af45dab4b0 100644 --- a/auth/lib/ui/settings/security_section_widget.dart +++ b/auth/lib/ui/settings/security_section_widget.dart @@ -2,6 +2,8 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:ente_auth/core/configuration.dart'; +import 'package:ente_auth/core/event_bus.dart'; +import 'package:ente_auth/events/app_lock_update_event.dart'; import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/models/user_details.dart'; import 'package:ente_auth/services/local_authentication_service.dart'; @@ -18,6 +20,7 @@ import 'package:ente_auth/ui/settings/common_settings.dart'; import 'package:ente_auth/ui/settings/lock_screen/lock_screen_options.dart'; import 'package:ente_auth/utils/auth_util.dart'; import 'package:ente_auth/utils/dialog_util.dart'; +import 'package:ente_auth/utils/lock_screen_settings.dart'; import 'package:ente_auth/utils/navigation_util.dart'; import 'package:ente_auth/utils/platform_util.dart'; import 'package:ente_auth/utils/toast_util.dart'; @@ -37,15 +40,25 @@ class _SecuritySectionWidgetState extends State { final _config = Configuration.instance; late bool _hasLoggedIn; final Logger _logger = Logger('SecuritySectionWidget'); - + late String appLockSubtitle; + late StreamSubscription _appLockUpdateEvent; @override void initState() { _hasLoggedIn = _config.hasConfiguredAccount(); + appLockSubtitle = LockScreenSettings.instance.getAppLockType(); + _appLockUpdateEvent = Bus.instance.on().listen((event) { + if (mounted) { + setState(() { + appLockSubtitle = LockScreenSettings.instance.getAppLockType(); + }); + } + }); super.initState(); } @override void dispose() { + _appLockUpdateEvent.cancel(); super.dispose(); } @@ -137,8 +150,9 @@ class _SecuritySectionWidgetState extends State { } children.addAll([ MenuItemWidget( - captionedTextWidget: const CaptionedTextWidget( + captionedTextWidget: CaptionedTextWidget( title: "App lock", + subTitle: appLockSubtitle, ), trailingIcon: Icons.chevron_right_outlined, trailingIconIsMuted: true, diff --git a/auth/lib/utils/auth_util.dart b/auth/lib/utils/auth_util.dart index 97c4bb2da3..df11211c92 100644 --- a/auth/lib/utils/auth_util.dart +++ b/auth/lib/utils/auth_util.dart @@ -14,6 +14,7 @@ Future requestAuthentication( BuildContext context, String reason, { bool isOpeningApp = false, + bool isAuthenticatingForInAppChange = false, }) async { Logger("AuthUtil").info("Requesting authentication"); @@ -25,7 +26,8 @@ Future requestAuthentication( context, savedPin, savedPassword, - isOnOpeningApp: isOpeningApp, + isAuthenticatingOnAppLaunch: isOpeningApp, + isAuthenticatingForInAppChange: isAuthenticatingForInAppChange, ); } if (Platform.isMacOS || Platform.isLinux) { diff --git a/auth/lib/utils/lock_screen_settings.dart b/auth/lib/utils/lock_screen_settings.dart index bc5764a3e9..e1b88bd040 100644 --- a/auth/lib/utils/lock_screen_settings.dart +++ b/auth/lib/utils/lock_screen_settings.dart @@ -1,3 +1,8 @@ +import "dart:convert"; +import "dart:typed_data"; + +import "package:ente_crypto_dart/ente_crypto_dart.dart"; +import "package:flutter_secure_storage/flutter_secure_storage.dart"; import "package:shared_preferences/shared_preferences.dart"; class LockScreenSettings { @@ -11,6 +16,7 @@ class LockScreenSettings { static const keyInvalidAttempts = "ls_invalid_attempts"; static const lastInvalidAttemptTime = "ls_last_invalid_attempt_time"; static const autoLockTime = "ls_auto_lock_time"; + static const appLockType = "ls_app_lock_type"; final List autoLockDurations = const [ Duration(seconds: 0), Duration(seconds: 30), @@ -22,11 +28,20 @@ class LockScreenSettings { ]; late SharedPreferences _preferences; - + late FlutterSecureStorage _secureStorage; Future init() async { + _secureStorage = const FlutterSecureStorage(); _preferences = await SharedPreferences.getInstance(); } + Future setAppLockType(String lockType) async { + await _preferences.setString(appLockType, lockType); + } + + String getAppLockType() { + return _preferences.getString(appLockType) ?? "None"; + } + Future setAutoLockTime(Duration duration) async { await _preferences.setInt(autoLockTime, duration.inMilliseconds); } @@ -51,86 +66,85 @@ class LockScreenSettings { await _preferences.setInt(keyInvalidAttempts, count); } - // static Uint8List _generateSalt() { - // return Sodium.randombytesBuf(Sodium.cryptoPwhashSaltbytes); - // } + static Uint8List _generateSalt() { + return sodium.randombytes.buf(sodium.crypto.pwhash.saltBytes); + } Future setPin(String userPin) async { - //await _secureStorage.delete(key: saltKey); + await _secureStorage.delete(key: saltKey); await _preferences.setString(pin, userPin); await _preferences.remove(password); - // final salt = _generateSalt(); - // final hash = cryptoPwHash({ - // "password": utf8.encode(userPin), - // "salt": salt, - // "opsLimit": Sodium.cryptoPwhashOpslimitInteractive, - // "memLimit": Sodium.cryptoPwhashMemlimitInteractive, - // }); + final salt = _generateSalt(); - // final String saltPin = base64Encode(salt); - // final String hashedPin = base64Encode(hash); + final hash = cryptoPwHash( + utf8.encode(userPin), + salt, + sodium.crypto.pwhash.memLimitSensitive, + sodium.crypto.pwhash.opsLimitSensitive, + sodium, + ); + final String saltPin = base64Encode(salt); + final String hashedPin = base64Encode(hash); - // await _secureStorage.write(key: saltKey, value: saltPin); - // await _secureStorage.write(key: pin, value: hashedPin); - // await _secureStorage.delete(key: password); + await _secureStorage.write(key: saltKey, value: saltPin); + await _secureStorage.write(key: pin, value: hashedPin); + await _secureStorage.delete(key: password); return; } - // Future getSalt() async { - // final String? salt = await _secureStorage.read(key: saltKey); - // if (salt == null) return null; - // return base64Decode(salt); - // } + Future getSalt() async { + final String? salt = await _secureStorage.read(key: saltKey); + if (salt == null) return null; + return base64Decode(salt); + } Future getPin() async { - return _preferences.getString(pin); - // return _secureStorage.read(key: pin); + return _secureStorage.read(key: pin); } Future setPassword(String pass) async { await _preferences.setString(password, pass); await _preferences.remove(pin); - // await _secureStorage.delete(key: saltKey); + await _secureStorage.delete(key: saltKey); - // final salt = _generateSalt(); - // final hash = cryptoPwHash({ - // "password": utf8.encode(pass), - // "salt": salt, - // "opsLimit": Sodium.cryptoPwhashOpslimitInteractive, - // "memLimit": Sodium.cryptoPwhashMemlimitInteractive, - // }); + final salt = _generateSalt(); - // final String saltPassword = base64Encode(salt); - // final String hashPassword = base64Encode(hash); + final hash = cryptoPwHash( + utf8.encode(pass), + salt, + sodium.crypto.pwhash.memLimitSensitive, + sodium.crypto.pwhash.opsLimitSensitive, + sodium, + ); - // await _secureStorage.write(key: saltKey, value: saltPassword); - // await _secureStorage.write(key: password, value: hashPassword); - // await _secureStorage.delete(key: pin); + final String saltPassword = base64Encode(salt); + final String hashPassword = base64Encode(hash); + + await _secureStorage.write(key: saltKey, value: saltPassword); + await _secureStorage.write(key: password, value: hashPassword); + await _secureStorage.delete(key: pin); return; } Future getPassword() async { - return _preferences.getString(password); - // return _secureStorage.read(key: password); + return _secureStorage.read(key: password); } Future removePinAndPassword() async { await _preferences.remove(pin); await _preferences.remove(password); - // await _secureStorage.delete(key: saltKey); - // await _secureStorage.delete(key: pin); - // await _secureStorage.delete(key: password); + await _secureStorage.delete(key: saltKey); + await _secureStorage.delete(key: pin); + await _secureStorage.delete(key: password); } Future isPinSet() async { - return _preferences.containsKey(pin); - // return await _secureStorage.containsKey(key: pin); + return await _secureStorage.containsKey(key: pin); } Future isPasswordSet() async { - return _preferences.containsKey(password); - // return await _secureStorage.containsKey(key: password); + return await _secureStorage.containsKey(key: password); } }