diff --git a/src/FingerprintTest/Assets/AboutAssets.txt b/src/FingerprintTest/Assets/AboutAssets.txt
new file mode 100644
index 00000000..ee398862
--- /dev/null
+++ b/src/FingerprintTest/Assets/AboutAssets.txt
@@ -0,0 +1,19 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories) and given a Build Action of "AndroidAsset".
+
+These files will be deployed with you package and will be accessible using Android's
+AssetManager, like this:
+
+public class ReadAsset : Activity
+{
+ protected override void OnCreate (Bundle bundle)
+ {
+ base.OnCreate (bundle);
+
+ InputStream input = Assets.Open ("my_asset.txt");
+ }
+}
+
+Additionally, some Android functions will automatically load asset files:
+
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
\ No newline at end of file
diff --git a/src/FingerprintTest/FingerprintModule.cs b/src/FingerprintTest/FingerprintModule.cs
new file mode 100644
index 00000000..faefaff8
--- /dev/null
+++ b/src/FingerprintTest/FingerprintModule.cs
@@ -0,0 +1,268 @@
+using System;
+using Android.Content;
+using Javax.Crypto;
+using Java.Security;
+using Java.Lang;
+using Android.Views.InputMethods;
+using Android.App;
+using Android.Hardware.Fingerprints;
+using Android.OS;
+using Android.Security.Keystore;
+using Android.Preferences;
+using Java.IO;
+using Java.Security.Cert;
+
+namespace keepass2android
+{
+ public class FingerprintModule
+ {
+ public Context Context { get; set; }
+
+ public FingerprintModule (Context context)
+ {
+ Context = context;
+ }
+
+ public FingerprintManager FingerprintManager
+ {
+ get { return (FingerprintManager) Context.GetSystemService("FingerprintManager"); }
+ }
+
+ public KeyguardManager KeyguardManager
+ {
+ get
+ {
+ return (KeyguardManager) Context.GetSystemService("keyguard");
+ }
+ }
+
+
+ public KeyStore Keystore
+ {
+ get
+ {
+ try
+ {
+ return KeyStore.GetInstance("AndroidKeyStore");
+ }
+ catch (KeyStoreException e)
+ {
+ throw new RuntimeException("Failed to get an instance of KeyStore", e);
+ }
+ }
+ }
+
+ public KeyGenerator KeyGenerator
+ {
+ get
+ {
+ try
+ {
+ return KeyGenerator.GetInstance(KeyProperties.KeyAlgorithmAes, "AndroidKeyStore");
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
+ }
+ }
+ }
+
+ public Cipher Cipher
+ {
+ get
+ {
+ try
+ {
+ return Cipher.GetInstance(KeyProperties.KeyAlgorithmAes + "/"
+ + KeyProperties.BlockModeCbc + "/"
+ + KeyProperties.EncryptionPaddingPkcs7);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException("Failed to get an instance of Cipher", e);
+ }
+ catch (NoSuchPaddingException e)
+ {
+ throw new RuntimeException("Failed to get an instance of Cipher", e);
+ }
+ }
+ }
+
+ public InputMethodManager InputMethodManager
+ {
+ get { return (InputMethodManager) Context.GetSystemService(Context.InputMethodService); }
+ }
+
+ public ISharedPreferences SharedPreferences
+ {
+ get { return PreferenceManager.GetDefaultSharedPreferences(Context); }
+ }
+ }
+
+ public class FingerprintEncryptionModule: FingerprintManager.AuthenticationCallback
+ {
+ public override void OnAuthenticationError(FingerprintState errorCode, ICharSequence errString)
+ {
+ _callback.OnAuthenticationError(errorCode, errString);
+ }
+
+ public override void OnAuthenticationFailed()
+ {
+ if (!_selfCancelled)
+ _callback.OnAuthenticationFailed();
+ }
+
+ public override void OnAuthenticationHelp(FingerprintState helpCode, ICharSequence helpString)
+ {
+ _callback.OnAuthenticationHelp(helpCode, helpString);
+ }
+
+ public override void OnAuthenticationSucceeded(FingerprintManager.AuthenticationResult result)
+ {
+ _callback.OnAuthenticationSucceeded(result);
+ }
+
+ private readonly FingerprintModule _fingerprint;
+ private readonly string _keyId;
+ private Cipher _cipher;
+ private bool _selfCancelled;
+ private CancellationSignal _cancellationSignal;
+ private FingerprintManager.CryptoObject _cryptoObject;
+ private FingerprintManager.AuthenticationCallback _callback;
+
+ public FingerprintEncryptionModule(FingerprintModule fingerprint, string keyId)
+ {
+ _fingerprint = fingerprint;
+ _keyId = keyId;
+ _cipher = fingerprint.Cipher;
+ CreateKey();
+ }
+
+ ///
+ /// Creates a symmetric key in the Android Key Store which can only be used after the user
+ /// has authenticated with fingerprint.
+ ///
+ private void CreateKey()
+ {
+ // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
+ // for your flow. Use of keys is necessary if you need to know if the set of
+ // enrolled fingerprints has changed.
+ try
+ {
+ _fingerprint.Keystore.Load(null);
+ // Set the alias of the entry in Android KeyStore where the key will appear
+ // and the constrains (purposes) in the constructor of the Builder
+ _fingerprint.KeyGenerator.Init(new KeyGenParameterSpec.Builder(GetAlias(_keyId),
+ KeyStorePurpose.Encrypt | KeyStorePurpose.Decrypt)
+ .SetBlockModes(KeyProperties.BlockModeCbc)
+ // Require the user to authenticate with a fingerprint to authorize every use
+ // of the key
+ .SetUserAuthenticationRequired(true)
+ .SetEncryptionPaddings(KeyProperties.EncryptionPaddingPkcs7)
+ .Build());
+ _fingerprint.KeyGenerator.GenerateKey();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (CertificateException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public bool InitCipher()
+ {
+ try
+ {
+ _fingerprint.Keystore.Load(null);
+ var key = _fingerprint.Keystore.GetKey(GetAlias(_keyId), null);
+ _cipher.Init(CipherMode.EncryptMode, key);
+ _cryptoObject = new FingerprintManager.CryptoObject(_cipher);
+ return true;
+ }
+ catch (KeyPermanentlyInvalidatedException)
+ {
+ return false;
+ }
+ catch (KeyStoreException e)
+ {
+ throw new RuntimeException("Failed to init Cipher", e);
+ }
+ catch (CertificateException e)
+ {
+ throw new RuntimeException("Failed to init Cipher", e);
+ }
+ catch (UnrecoverableKeyException e)
+ {
+ throw new RuntimeException("Failed to init Cipher", e);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Failed to init Cipher", e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException("Failed to init Cipher", e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new RuntimeException("Failed to init Cipher", e);
+ }
+ }
+
+ private string GetAlias(string keyId)
+ {
+ return "keepass2android." + keyId;
+ }
+
+ public bool IsFingerprintAuthAvailable
+ {
+ get
+ {
+ return _fingerprint.FingerprintManager.IsHardwareDetected
+ && _fingerprint.FingerprintManager.HasEnrolledFingerprints;
+ }
+ }
+
+ public void StartListening(FingerprintManager.AuthenticationCallback callback)
+ {
+ if (!IsFingerprintAuthAvailable)
+ return;
+
+ _cancellationSignal = new CancellationSignal();
+ _selfCancelled = false;
+ _callback = callback;
+ _fingerprint.FingerprintManager.Authenticate(_cryptoObject, _cancellationSignal, 0 /* flags */, this, null);
+
+ }
+
+ public void StopListening()
+ {
+ if (_cancellationSignal != null)
+ {
+ _selfCancelled = true;
+ _cancellationSignal.Cancel();
+ _cancellationSignal = null;
+ }
+ }
+
+ public void Encrypt(string textToEncrypt)
+ {
+ _cipher.DoFinal(MemUtil)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FingerprintTest/FingerprintTest.csproj b/src/FingerprintTest/FingerprintTest.csproj
new file mode 100644
index 00000000..4049c489
--- /dev/null
+++ b/src/FingerprintTest/FingerprintTest.csproj
@@ -0,0 +1,95 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {52C0A0E7-D625-44BE-948E-D98BC6C82F0F}
+ {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ Properties
+ FingerprintTest
+ FingerprintTest
+ 512
+ true
+ Resources\Resource.Designer.cs
+ Off
+ True
+ v6.0
+ Properties\AndroidManifest.xml
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ True
+ None
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ False
+ SdkOnly
+
+
+
+
+
+
+
+
+
+ ..\packages\Xamarin.Android.Support.v4.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll
+
+
+ ..\packages\Xamarin.Android.Support.v7.AppCompat.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ 21.0.3.0
+
+
+
+
+
\ No newline at end of file
diff --git a/src/FingerprintTest/FingerprintTest.csproj.bak b/src/FingerprintTest/FingerprintTest.csproj.bak
new file mode 100644
index 00000000..d9192d70
--- /dev/null
+++ b/src/FingerprintTest/FingerprintTest.csproj.bak
@@ -0,0 +1,81 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {52C0A0E7-D625-44BE-948E-D98BC6C82F0F}
+ {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ Properties
+ FingerprintTest
+ FingerprintTest
+ 512
+ true
+ Resources\Resource.Designer.cs
+ Off
+ True
+ v5.0
+ Properties\AndroidManifest.xml
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ True
+ None
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ False
+ SdkOnly
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/FingerprintTest/GettingStarted.Xamarin b/src/FingerprintTest/GettingStarted.Xamarin
new file mode 100644
index 00000000..e9d4f6a4
--- /dev/null
+++ b/src/FingerprintTest/GettingStarted.Xamarin
@@ -0,0 +1,4 @@
+
+ GS\Android\CS\AndroidApp\GettingStarted.html
+ false
+
\ No newline at end of file
diff --git a/src/FingerprintTest/MainActivity.cs b/src/FingerprintTest/MainActivity.cs
new file mode 100644
index 00000000..ac8b6c93
--- /dev/null
+++ b/src/FingerprintTest/MainActivity.cs
@@ -0,0 +1,105 @@
+using System;
+using Android;
+using Android.App;
+using Android.Content;
+using Android.Content.PM;
+using Android.Hardware.Fingerprints;
+using Android.Runtime;
+using Android.Views;
+using Android.Widget;
+using Android.OS;
+using Android.Preferences;
+using Android.Support.V7.App;
+using keepass2android;
+
+namespace FingerprintTest
+{
+ [Activity(Label = "FingerprintTest", MainLauncher = true, Icon = "@drawable/icon")]
+ public class MainActivity : AppCompatActivity
+ {
+ int count = 1;
+ const int FINGERPRINT_PERMISSION_REQUEST_CODE = 0;
+
+ protected override void OnCreate(Bundle bundle)
+ {
+ base.OnCreate(bundle);
+
+ // Set our view from the "main" layout resource
+ SetContentView(Resource.Layout.Main);
+
+ // Get our button from the layout resource,
+ // and attach an event to it
+ Button button = FindViewById