mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Better biometric key implementation
This commit is contained in:
@@ -25,9 +25,9 @@ class AdvancedUnlockedViewManager(var context: FragmentActivity,
|
|||||||
var onCheckedPasswordChangeListener: CompoundButton.OnCheckedChangeListener? = null,
|
var onCheckedPasswordChangeListener: CompoundButton.OnCheckedChangeListener? = null,
|
||||||
var passwordView: TextView?,
|
var passwordView: TextView?,
|
||||||
var loadDatabase: (password: String?) -> Unit)
|
var loadDatabase: (password: String?) -> Unit)
|
||||||
: BiometricHelper.BiometricUnlockCallback {
|
: BiometricUnlockDatabaseHelper.BiometricUnlockCallback {
|
||||||
|
|
||||||
private var biometricHelper: BiometricHelper? = null
|
private var biometricUnlockDatabaseHelper: BiometricUnlockDatabaseHelper? = null
|
||||||
private var biometricMode: Mode = Mode.NOT_CONFIGURED
|
private var biometricMode: Mode = Mode.NOT_CONFIGURED
|
||||||
|
|
||||||
private var isBiometricPromptAutoOpenEnable = PreferencesUtil.isBiometricPromptAutoOpenEnable(context)
|
private var isBiometricPromptAutoOpenEnable = PreferencesUtil.isBiometricPromptAutoOpenEnable(context)
|
||||||
@@ -46,11 +46,11 @@ class AdvancedUnlockedViewManager(var context: FragmentActivity,
|
|||||||
|
|
||||||
// Check if fingerprint well init (be called the first time the fingerprint is configured
|
// Check if fingerprint well init (be called the first time the fingerprint is configured
|
||||||
// and the activity still active)
|
// and the activity still active)
|
||||||
if (biometricHelper == null || !biometricHelper!!.isFingerprintInitialized) {
|
if (biometricUnlockDatabaseHelper == null || !biometricUnlockDatabaseHelper!!.isFingerprintInitialized) {
|
||||||
|
|
||||||
biometricHelper = BiometricHelper(context, this)
|
biometricUnlockDatabaseHelper = BiometricUnlockDatabaseHelper(context, this)
|
||||||
// callback for fingerprint findings
|
// callback for fingerprint findings
|
||||||
biometricHelper?.setAuthenticationCallback(biometricCallback)
|
biometricUnlockDatabaseHelper?.setAuthenticationCallback(biometricCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a check listener to change fingerprint mode
|
// Add a check listener to change fingerprint mode
|
||||||
@@ -131,12 +131,12 @@ class AdvancedUnlockedViewManager(var context: FragmentActivity,
|
|||||||
Mode.WAIT_CREDENTIAL -> {}
|
Mode.WAIT_CREDENTIAL -> {}
|
||||||
Mode.STORE -> {
|
Mode.STORE -> {
|
||||||
// newly store the entered password in encrypted way
|
// newly store the entered password in encrypted way
|
||||||
biometricHelper?.encryptData(passwordView?.text.toString())
|
biometricUnlockDatabaseHelper?.encryptData(passwordView?.text.toString())
|
||||||
}
|
}
|
||||||
Mode.OPEN -> {
|
Mode.OPEN -> {
|
||||||
// retrieve the encrypted value from preferences
|
// retrieve the encrypted value from preferences
|
||||||
prefsNoBackup.getString(preferenceKeyValue, null)?.let {
|
prefsNoBackup.getString(preferenceKeyValue, null)?.let {
|
||||||
biometricHelper?.decryptData(it)
|
biometricUnlockDatabaseHelper?.decryptData(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ class AdvancedUnlockedViewManager(var context: FragmentActivity,
|
|||||||
setAdvancedUnlockedTitleView(R.string.open_biometric_prompt_store_credential)
|
setAdvancedUnlockedTitleView(R.string.open_biometric_prompt_store_credential)
|
||||||
setAdvancedUnlockedMessageView("")
|
setAdvancedUnlockedMessageView("")
|
||||||
|
|
||||||
biometricHelper?.initEncryptData { biometricPrompt, cryptoObject, promptInfo ->
|
biometricUnlockDatabaseHelper?.initEncryptData { biometricPrompt, cryptoObject, promptInfo ->
|
||||||
|
|
||||||
cryptoObject?.let { crypto ->
|
cryptoObject?.let { crypto ->
|
||||||
// Set listener to open the biometric dialog and save credential
|
// Set listener to open the biometric dialog and save credential
|
||||||
@@ -193,9 +193,9 @@ class AdvancedUnlockedViewManager(var context: FragmentActivity,
|
|||||||
setAdvancedUnlockedTitleView(R.string.open_biometric_prompt_unlock_database)
|
setAdvancedUnlockedTitleView(R.string.open_biometric_prompt_unlock_database)
|
||||||
setAdvancedUnlockedMessageView("")
|
setAdvancedUnlockedMessageView("")
|
||||||
|
|
||||||
if (biometricHelper != null) {
|
if (biometricUnlockDatabaseHelper != null) {
|
||||||
prefsNoBackup.getString(preferenceKeyIvSpec, null)?.let {
|
prefsNoBackup.getString(preferenceKeyIvSpec, null)?.let {
|
||||||
biometricHelper?.initDecryptData(it) { biometricPrompt, cryptoObject, promptInfo ->
|
biometricUnlockDatabaseHelper?.initDecryptData(it) { biometricPrompt, cryptoObject, promptInfo ->
|
||||||
|
|
||||||
cryptoObject?.let { crypto ->
|
cryptoObject?.let { crypto ->
|
||||||
// Set listener to open the biometric dialog and check credential
|
// Set listener to open the biometric dialog and check credential
|
||||||
@@ -244,7 +244,7 @@ class AdvancedUnlockedViewManager(var context: FragmentActivity,
|
|||||||
|
|
||||||
biometricMode = Mode.UNAVAILABLE
|
biometricMode = Mode.UNAVAILABLE
|
||||||
initBiometricMode()
|
initBiometricMode()
|
||||||
biometricHelper = null
|
biometricUnlockDatabaseHelper = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun inflateOptionsMenu(menuInflater: MenuInflater, menu: Menu) {
|
fun inflateOptionsMenu(menuInflater: MenuInflater, menu: Menu) {
|
||||||
@@ -262,7 +262,7 @@ class AdvancedUnlockedViewManager(var context: FragmentActivity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun deleteEntryKey() {
|
fun deleteEntryKey() {
|
||||||
biometricHelper?.deleteEntryKey()
|
biometricUnlockDatabaseHelper?.deleteEntryKey()
|
||||||
removePrefsNoBackupKey()
|
removePrefsNoBackupKey()
|
||||||
biometricMode = Mode.NOT_CONFIGURED
|
biometricMode = Mode.NOT_CONFIGURED
|
||||||
checkBiometricAvailability()
|
checkBiometricAvailability()
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ import javax.crypto.SecretKey
|
|||||||
import javax.crypto.spec.IvParameterSpec
|
import javax.crypto.spec.IvParameterSpec
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
class BiometricHelper(private val context: FragmentActivity, private val biometricUnlockCallback: BiometricUnlockCallback?) {
|
class BiometricUnlockDatabaseHelper(private val context: FragmentActivity, private val biometricUnlockCallback: BiometricUnlockCallback?) {
|
||||||
|
|
||||||
private var biometricPrompt: BiometricPrompt? = null
|
private var biometricPrompt: BiometricPrompt? = null
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ class BiometricHelper(private val context: FragmentActivity, private val biometr
|
|||||||
.build())
|
.build())
|
||||||
keyGenerator?.generateKey()
|
keyGenerator?.generateKey()
|
||||||
}
|
}
|
||||||
}catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Unable to create a key in keystore", e)
|
Log.e(TAG, "Unable to create a key in keystore", e)
|
||||||
biometricUnlockCallback?.onBiometricException(e)
|
biometricUnlockCallback?.onBiometricException(e)
|
||||||
}
|
}
|
||||||
@@ -289,7 +289,7 @@ class BiometricHelper(private val context: FragmentActivity, private val biometr
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val TAG = BiometricHelper::class.java.name
|
private val TAG = BiometricUnlockDatabaseHelper::class.java.name
|
||||||
|
|
||||||
private const val BIOMETRIC_KEYSTORE = "AndroidKeyStore"
|
private const val BIOMETRIC_KEYSTORE = "AndroidKeyStore"
|
||||||
private const val BIOMETRIC_KEYSTORE_KEY = "com.kunzisoft.keepass.biometric.key"
|
private const val BIOMETRIC_KEYSTORE_KEY = "com.kunzisoft.keepass.biometric.key"
|
||||||
@@ -302,7 +302,7 @@ class BiometricHelper(private val context: FragmentActivity, private val biometr
|
|||||||
*/
|
*/
|
||||||
fun deleteEntryKeyInKeystoreForBiometric(context: FragmentActivity,
|
fun deleteEntryKeyInKeystoreForBiometric(context: FragmentActivity,
|
||||||
biometricUnlockCallback: BiometricUnlockErrorCallback) {
|
biometricUnlockCallback: BiometricUnlockErrorCallback) {
|
||||||
val fingerPrintHelper = BiometricHelper(context, object : BiometricUnlockCallback {
|
val fingerPrintHelper = BiometricUnlockDatabaseHelper(context, object : BiometricUnlockCallback {
|
||||||
|
|
||||||
override fun handleEncryptedResult(value: String, ivSpec: String) {}
|
override fun handleEncryptedResult(value: String, ivSpec: String) {}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ import com.kunzisoft.keepass.activities.stylish.Stylish
|
|||||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistory
|
import com.kunzisoft.keepass.app.database.FileDatabaseHistory
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.education.Education
|
import com.kunzisoft.keepass.education.Education
|
||||||
import com.kunzisoft.keepass.biometric.BiometricHelper
|
import com.kunzisoft.keepass.biometric.BiometricUnlockDatabaseHelper
|
||||||
import com.kunzisoft.keepass.biometric.AdvancedUnlockedViewManager
|
import com.kunzisoft.keepass.biometric.AdvancedUnlockedViewManager
|
||||||
import com.kunzisoft.keepass.icons.IconPackChooser
|
import com.kunzisoft.keepass.icons.IconPackChooser
|
||||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.*
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.*
|
||||||
@@ -252,9 +252,9 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen
|
|||||||
.setPositiveButton(resources.getString(android.R.string.yes)
|
.setPositiveButton(resources.getString(android.R.string.yes)
|
||||||
) { _, _ ->
|
) { _, _ ->
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
BiometricHelper.deleteEntryKeyInKeystoreForBiometric(
|
BiometricUnlockDatabaseHelper.deleteEntryKeyInKeystoreForBiometric(
|
||||||
activity,
|
activity,
|
||||||
object : BiometricHelper.BiometricUnlockErrorCallback {
|
object : BiometricUnlockDatabaseHelper.BiometricUnlockErrorCallback {
|
||||||
override fun onInvalidKeyException(e: Exception) {}
|
override fun onInvalidKeyException(e: Exception) {}
|
||||||
|
|
||||||
override fun onBiometricException(e: Exception) {
|
override fun onBiometricException(e: Exception) {
|
||||||
|
|||||||
@@ -72,12 +72,16 @@ class AdvancedUnlockInfoView @JvmOverloads constructor(context: Context,
|
|||||||
title = context.getString(textId)
|
title = context.getString(textId)
|
||||||
}
|
}
|
||||||
|
|
||||||
var message: CharSequence
|
var message: CharSequence?
|
||||||
get() {
|
get() {
|
||||||
return unlockMessageTextView?.text?.toString() ?: ""
|
return unlockMessageTextView?.text?.toString() ?: ""
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
unlockMessageTextView?.text = value
|
if (value == null || value.isEmpty())
|
||||||
|
unlockMessageTextView?.visibility = GONE
|
||||||
|
else
|
||||||
|
unlockMessageTextView?.visibility = VISIBLE
|
||||||
|
unlockMessageTextView?.text = value ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setMessage(@StringRes textId: Int) {
|
fun setMessage(@StringRes textId: Int) {
|
||||||
|
|||||||
@@ -103,6 +103,7 @@
|
|||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:elevation="4dp"
|
android:elevation="4dp"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
android:src="@drawable/fingerprint"
|
android:src="@drawable/fingerprint"
|
||||||
android:background="@drawable/background_image"
|
android:background="@drawable/background_image"
|
||||||
tools:targetApi="lollipop" />
|
tools:targetApi="lollipop" />
|
||||||
@@ -112,7 +113,6 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:layout_marginBottom="8dp">
|
android:layout_marginBottom="8dp">
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="20dp"
|
android:layout_width="20dp"
|
||||||
|
|||||||
Reference in New Issue
Block a user