mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-22 09:12:17 -05:00
implement Unlock by Samsung Fingerprint (Pass SDK)
This commit is contained in:
parent
41d6b3ac5e
commit
b67f5538ce
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[submodule "SamsungPass"]
|
||||
path = SamsungPass
|
||||
url = https://github.com/sraiteri/Xamarin-Samsung-Pass.git
|
||||
[submodule "src/SamsungPass"]
|
||||
path = src/SamsungPass
|
||||
url = https://github.com/sraiteri/Xamarin-Samsung-Pass.git
|
@ -47,6 +47,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AncientIconSet", "AncientIc
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FingerprintTest", "FingerprintTest\FingerprintTest.csproj", "{52C0A0E7-D625-44BE-948E-D98BC6C82F0F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj", "{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -524,6 +526,24 @@ Global
|
||||
{52C0A0E7-D625-44BE-948E-D98BC6C82F0F}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU
|
||||
{52C0A0E7-D625-44BE-948E-D98BC6C82F0F}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||
{52C0A0E7-D625-44BE-948E-D98BC6C82F0F}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
1
src/SamsungPass
Submodule
1
src/SamsungPass
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 1495b1ad7914fa2be69e111b90039770d101aa3d
|
@ -17,6 +17,12 @@ using Javax.Crypto.Spec;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
public interface IFingerprintAuthCallback
|
||||
{
|
||||
void OnFingerprintAuthSucceeded();
|
||||
void OnFingerprintError(string toString);
|
||||
}
|
||||
|
||||
public class FingerprintModule
|
||||
{
|
||||
public Context Context { get; set; }
|
||||
@ -106,7 +112,7 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class FingerprintCrypt: FingerprintManager.AuthenticationCallback
|
||||
public abstract class FingerprintCrypt: FingerprintManager.AuthenticationCallback, IFingerprintIdentifier
|
||||
{
|
||||
protected const string FailedToInitCipher = "Failed to init Cipher";
|
||||
public override void OnAuthenticationError(FingerprintState errorCode, ICharSequence errString)
|
||||
@ -157,7 +163,9 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
public abstract bool InitCipher();
|
||||
public abstract bool Init();
|
||||
|
||||
|
||||
protected static string GetAlias(string keyId)
|
||||
{
|
||||
return "keepass2android." + keyId;
|
||||
@ -175,6 +183,11 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
public void StartListening(Context ctx, IFingerprintAuthCallback callback)
|
||||
{
|
||||
StartListening(new FingerprintAuthCallbackAdapter(callback, ctx));
|
||||
}
|
||||
|
||||
public void StartListening(FingerprintManager.AuthenticationCallback callback)
|
||||
{
|
||||
if (!IsFingerprintAuthAvailable)
|
||||
@ -227,6 +240,13 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
public interface IFingerprintIdentifier
|
||||
{
|
||||
bool Init();
|
||||
void StartListening(Context ctx, IFingerprintAuthCallback callback);
|
||||
void StopListening();
|
||||
}
|
||||
|
||||
public class FingerprintDecryption : FingerprintCrypt
|
||||
{
|
||||
private readonly Context _context;
|
||||
@ -245,9 +265,9 @@ namespace keepass2android
|
||||
_iv = Base64.Decode(PreferenceManager.GetDefaultSharedPreferences(context).GetString(GetIvPrefKey(prefKey), null), 0);
|
||||
}
|
||||
|
||||
public override bool InitCipher()
|
||||
public override bool Init()
|
||||
{
|
||||
Kp2aLog.Log("FP: InitCipher for Dec");
|
||||
Kp2aLog.Log("FP: Init for Dec");
|
||||
try
|
||||
{
|
||||
_keystore.Load(null);
|
||||
@ -355,9 +375,9 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
public override bool InitCipher()
|
||||
public override bool Init()
|
||||
{
|
||||
Kp2aLog.Log("FP: InitCipher for Enc ");
|
||||
Kp2aLog.Log("FP: Init for Enc ");
|
||||
try
|
||||
{
|
||||
_keystore.Load(null);
|
||||
|
141
src/keepass2android/FingerprintSamsungIdentifier.cs
Normal file
141
src/keepass2android/FingerprintSamsungIdentifier.cs
Normal file
@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Com.Samsung.Android.Sdk;
|
||||
using Com.Samsung.Android.Sdk.Pass;
|
||||
using Java.Lang;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
class FingerprintSamsungIdentifier: IFingerprintIdentifier
|
||||
{
|
||||
SpassFingerprint _spassFingerprint;
|
||||
Spass _spass;
|
||||
public FingerprintSamsungIdentifier(Context context)
|
||||
{
|
||||
_spass = new Spass();
|
||||
|
||||
try
|
||||
{
|
||||
_spass.Initialize(context);
|
||||
}
|
||||
catch (SecurityException)
|
||||
{
|
||||
//"Did you add the permission to the AndroidManifest.xml?");
|
||||
throw;
|
||||
}
|
||||
|
||||
if (_spass.IsFeatureEnabled(Spass.DeviceFingerprint))
|
||||
{
|
||||
_spassFingerprint = new SpassFingerprint(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("Fingerprint Featue not available.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public bool Init()
|
||||
{
|
||||
try
|
||||
{
|
||||
return _spassFingerprint.HasRegisteredFinger;
|
||||
}
|
||||
catch (UnsupportedOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
class IdentifyListener : Java.Lang.Object, IIdentifyListener
|
||||
{
|
||||
private readonly IFingerprintAuthCallback _callback;
|
||||
private readonly Context _context;
|
||||
private readonly FingerprintSamsungIdentifier _id;
|
||||
|
||||
|
||||
public IdentifyListener(IFingerprintAuthCallback callback, Context context, FingerprintSamsungIdentifier id)
|
||||
{
|
||||
_callback = callback;
|
||||
_context = context;
|
||||
_id = id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void OnFinished (int responseCode)
|
||||
{
|
||||
_id.Listening = false;
|
||||
if (responseCode == SpassFingerprint.StatusAuthentificationSuccess)
|
||||
{
|
||||
_callback.OnFingerprintAuthSucceeded();
|
||||
}
|
||||
else if (responseCode == SpassFingerprint.StatusAuthentificationPasswordSuccess)
|
||||
{
|
||||
_callback.OnFingerprintAuthSucceeded();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void OnReady ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnStarted ()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal bool Listening
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
|
||||
public void StartListening(Context ctx, IFingerprintAuthCallback callback)
|
||||
{
|
||||
if (Listening) return;
|
||||
|
||||
try
|
||||
{
|
||||
_spassFingerprint.StartIdentifyWithDialog(ctx, new IdentifyListener(callback, ctx, this), false);
|
||||
Listening = true;
|
||||
}
|
||||
catch (SpassInvalidStateException m)
|
||||
{
|
||||
callback.OnFingerprintError(m.Message);
|
||||
}
|
||||
catch (IllegalStateException ex)
|
||||
{
|
||||
callback.OnFingerprintError(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void StopListening()
|
||||
{
|
||||
try
|
||||
{
|
||||
_spassFingerprint.CancelIdentify();
|
||||
Listening = false;
|
||||
}
|
||||
catch (IllegalStateException ise)
|
||||
{
|
||||
Kp2aLog.Log(ise.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ namespace keepass2android
|
||||
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/MyTheme_ActionBar", MainLauncher = false)]
|
||||
[IntentFilter(new[] { "kp2a.action.FingerprintSetupActivity" }, Categories = new[] { Intent.CategoryDefault })]
|
||||
public class FingerprintSetupActivity : LockCloseActivity
|
||||
public class FingerprintSetupActivity : LockCloseActivity, IFingerprintAuthCallback
|
||||
{
|
||||
private readonly ActivityDesign _activityDesign;
|
||||
|
||||
@ -119,8 +119,29 @@ namespace keepass2android
|
||||
FindViewById(Resource.Id.radio_buttons).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fingerprint_auth_container).Visibility = ViewStates.Gone;
|
||||
|
||||
if ((int)Build.VERSION.SdkInt >= 23)
|
||||
RequestPermissions(new[] { Manifest.Permission.UseFingerprint }, FingerprintPermissionRequestCode);
|
||||
if ((int) Build.VERSION.SdkInt >= 23)
|
||||
RequestPermissions(new[] {Manifest.Permission.UseFingerprint}, FingerprintPermissionRequestCode);
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
//try to create a Samsung ID object
|
||||
_samsungFingerprint = new FingerprintSamsungIdentifier(this);
|
||||
if (!_samsungFingerprint.Init())
|
||||
{
|
||||
SetError(Resource.String.fingerprint_no_enrolled);
|
||||
}
|
||||
ShowRadioButtons();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_samsungFingerprint = null;
|
||||
}
|
||||
|
||||
}
|
||||
FindViewById(Resource.Id.container_fingerprint_unlock).Visibility = _samsungFingerprint == null
|
||||
? ViewStates.Visible
|
||||
: ViewStates.Gone;
|
||||
}
|
||||
|
||||
string CurrentPreferenceKey
|
||||
@ -181,18 +202,32 @@ namespace keepass2android
|
||||
SetError(Resource.String.fingerprint_no_enrolled);
|
||||
return;
|
||||
}
|
||||
FindViewById<TextView>(Resource.Id.tvFatalError).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.radio_buttons).Visibility = ViewStates.Visible;
|
||||
FindViewById(Resource.Id.fingerprint_auth_container).Visibility = ViewStates.Gone;
|
||||
ShowRadioButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowRadioButtons()
|
||||
{
|
||||
FindViewById<TextView>(Resource.Id.tvFatalError).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.radio_buttons).Visibility = ViewStates.Visible;
|
||||
FindViewById(Resource.Id.fingerprint_auth_container).Visibility = ViewStates.Gone;
|
||||
}
|
||||
|
||||
|
||||
private void ChangeUnlockMode(FingerprintUnlockMode oldMode, FingerprintUnlockMode newMode)
|
||||
{
|
||||
if (oldMode == newMode)
|
||||
return;
|
||||
|
||||
if (_samsungFingerprint != null)
|
||||
{
|
||||
_unlockMode = newMode;
|
||||
ISharedPreferencesEditor edit = PreferenceManager.GetDefaultSharedPreferences(this).Edit();
|
||||
edit.PutString(App.Kp2a.GetDb().CurrentFingerprintModePrefKey, _unlockMode.ToString());
|
||||
edit.Commit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (newMode == FingerprintUnlockMode.Disabled)
|
||||
{
|
||||
_unlockMode = newMode;
|
||||
@ -207,10 +242,10 @@ namespace keepass2android
|
||||
_enc = new FingerprintEncryption(new FingerprintModule(this), CurrentPreferenceKey);
|
||||
try
|
||||
{
|
||||
if (!_enc.InitCipher())
|
||||
if (!_enc.Init())
|
||||
throw new Exception("Failed to initialize cipher");
|
||||
ResetErrorTextRunnable();
|
||||
_enc.StartListening(new SetupCallback(this));
|
||||
_enc.StartListening(new FingerprintAuthCallbackAdapter(this, this));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -227,7 +262,10 @@ namespace keepass2android
|
||||
static readonly long SUCCESS_DELAY_MILLIS = 1300;
|
||||
private ImageView _fpIcon;
|
||||
private TextView _fpTextView;
|
||||
public void OnAuthSucceeded()
|
||||
|
||||
private FingerprintSamsungIdentifier _samsungFingerprint;
|
||||
|
||||
public void OnFingerprintAuthSucceeded()
|
||||
{
|
||||
_unlockMode = _desiredUnlockMode;
|
||||
|
||||
@ -248,6 +286,7 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void OnFingerprintError(string error)
|
||||
{
|
||||
_fpIcon.SetImageResource(Resource.Drawable.ic_fingerprint_error);
|
||||
@ -270,7 +309,7 @@ namespace keepass2android
|
||||
{
|
||||
base.OnResume();
|
||||
if (_enc != null)
|
||||
_enc.StartListening(new SetupCallback(this));
|
||||
_enc.StartListening(new FingerprintAuthCallbackAdapter(this, this));
|
||||
}
|
||||
|
||||
protected override void OnPause()
|
||||
@ -281,33 +320,4 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
internal class SetupCallback : FingerprintManager.AuthenticationCallback
|
||||
{
|
||||
private readonly FingerprintSetupActivity _fingerprintSetupActivity;
|
||||
|
||||
public SetupCallback(FingerprintSetupActivity fingerprintSetupActivity)
|
||||
{
|
||||
_fingerprintSetupActivity = fingerprintSetupActivity;
|
||||
}
|
||||
|
||||
public override void OnAuthenticationSucceeded(FingerprintManager.AuthenticationResult result)
|
||||
{
|
||||
_fingerprintSetupActivity.OnAuthSucceeded();
|
||||
}
|
||||
|
||||
public override void OnAuthenticationError(FingerprintState errorCode, ICharSequence errString)
|
||||
{
|
||||
_fingerprintSetupActivity.OnFingerprintError(errString.ToString());
|
||||
}
|
||||
|
||||
public override void OnAuthenticationHelp(FingerprintState helpCode, ICharSequence helpString)
|
||||
{
|
||||
_fingerprintSetupActivity.OnFingerprintError(helpString.ToString());
|
||||
}
|
||||
|
||||
public override void OnAuthenticationFailed()
|
||||
{
|
||||
_fingerprintSetupActivity.OnFingerprintError(_fingerprintSetupActivity.Resources.GetString(Resource.String.fingerprint_not_recognized));
|
||||
}
|
||||
}
|
||||
}
|
@ -64,8 +64,7 @@ namespace KeeChallenge
|
||||
|
||||
private byte[] GenerateChallenge()
|
||||
{
|
||||
CryptoRandom rand = CryptoRandom.Instance;
|
||||
byte[] chal = CryptoRandom.Instance.GetRandomBytes(challengeLenBytes);
|
||||
byte[] chal = CryptoRandom.Instance.GetRandomBytes(challengeLenBytes);
|
||||
if (LT64)
|
||||
{
|
||||
chal[challengeLenBytes - 2] = (byte)~chal[challengeLenBytes - 1];
|
||||
|
@ -700,6 +700,7 @@ namespace keepass2android
|
||||
private ActivityDesign _activityDesign;
|
||||
private FingerprintDecryption _fingerprintDec;
|
||||
private bool _fingerprintPermissionGranted;
|
||||
private PasswordActivityBroadcastReceiver _intentReceiver;
|
||||
|
||||
|
||||
internal class MyActionBarDrawerToggle : ActionBarDrawerToggle
|
||||
@ -757,6 +758,11 @@ namespace keepass2android
|
||||
_activityDesign.ApplyTheme();
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
_intentReceiver = new PasswordActivityBroadcastReceiver(this);
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.AddAction(Intent.ActionScreenOff);
|
||||
RegisterReceiver(_intentReceiver, filter);
|
||||
|
||||
|
||||
//use FlagSecure to make sure the last (revealed) character of the master password is not visible in recent apps
|
||||
if (PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean(
|
||||
@ -1800,7 +1806,7 @@ namespace keepass2android
|
||||
|
||||
btn.Tag = GetString(Resource.String.fingerprint_unlock_hint);
|
||||
|
||||
if (_fingerprintDec.InitCipher())
|
||||
if (_fingerprintDec.Init())
|
||||
{
|
||||
btn.SetImageResource(Resource.Drawable.ic_fp_40px);
|
||||
_fingerprintDec.StartListening(new FingerprintAuthCallbackAdapter(this, this));
|
||||
@ -2044,13 +2050,36 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
}
|
||||
private class PasswordActivityBroadcastReceiver : BroadcastReceiver
|
||||
{
|
||||
readonly PasswordActivity _activity;
|
||||
public PasswordActivityBroadcastReceiver(PasswordActivity activity)
|
||||
{
|
||||
_activity = activity;
|
||||
}
|
||||
|
||||
public override void OnReceive(Context context, Intent intent)
|
||||
{
|
||||
switch (intent.Action)
|
||||
{
|
||||
case Intent.ActionScreenOff:
|
||||
Kp2aLog.Log("bla");
|
||||
_activity.OnScreenLocked();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnScreenLocked()
|
||||
{
|
||||
if (_fingerprintDec != null)
|
||||
_fingerprintDec.StopListening();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public interface IFingerprintAuthCallback
|
||||
{
|
||||
void OnFingerprintAuthSucceeded();
|
||||
void OnFingerprintError(string toString);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -99,4 +99,6 @@
|
||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
||||
<uses-permission android:name="keepass2android.keepass2android_debug.permission.KP2aInternalFileBrowsing" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<!-- Samsung Pass permission -->
|
||||
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
|
||||
</manifest>
|
@ -102,4 +102,6 @@
|
||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
||||
<uses-permission android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<!-- Samsung Pass permission -->
|
||||
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
|
||||
</manifest>
|
@ -80,4 +80,6 @@
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<!-- Samsung Pass permission -->
|
||||
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
|
||||
</manifest>
|
@ -43,7 +43,7 @@ namespace keepass2android
|
||||
private QuickUnlockBroadcastReceiver _intentReceiver;
|
||||
private ActivityDesign _design;
|
||||
private bool _fingerprintPermissionGranted;
|
||||
private FingerprintDecryption _fingerprintDec;
|
||||
private IFingerprintIdentifier _fingerprintIdentifier;
|
||||
private int _quickUnlockLength;
|
||||
private const int FingerprintPermissionRequestCode = 0;
|
||||
|
||||
@ -139,8 +139,12 @@ namespace keepass2android
|
||||
filter.AddAction(Intents.DatabaseLocked);
|
||||
RegisterReceiver(_intentReceiver, filter);
|
||||
|
||||
if ((int)Build.VERSION.SdkInt >= 23)
|
||||
RequestPermissions(new[] { Manifest.Permission.UseFingerprint }, FingerprintPermissionRequestCode);
|
||||
if ((int) Build.VERSION.SdkInt >= 23)
|
||||
RequestPermissions(new[] {Manifest.Permission.UseFingerprint}, FingerprintPermissionRequestCode);
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -176,7 +180,7 @@ namespace keepass2android
|
||||
|
||||
public void OnFingerprintAuthSucceeded()
|
||||
{
|
||||
_fingerprintDec.StopListening();
|
||||
_fingerprintIdentifier.StopListening();
|
||||
var btn = FindViewById<ImageButton>(Resource.Id.fingerprintbtn);
|
||||
|
||||
btn.SetImageResource(Resource.Drawable.ic_fingerprint_success);
|
||||
@ -207,23 +211,42 @@ namespace keepass2android
|
||||
return;
|
||||
}
|
||||
|
||||
FingerprintModule fpModule = new FingerprintModule(this);
|
||||
_fingerprintDec = new FingerprintDecryption(fpModule, App.Kp2a.GetDb().CurrentFingerprintPrefKey, this,
|
||||
App.Kp2a.GetDb().CurrentFingerprintPrefKey);
|
||||
|
||||
if (_fingerprintPermissionGranted)
|
||||
{
|
||||
FingerprintModule fpModule = new FingerprintModule(this);
|
||||
_fingerprintIdentifier = new FingerprintDecryption(fpModule, App.Kp2a.GetDb().CurrentFingerprintPrefKey, this,
|
||||
App.Kp2a.GetDb().CurrentFingerprintPrefKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
_fingerprintIdentifier = new FingerprintSamsungIdentifier(this);
|
||||
btn.Click += (sender, args) =>
|
||||
{
|
||||
if (_fingerprintIdentifier.Init())
|
||||
_fingerprintIdentifier.StartListening(this, this);
|
||||
};
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
FindViewById<ImageButton>(Resource.Id.fingerprintbtn).Visibility = ViewStates.Gone;
|
||||
return;
|
||||
}
|
||||
}
|
||||
btn.Tag = GetString(Resource.String.fingerprint_unlock_hint);
|
||||
|
||||
if (_fingerprintDec.InitCipher())
|
||||
if (_fingerprintIdentifier.Init())
|
||||
{
|
||||
btn.SetImageResource(Resource.Drawable.ic_fp_40px);
|
||||
_fingerprintDec.StartListening(new FingerprintAuthCallbackAdapter(this, this));
|
||||
_fingerprintIdentifier.StartListening(this, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
//key invalidated permanently
|
||||
btn.SetImageResource(Resource.Drawable.ic_fingerprint_error);
|
||||
btn.Tag = GetString(Resource.String.fingerprint_unlock_failed);
|
||||
_fingerprintDec = null;
|
||||
_fingerprintIdentifier = null;
|
||||
|
||||
ClearFingerprintUnlockData();
|
||||
}
|
||||
@ -233,7 +256,7 @@ namespace keepass2android
|
||||
btn.SetImageResource(Resource.Drawable.ic_fingerprint_error);
|
||||
btn.Tag = "Error initializing Fingerprint Unlock: " + e;
|
||||
|
||||
_fingerprintDec = null;
|
||||
_fingerprintIdentifier = null;
|
||||
}
|
||||
|
||||
|
||||
@ -294,23 +317,17 @@ namespace keepass2android
|
||||
}, 50);
|
||||
|
||||
|
||||
if (_fingerprintPermissionGranted)
|
||||
{
|
||||
InitFingerprintUnlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
FindViewById<ImageButton>(Resource.Id.fingerprintbtn).Visibility = ViewStates.Gone;
|
||||
|
||||
}
|
||||
InitFingerprintUnlock();
|
||||
|
||||
}
|
||||
|
||||
protected override void OnPause()
|
||||
{
|
||||
base.OnPause();
|
||||
if (_fingerprintDec != null)
|
||||
if (_fingerprintIdentifier != null)
|
||||
{
|
||||
_fingerprintDec.StopListening();
|
||||
_fingerprintIdentifier.StopListening();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/container_fingerprint_unlock"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<RadioButton
|
||||
|
@ -136,6 +136,7 @@
|
||||
<Compile Include="EntryActivityClasses\ToggleVisibilityPopupMenuItem.cs" />
|
||||
<Compile Include="EntryActivityClasses\WriteBinaryToFilePopupItem.cs" />
|
||||
<Compile Include="FingerprintModule.cs" />
|
||||
<Compile Include="FingerprintSamsungIdentifier.cs" />
|
||||
<Compile Include="FingerprintSetupActivity.cs" />
|
||||
<Compile Include="ExportDatabaseActivity.cs" />
|
||||
<Compile Include="fileselect\FileChooserFileProvider.cs" />
|
||||
@ -756,6 +757,10 @@
|
||||
<Project>{3DA3911E-36DE-465E-8F15-F1991B6437E5}</Project>
|
||||
<Name>PluginSdkBinding</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj">
|
||||
<Project>{3a4b8e88-fa9b-4663-bcda-21c12e3af98a}</Project>
|
||||
<Name>SamsungPass</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\TwofishCipher\TwofishCipher.csproj">
|
||||
<Project>{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}</Project>
|
||||
<Name>TwofishCipher</Name>
|
||||
|
Loading…
Reference in New Issue
Block a user