+ first version of MasterKee plugin

This commit is contained in:
Philipp Crocoll 2014-07-13 20:58:10 +02:00
parent 2e56a007fc
commit d93946ed05
36 changed files with 1865 additions and 367 deletions

22
.gitignore vendored
View File

@ -260,3 +260,25 @@ Thumbs.db
/src/java/PluginInputStick/icons /src/java/PluginInputStick/icons
/src/PluginSdkBinding/bin/Release /src/PluginSdkBinding/bin/Release
/src/MasterPassword/bin/Debug
/src/MasterPassword/obj/Debug
/src/MasterPassword/obj/Release
/src/MPTest/bin/Debug
/src/MPTest/obj/Debug
/src/MasterKeePlugin/obj/Release
/src/MasterKeePlugin/bin/Debug
/src/MasterKeePlugin/bin/Release
/src/MasterKeePlugin/obj/Debug
/src/PluginSdkBinding/obj/Release
/src/MasterPassword/bin/Release
/src/java/MasterKee
/src/PluginSdkBinding/obj/ReleaseNoNet

View File

@ -29,6 +29,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginTOTP", "PluginTOTP\Pl
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginHostTest", "PluginHostTest\PluginHostTest.csproj", "{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginHostTest", "PluginHostTest\PluginHostTest.csproj", "{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasterKeePlugin", "MasterKeePlugin\MasterKeePlugin.csproj", "{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasterPassword", "MasterPassword\MasterPassword.csproj", "{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MPTest", "MPTest\MPTest.csproj", "{96A3EA5A-7024-479F-A5B1-06654D0867A3}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -336,6 +342,66 @@ Global
{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU {C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU
{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU {C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU {C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Debug|Win32.ActiveCfg = Debug|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Debug|x64.ActiveCfg = Debug|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Release|Any CPU.Build.0 = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Release|Any CPU.Deploy.0 = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Release|Win32.ActiveCfg = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.Release|x64.ActiveCfg = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.ReleaseNoNet|Any CPU.Deploy.0 = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Debug|Win32.ActiveCfg = Debug|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Debug|x64.ActiveCfg = Debug|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Release|Any CPU.Build.0 = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Release|Win32.ActiveCfg = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.Release|x64.ActiveCfg = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Debug|Win32.ActiveCfg = Debug|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Debug|x64.ActiveCfg = Debug|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Release|Any CPU.Build.0 = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Release|Win32.ActiveCfg = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.Release|x64.ActiveCfg = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{96A3EA5A-7024-479F-A5B1-06654D0867A3}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -11,6 +11,21 @@ namespace MPTest
[TestClass()] [TestClass()]
public class MpAlgorithmTests public class MpAlgorithmTests
{ {
static sbyte[] ToSignedByteArray(byte[] unsigned)
{
sbyte[] signed = new sbyte[unsigned.Length];
Buffer.BlockCopy(unsigned, 0, signed, 0, unsigned.Length);
return signed;
}
static byte[] ToUnsignedByteArray(sbyte[] signed)
{
byte[] unsigned = new byte[signed.Length];
Buffer.BlockCopy(signed, 0, unsigned, 0, signed.Length);
return unsigned;
}
private static byte[] HashHMAC(byte[] key, byte[] message) private static byte[] HashHMAC(byte[] key, byte[] message)
{ {
var hash = new HMACSHA256(key); var hash = new HMACSHA256(key);
@ -28,7 +43,7 @@ namespace MPTest
}; };
var result = MpAlgorithm.GetKeyForPassword("u", "test"); var result = MpAlgorithm.GetKeyForPassword("u", "test");
Assert.IsTrue(expectedRes.SequenceEqual(result)); Assert.IsTrue(expectedRes.SequenceEqual(ToSignedByteArray(result)));
} }
[TestMethod] [TestMethod]
@ -63,7 +78,7 @@ namespace MPTest
{ {
-53, -69, -89, 48, 122, 56, 34, 13, -70, -103, 102, 90, -96, -75, 45, 68, 43, 67, 97, 60, 84, -90, 98, -95, -2, -2, 99, -60, -121, -2, -26, -45, 53, -31, 47, 0, -46, -97, 77, -41, 63, -15, -30, 60, 4, -120, 32, 122, -94, 42, 122, -103, -61, -115, 75, -123, -15, 47, 61, -100, -119, 115, 118, 82 -53, -69, -89, 48, 122, 56, 34, 13, -70, -103, 102, 90, -96, -75, 45, 68, 43, 67, 97, 60, 84, -90, 98, -95, -2, -2, 99, -60, -121, -2, -26, -45, 53, -31, 47, 0, -46, -97, 77, -41, 63, -15, -30, 60, 4, -120, 32, 122, -94, 42, 122, -103, -61, -115, 75, -123, -15, 47, 61, -100, -119, 115, 118, 82
}; };
Assert.IsTrue(expected.SequenceEqual(key)); Assert.IsTrue(expected.SequenceEqual(ToSignedByteArray(key)));
} }
} }
} }

View File

@ -0,0 +1,38 @@
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.Views;
using Android.Widget;
using Keepass2android.Pluginsdk;
namespace MasterKeePlugin
{
[BroadcastReceiver(Exported = true)]
[IntentFilter(new[] { Strings.ActionTriggerRequestAccess, Strings.ActionReceiveAccess, Strings.ActionRevokeAccess })]
public class AccessReceiver: PluginAccessBroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Android.Util.Log.Debug("KP2A_MasterKee", intent.Action);
base.OnReceive(context, intent);
}
public override IList<string> Scopes
{
get
{
return new List<string>
{
Strings.ScopeCurrentEntry,
Strings.ScopeQueryCredentialsForOwnPackage
};
}
}
}
}

View File

@ -0,0 +1,80 @@
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Java.Util;
using KeePassLib.Utility;
using Keepass2android.Pluginsdk;
namespace MasterKeePlugin
{
[BroadcastReceiver(Exported = true)]
[IntentFilter(new[] {Strings.ActionOpenEntry, Strings.ActionEntryActionSelected })]
public class ActionReceiver: PluginActionBroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Android.Util.Log.Debug("KP2A_MasterKee", intent.Action);
base.OnReceive(context, intent);
}
private static byte[] HashHMAC(byte[] key, byte[] message)
{
var hash = new HMACSHA256(key);
return hash.ComputeHash(message);
}
protected override void OpenEntry(OpenEntryAction oe)
{
string masterkey;
Android.Util.Log.Debug("KP2A_MasterKee", "Opening entry...");
if (oe.EntryFields.TryGetValue("MK_MasterKey", out masterkey))
{
Android.Util.Log.Debug("KP2A_MasterKee", "Entry is MK entry.");
string type;
if (!oe.EntryFields.TryGetValue("MK_Type", out type))
type = "Long Password";
int counter = 1;
string strCounter;
if (oe.EntryFields.TryGetValue("MK_Site_Counter", out strCounter))
{
int.TryParse(strCounter, out counter);
}
Android.Util.Log.Debug("KP2A_MasterKee", "Calculating password...");
string calculatedKey = MasterPassword.MpAlgorithm.GenerateContent(type,
oe.EntryFields[KeepassDefs.TitleField],
MemUtil.HexStringToByteArray(masterkey),
counter,
HashHMAC
);
Android.Util.Log.Debug("KP2A_MasterKee", "ok. Returning data.");
try
{
oe.SetEntryField(KeepassDefs.PasswordField, calculatedKey, true);
oe.SetEntryField("MK_MasterKey", "", true);
oe.SetEntryField("MK_Type", "", true);
oe.SetEntryField("MK_Site_Counter", "", true);
}
catch (Exception e)
{
Android.Util.Log.Debug("KP2A_MasterKee", e.ToString());
}
}
Android.Util.Log.Debug("KP2A_MasterKee", "Done.");
}
protected override void ActionSelected(ActionSelectedAction asa)
{
}
}
}

View File

@ -0,0 +1,26 @@
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.Views;
using Android.Widget;
namespace MasterKeePlugin
{
//TODO remove?
[Activity(Label = "@string/AddMkEntry")]
public class AddMasterKeeActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
}
}
}

View File

@ -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");

View File

@ -0,0 +1,156 @@
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Java.Lang;
using MasterKeePlugin;
using Exception = System.Exception;
using Object = Java.Lang.Object;
namespace keepass2android.Utils
{
public class LoadingDialog<TParams, TProgress, TResult> : AsyncTask<TParams, TProgress, TResult>
{
private readonly Context _context;
private readonly string _message;
private readonly bool _cancelable;
readonly Func<Object[], Object> _doInBackground;
readonly Action<Object> _onPostExecute;
private ProgressDialog mDialog;
/**
* Default is {@code 500}ms
*/
private int mDelayTime = 500;
/**
* Flag to use along with {@link #mDelayTime}
*/
private bool mFinished = false;
private Exception mLastException;
public LoadingDialog(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public LoadingDialog(Context context, string message, bool cancelable, Func<Object[], Object> doInBackground,
Action<Object> onPostExecute)
{
_context = context;
_message = message;
_cancelable = cancelable;
_doInBackground = doInBackground;
_onPostExecute = onPostExecute;
Initialize();
}
private void Initialize()
{
mDialog = new ProgressDialog(_context);
mDialog.SetMessage(_message);
mDialog.Indeterminate = true;
mDialog.SetCancelable(_cancelable);
if (_cancelable)
{
mDialog.SetCanceledOnTouchOutside(true);
mDialog.CancelEvent += (sender, args) => mDialog.Cancel();
}
}
protected override void OnPreExecute()
{
new Handler().PostDelayed(() =>
{
if (!mFinished)
{
try
{
/*
* sometime the activity has been finished before we
* show this dialog, it will raise error
*/
mDialog.Show();
}
catch (Exception t)
{
Android.Util.Log.Debug("LD", t.ToString());
}
}
}
, mDelayTime);
}
/**
* If you override this method, you must call {@code super.onCancelled()} at
* beginning of the method.
*/
protected override void OnCancelled() {
DoFinish();
base.OnCancelled();
}// onCancelled()
private void DoFinish() {
mFinished = true;
try {
/*
* Sometime the activity has been finished before we dismiss this
* dialog, it will raise error.
*/
mDialog.Dismiss();
} catch (Exception e)
{
Android.Util.Log.Debug("LD", e.ToString());
}
}// doFinish()
/**
* Sets last exception. This method is useful in case an exception raises
* inside {@link #doInBackground(Void...)}
*
* @param t
* {@link Throwable}
*/
protected void SetLastException(Exception e) {
mLastException = e;
}// setLastException()
/**
* Gets last exception.
*
* @return {@link Throwable}
*/
protected Exception GetLastException() {
return mLastException;
}// getLastException()
protected override Object DoInBackground(params Object[] @params)
{
return _doInBackground(@params);
}
protected override TResult RunInBackground(params TParams[] @params)
{
throw new NotImplementedException();
}
protected override void OnPostExecute(Object result)
{
DoFinish();
if (_onPostExecute != null)
_onPostExecute(result);
}
}
}

View File

@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Preferences;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Keepass2android.Pluginsdk;
namespace MasterKeePlugin
{
[Activity(Label = "MasterKee", MainLauncher = true, Icon = "@drawable/ic_launcher")]
public class MainActivity : Activity
{
private const string KEY_MK_ENTRY_ID = "KEY_MK_ENTRY_ID";
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
Button buttonSelect = FindViewById<Button>(Resource.Id.btnSelectMaster);
buttonSelect.Click += delegate {
var intent = Kp2aControl.QueryEntryIntentForOwnPackage;
try
{
StartActivityForResult(intent, 123);
}
catch (ActivityNotFoundException)
{
Toast.MakeText(this, "No Keepass2Android host app found. Please install Keepass2Android 0.9.4 or above!", ToastLength.Long).Show();
}
};
Button buttonCreateMaster = FindViewById<Button>(Resource.Id.btnSetupMaster);
buttonCreateMaster.Click += delegate
{
StartActivityForResult(new Intent(this, typeof (SetupMasterEntryActivity)), 124);
};
FindViewById(Resource.Id.btnAddEntry).Click += delegate
{
//StartActivityForResult(new Intent(this, typeof()), 125);
var prefs = PreferenceManager.GetDefaultSharedPreferences(this);
Dictionary<string, string> fields = new Dictionary<string, string>();
fields["MK_Site_Counter"] = "1";
fields["MK_Type"] = "Long Password";
fields[KeepassDefs.PasswordField] = "{MASTERKEE}";
fields["MK_MasterKey"] = "{REF:P@I:" + prefs.GetString(KEY_MK_ENTRY_ID, "") + "}";
try
{
StartActivityForResult(Kp2aControl.GetAddEntryIntent(fields, new List<string>() { "MK_MasterKey" }), 125);
}
catch (ActivityNotFoundException)
{
Toast.MakeText(this, "No Keepass2Android host app found. Please install Keepass2Android 0.9.4 or above!", ToastLength.Long).Show();
}
};
}
protected override void OnResume()
{
base.OnResume();
var prefs = PreferenceManager.GetDefaultSharedPreferences(this);
if (prefs.Contains(KEY_MK_ENTRY_ID))
{
Button buttonCreateMaster = FindViewById<Button>(Resource.Id.btnSetupMaster);
buttonCreateMaster.Visibility = ViewStates.Gone;
Button buttonSelect = FindViewById<Button>(Resource.Id.btnSelectMaster);
buttonSelect.Visibility = ViewStates.Gone;
FindViewById(Resource.Id.btnAddEntry).Visibility = ViewStates.Visible;
}
else
{
FindViewById(Resource.Id.btnAddEntry).Visibility = ViewStates.Gone;
}
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if ((requestCode == 123) && (resultCode == Result.Ok))
{
string masterEntryId = data.GetStringExtra(Strings.ExtraEntryId);
if (!String.IsNullOrEmpty(masterEntryId))
{
var prefs = PreferenceManager.GetDefaultSharedPreferences(this);
prefs.Edit().PutString(KEY_MK_ENTRY_ID, masterEntryId).Commit();
}
}
}
}
}

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MasterKeePlugin</RootNamespace>
<AssemblyName>MasterKeePlugin</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidApplication>true</AndroidApplication>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AccessReceiver.cs" />
<Compile Include="ActionReceiver.cs" />
<Compile Include="AddMasterKeeActivity.cs" />
<Compile Include="LoadingDialog.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="MemUtil.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SetupMasterEntryActivity.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\AboutResources.txt" />
<None Include="Assets\AboutAssets.txt" />
<AndroidResource Include="Resources\layout\Setup.axml" />
<AndroidResource Include="Resources\layout\AddMkEntry.axml">
<SubType>AndroidResource</SubType>
</AndroidResource>
<AndroidResource Include="Resources\drawable-xxhdpi\Thumbs.db" />
<AndroidResource Include="Resources\drawable-xxxhdpi\Thumbs.db" />
<AndroidResource Include="Resources\drawable-hdpi\Thumbs.db" />
<AndroidResource Include="Resources\drawable-mdpi\Thumbs.db" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\Main.axml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values\Strings.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\Icon.png" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Properties\AndroidManifest.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MasterPassword\MasterPassword.csproj">
<Project>{2f7cb5b4-ac2a-4790-b0f3-42e6c9a060d5}</Project>
<Name>MasterPassword</Name>
</ProjectReference>
<ProjectReference Include="..\PluginSdkBinding\PluginSdkBinding.csproj">
<Project>{3da3911e-36de-465e-8f15-f1991b6437e5}</Project>
<Name>PluginSdkBinding</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_menu_view.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-mdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_launcher.png" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,567 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Diagnostics;
using System.IO;
#if !KeePassLibSD
using System.IO.Compression;
#else
using KeePassLibSD;
#endif
namespace KeePassLib.Utility
{
/// <summary>
/// Contains static buffer manipulation and string conversion routines.
/// </summary>
public static class MemUtil
{
private static readonly uint[] m_vSBox = new uint[256] {
0xCD2FACB3, 0xE78A7F5C, 0x6F0803FC, 0xBCF6E230,
0x3A321712, 0x06403DB1, 0xD2F84B95, 0xDF22A6E4,
0x07CE9E5B, 0x31788A0C, 0xF683F6F4, 0xEA061F49,
0xFA5C2ACA, 0x4B9E494E, 0xB0AB25BA, 0x767731FC,
0x261893A7, 0x2B09F2CE, 0x046261E4, 0x41367B4B,
0x18A7F225, 0x8F923C0E, 0x5EF3A325, 0x28D0435E,
0x84C22919, 0xED66873C, 0x8CEDE444, 0x7FC47C24,
0xFCFC6BA3, 0x676F928D, 0xB4147187, 0xD8FB126E,
0x7D798D17, 0xFF82E424, 0x1712FA5B, 0xABB09DD5,
0x8156BA63, 0x84E4D969, 0xC937FB9A, 0x2F1E5BFC,
0x178ECA11, 0x0E71CD5F, 0x52AAC6F4, 0x71EEFC8F,
0x7090D749, 0x21CACA31, 0x92996378, 0x0939A8A8,
0xE9EE1934, 0xD2718616, 0xF2500543, 0xB911873C,
0xD3CB3EEC, 0x2BA0DBEB, 0xB42D0A27, 0xECE67C0F,
0x302925F0, 0x6114F839, 0xD39E6307, 0xE28970D6,
0xEB982F99, 0x941B4CDF, 0xC540E550, 0x8124FC45,
0x98B025C7, 0xE2BF90EA, 0x4F57C976, 0xCF546FE4,
0x59566DC8, 0xE3F4360D, 0xF5F9D231, 0xD6180B22,
0xB54E088A, 0xB5DFE6A6, 0x3637A36F, 0x056E9284,
0xAFF8FBC5, 0x19E01648, 0x8611F043, 0xDAE44337,
0xF61B6A1C, 0x257ACD9E, 0xDD35F507, 0xEF05CAFA,
0x05EB4A83, 0xFC25CA92, 0x0A4728E6, 0x9CF150EF,
0xAEEF67DE, 0xA9472337, 0x57C81EFE, 0x3E5E009F,
0x02CB03BB, 0x2BA85674, 0xF21DC251, 0x78C34A34,
0xABB1F5BF, 0xB95A2FBD, 0x1FB47777, 0x9A96E8AC,
0x5D2D2838, 0x55AAC92A, 0x99EE324E, 0x10F6214B,
0x58ABDFB1, 0x2008794D, 0xBEC880F0, 0xE75E5341,
0x88015C34, 0x352D8FBF, 0x622B7F6C, 0xF5C59EA2,
0x1F759D8E, 0xADE56159, 0xCC7B4C25, 0x5B8BC48C,
0xB6BD15AF, 0x3C5B5110, 0xE74A7C3D, 0xEE613161,
0x156A1C67, 0x72C06817, 0xEA0A6F69, 0x4CECF993,
0xCA9D554C, 0x8E20361F, 0x42D396B9, 0x595DE578,
0x749D7955, 0xFD1BA5FD, 0x81FC160E, 0xDB97E28C,
0x7CF148F7, 0x0B0B3CF5, 0x534DE605, 0x46421066,
0xD4B68DD1, 0x9E479CE6, 0xAE667A9D, 0xBC082082,
0xB06DD6EF, 0x20F0F23F, 0xB99E1551, 0xF47A2E3A,
0x71DA50C6, 0x67B65779, 0x2A8CB376, 0x1EA71EEE,
0x29ABCD50, 0xB6EB0C6B, 0x23C10511, 0x6F3F2144,
0x6AF23012, 0xF696BD9E, 0xB94099D8, 0xAD5A9C81,
0x7A0794FA, 0x7EDF59D6, 0x1E72E574, 0x8561913C,
0x4E4D568F, 0xEECB9928, 0x9C124D2E, 0x0848B82C,
0xF1CA395F, 0x9DAF43DC, 0xF77EC323, 0x394E9B59,
0x7E200946, 0x8B811D68, 0x16DA3305, 0xAB8DE2C3,
0xE6C53B64, 0x98C2D321, 0x88A97D81, 0xA7106419,
0x8E52F7BF, 0x8ED262AF, 0x7CCA974E, 0xF0933241,
0x040DD437, 0xE143B3D4, 0x3019F56F, 0xB741521D,
0xF1745362, 0x4C435F9F, 0xB4214D0D, 0x0B0C348B,
0x5051D189, 0x4C30447E, 0x7393D722, 0x95CEDD0B,
0xDD994E80, 0xC3D22ED9, 0x739CD900, 0x131EB9C4,
0xEF1062B2, 0x4F0DE436, 0x52920073, 0x9A7F3D80,
0x896E7B1B, 0x2C8BBE5A, 0xBD304F8A, 0xA993E22C,
0x134C41A0, 0xFA989E00, 0x39CE9726, 0xFB89FCCF,
0xE8FBAC97, 0xD4063FFC, 0x935A2B5A, 0x44C8EE83,
0xCB2BC7B6, 0x02989E92, 0x75478BEA, 0x144378D0,
0xD853C087, 0x8897A34E, 0xDD23629D, 0xBDE2A2A2,
0x581D8ECC, 0x5DA8AEE8, 0xFF8AAFD0, 0xBA2BCF6E,
0x4BD98DAC, 0xF2EDB9E4, 0xFA2DC868, 0x47E84661,
0xECEB1C7D, 0x41705CA4, 0x5982E4D4, 0xEB5204A1,
0xD196CAFB, 0x6414804D, 0x3ABD4B46, 0x8B494C26,
0xB432D52B, 0x39C5356B, 0x6EC80BF7, 0x71BE5483,
0xCEC4A509, 0xE9411D61, 0x52F341E5, 0xD2E6197B,
0x4F02826C, 0xA9E48838, 0xD1F8F247, 0xE4957FB3,
0x586CCA99, 0x9A8B6A5B, 0x4998FBEA, 0xF762BE4C,
0x90DFE33C, 0x9731511E, 0x88C6A82F, 0xDD65A4D4
};
/// <summary>
/// Convert a hexadecimal string to a byte array. The input string must be
/// even (i.e. its length is a multiple of 2).
/// </summary>
/// <param name="strHex">String containing hexadecimal characters.</param>
/// <returns>Returns a byte array. Returns <c>null</c> if the string parameter
/// was <c>null</c> or is an uneven string (i.e. if its length isn't a
/// multiple of 2).</returns>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="strHex" />
/// is <c>null</c>.</exception>
public static byte[] HexStringToByteArray(string strHex)
{
if(strHex == null) { Debug.Assert(false); throw new ArgumentNullException("strHex"); }
int nStrLen = strHex.Length;
if((nStrLen & 1) != 0) { Debug.Assert(false); return null; }
byte[] pb = new byte[nStrLen / 2];
byte bt;
char ch;
for(int i = 0; i < nStrLen; i += 2)
{
ch = strHex[i];
if((ch >= '0') && (ch <= '9'))
bt = (byte)(ch - '0');
else if((ch >= 'a') && (ch <= 'f'))
bt = (byte)(ch - 'a' + 10);
else if((ch >= 'A') && (ch <= 'F'))
bt = (byte)(ch - 'A' + 10);
else { Debug.Assert(false); bt = 0; }
bt <<= 4;
ch = strHex[i + 1];
if((ch >= '0') && (ch <= '9'))
bt += (byte)(ch - '0');
else if((ch >= 'a') && (ch <= 'f'))
bt += (byte)(ch - 'a' + 10);
else if((ch >= 'A') && (ch <= 'F'))
bt += (byte)(ch - 'A' + 10);
else { Debug.Assert(false); }
pb[i >> 1] = bt;
}
return pb;
}
/// <summary>
/// Convert a byte array to a hexadecimal string.
/// </summary>
/// <param name="pbArray">Input byte array.</param>
/// <returns>Returns the hexadecimal string representing the byte
/// array. Returns <c>null</c>, if the input byte array was <c>null</c>. Returns
/// an empty string, if the input byte array has length 0.</returns>
public static string ByteArrayToHexString(byte[] pbArray)
{
if(pbArray == null) return null;
int nLen = pbArray.Length;
if(nLen == 0) return string.Empty;
StringBuilder sb = new StringBuilder();
byte bt, btHigh, btLow;
for(int i = 0; i < nLen; ++i)
{
bt = pbArray[i];
btHigh = bt; btHigh >>= 4;
btLow = (byte)(bt & 0x0F);
if(btHigh >= 10) sb.Append((char)('A' + btHigh - 10));
else sb.Append((char)('0' + btHigh));
if(btLow >= 10) sb.Append((char)('A' + btLow - 10));
else sb.Append((char)('0' + btLow));
}
return sb.ToString();
}
/// <summary>
/// Set all bytes in a byte array to zero.
/// </summary>
/// <param name="pbArray">Input array. All bytes of this array will be set
/// to zero.</param>
public static void ZeroByteArray(byte[] pbArray)
{
Debug.Assert(pbArray != null); if(pbArray == null) throw new ArgumentNullException("pbArray");
// for(int i = 0; i < pbArray.Length; ++i)
// pbArray[i] = 0;
Array.Clear(pbArray, 0, pbArray.Length);
}
/// <summary>
/// Convert 2 bytes to a 16-bit unsigned integer using Little-Endian
/// encoding.
/// </summary>
/// <param name="pb">Input bytes. Array must contain at least 2 bytes.</param>
/// <returns>16-bit unsigned integer.</returns>
public static ushort BytesToUInt16(byte[] pb)
{
Debug.Assert((pb != null) && (pb.Length == 2));
if(pb == null) throw new ArgumentNullException("pb");
if(pb.Length != 2) throw new ArgumentException();
return (ushort)((ushort)pb[0] | ((ushort)pb[1] << 8));
}
/// <summary>
/// Convert 4 bytes to a 32-bit unsigned integer using Little-Endian
/// encoding.
/// </summary>
/// <param name="pb">Input bytes.</param>
/// <returns>32-bit unsigned integer.</returns>
public static uint BytesToUInt32(byte[] pb)
{
Debug.Assert((pb != null) && (pb.Length == 4));
if(pb == null) throw new ArgumentNullException("pb");
if(pb.Length != 4) throw new ArgumentException("Input array must contain 4 bytes!");
return (uint)pb[0] | ((uint)pb[1] << 8) | ((uint)pb[2] << 16) |
((uint)pb[3] << 24);
}
/// <summary>
/// Convert 8 bytes to a 64-bit unsigned integer using Little-Endian
/// encoding.
/// </summary>
/// <param name="pb">Input bytes.</param>
/// <returns>64-bit unsigned integer.</returns>
public static ulong BytesToUInt64(byte[] pb)
{
Debug.Assert((pb != null) && (pb.Length == 8));
if(pb == null) throw new ArgumentNullException("pb");
if(pb.Length != 8) throw new ArgumentException();
return (ulong)pb[0] | ((ulong)pb[1] << 8) | ((ulong)pb[2] << 16) |
((ulong)pb[3] << 24) | ((ulong)pb[4] << 32) | ((ulong)pb[5] << 40) |
((ulong)pb[6] << 48) | ((ulong)pb[7] << 56);
}
/// <summary>
/// Convert a 16-bit unsigned integer to 2 bytes using Little-Endian
/// encoding.
/// </summary>
/// <param name="uValue">16-bit input word.</param>
/// <returns>Two bytes representing the 16-bit value.</returns>
public static byte[] UInt16ToBytes(ushort uValue)
{
byte[] pb = new byte[2];
unchecked
{
pb[0] = (byte)uValue;
pb[1] = (byte)(uValue >> 8);
}
return pb;
}
/// <summary>
/// Convert a 32-bit unsigned integer to 4 bytes using Little-Endian
/// encoding.
/// </summary>
/// <param name="uValue">32-bit input word.</param>
/// <returns>Four bytes representing the 32-bit value.</returns>
public static byte[] UInt32ToBytes(uint uValue)
{
byte[] pb = new byte[4];
unchecked
{
pb[0] = (byte)uValue;
pb[1] = (byte)(uValue >> 8);
pb[2] = (byte)(uValue >> 16);
pb[3] = (byte)(uValue >> 24);
}
return pb;
}
/// <summary>
/// Convert a 64-bit unsigned integer to 8 bytes using Little-Endian
/// encoding.
/// </summary>
/// <param name="uValue">64-bit input word.</param>
/// <returns>Eight bytes representing the 64-bit value.</returns>
public static byte[] UInt64ToBytes(ulong uValue)
{
byte[] pb = new byte[8];
unchecked
{
pb[0] = (byte)uValue;
pb[1] = (byte)(uValue >> 8);
pb[2] = (byte)(uValue >> 16);
pb[3] = (byte)(uValue >> 24);
pb[4] = (byte)(uValue >> 32);
pb[5] = (byte)(uValue >> 40);
pb[6] = (byte)(uValue >> 48);
pb[7] = (byte)(uValue >> 56);
}
return pb;
}
public static bool ArraysEqual(byte[] x, byte[] y)
{
// Return false if one of them is null (not comparable)!
if((x == null) || (y == null)) { Debug.Assert(false); return false; }
if(x.Length != y.Length) return false;
for(int i = 0; i < x.Length; ++i)
{
if(x[i] != y[i]) return false;
}
return true;
}
public static void XorArray(byte[] pbSource, int nSourceOffset,
byte[] pbBuffer, int nBufferOffset, int nLength)
{
if(pbSource == null) throw new ArgumentNullException("pbSource");
if(nSourceOffset < 0) throw new ArgumentException();
if(pbBuffer == null) throw new ArgumentNullException("pbBuffer");
if(nBufferOffset < 0) throw new ArgumentException();
if(nLength < 0) throw new ArgumentException();
if((nSourceOffset + nLength) > pbSource.Length) throw new ArgumentException();
if((nBufferOffset + nLength) > pbBuffer.Length) throw new ArgumentException();
for(int i = 0; i < nLength; ++i)
pbBuffer[nBufferOffset + i] ^= pbSource[nSourceOffset + i];
}
/// <summary>
/// Fast hash that can be used e.g. for hash tables.
/// The algorithm might change in the future; do not store
/// the hashes for later use.
/// </summary>
public static uint Hash32(byte[] v, int iStart, int iLength)
{
uint u = 0x326F637B;
if(v == null) { Debug.Assert(false); return u; }
if(iStart < 0) { Debug.Assert(false); return u; }
if(iLength < 0) { Debug.Assert(false); return u; }
int m = iStart + iLength;
if(m > v.Length) { Debug.Assert(false); return u; }
for(int i = iStart; i < m; ++i)
{
u ^= m_vSBox[v[i]];
u *= 3;
}
return u;
}
public static void CopyStream(Stream sSource, Stream sTarget)
{
Debug.Assert((sSource != null) && (sTarget != null));
if(sSource == null) throw new ArgumentNullException("sSource");
if(sTarget == null) throw new ArgumentNullException("sTarget");
const int nBufSize = 4096;
byte[] pbBuf = new byte[nBufSize];
while(true)
{
int nRead = sSource.Read(pbBuf, 0, nBufSize);
if(nRead == 0) break;
sTarget.Write(pbBuf, 0, nRead);
}
// Do not close any of the streams
}
public static byte[] Read(Stream s, int nCount)
{
if(s == null) throw new ArgumentNullException("s");
if(nCount < 0) throw new ArgumentOutOfRangeException("nCount");
byte[] pb = new byte[nCount];
int iOffset = 0;
while(nCount > 0)
{
int iRead = s.Read(pb, iOffset, nCount);
if(iRead == 0) break;
iOffset += iRead;
nCount -= iRead;
}
if(iOffset != pb.Length)
{
byte[] pbPart = new byte[iOffset];
Array.Copy(pb, pbPart, iOffset);
return pbPart;
}
return pb;
}
public static void Write(Stream s, byte[] pbData)
{
if(s == null) { Debug.Assert(false); return; }
if(pbData == null) { Debug.Assert(false); return; }
s.Write(pbData, 0, pbData.Length);
}
public static byte[] Compress(byte[] pbData)
{
if(pbData == null) throw new ArgumentNullException("pbData");
if(pbData.Length == 0) return pbData;
MemoryStream msCompressed = new MemoryStream();
GZipStream gz = new GZipStream(msCompressed, CompressionMode.Compress);
MemoryStream msSource = new MemoryStream(pbData, false);
MemUtil.CopyStream(msSource, gz);
gz.Close();
msSource.Close();
byte[] pbCompressed = msCompressed.ToArray();
msCompressed.Close();
return pbCompressed;
}
public static byte[] Decompress(byte[] pbCompressed)
{
if(pbCompressed == null) throw new ArgumentNullException("pbCompressed");
if(pbCompressed.Length == 0) return pbCompressed;
MemoryStream msCompressed = new MemoryStream(pbCompressed, false);
GZipStream gz = new GZipStream(msCompressed, CompressionMode.Decompress);
MemoryStream msData = new MemoryStream();
MemUtil.CopyStream(gz, msData);
gz.Close();
msCompressed.Close();
byte[] pbData = msData.ToArray();
msData.Close();
return pbData;
}
public static int IndexOf<T>(T[] vHaystack, T[] vNeedle)
where T : IEquatable<T>
{
if(vHaystack == null) throw new ArgumentNullException("vHaystack");
if(vNeedle == null) throw new ArgumentNullException("vNeedle");
if(vNeedle.Length == 0) return 0;
for(int i = 0; i <= (vHaystack.Length - vNeedle.Length); ++i)
{
bool bFound = true;
for(int m = 0; m < vNeedle.Length; ++m)
{
if(!vHaystack[i + m].Equals(vNeedle[m]))
{
bFound = false;
break;
}
}
if(bFound) return i;
}
return -1;
}
public static T[] Mid<T>(T[] v, int iOffset, int iLength)
{
if(v == null) throw new ArgumentNullException("v");
if(iOffset < 0) throw new ArgumentOutOfRangeException("iOffset");
if(iLength < 0) throw new ArgumentOutOfRangeException("iLength");
if((iOffset + iLength) > v.Length) throw new ArgumentException();
T[] r = new T[iLength];
Array.Copy(v, iOffset, r, 0, iLength);
return r;
}
public static IEnumerable<T> Union<T>(IEnumerable<T> a, IEnumerable<T> b,
IEqualityComparer<T> cmp)
{
if(a == null) throw new ArgumentNullException("a");
if(b == null) throw new ArgumentNullException("b");
Dictionary<T, bool> d = ((cmp != null) ?
(new Dictionary<T, bool>(cmp)) : (new Dictionary<T, bool>()));
foreach(T ta in a)
{
if(d.ContainsKey(ta)) continue; // Prevent duplicates
d[ta] = true;
yield return ta;
}
foreach(T tb in b)
{
if(d.ContainsKey(tb)) continue; // Prevent duplicates
d[tb] = true;
yield return tb;
}
yield break;
}
public static IEnumerable<T> Intersect<T>(IEnumerable<T> a, IEnumerable<T> b,
IEqualityComparer<T> cmp)
{
if(a == null) throw new ArgumentNullException("a");
if(b == null) throw new ArgumentNullException("b");
Dictionary<T, bool> d = ((cmp != null) ?
(new Dictionary<T, bool>(cmp)) : (new Dictionary<T, bool>()));
foreach(T tb in b) { d[tb] = true; }
foreach(T ta in a)
{
if(d.Remove(ta)) // Prevent duplicates
yield return ta;
}
yield break;
}
public static IEnumerable<T> Except<T>(IEnumerable<T> a, IEnumerable<T> b,
IEqualityComparer<T> cmp)
{
if(a == null) throw new ArgumentNullException("a");
if(b == null) throw new ArgumentNullException("b");
Dictionary<T, bool> d = ((cmp != null) ?
(new Dictionary<T, bool>(cmp)) : (new Dictionary<T, bool>()));
foreach(T tb in b) { d[tb] = true; }
foreach(T ta in a)
{
if(d.ContainsKey(ta)) continue;
d[ta] = true; // Prevent duplicates
yield return ta;
}
yield break;
}
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="keepass2android.plugin.masterkee" android:versionCode="1" android:versionName="1.0" android:installLocation="auto">
<uses-sdk android:minSdkVersion="14" />
<application android:label="MasterKeePlugin" android:icon="@drawable/ic_launcher"></application>
</manifest>

View File

@ -0,0 +1,30 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MasterKeePlugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MasterKeePlugin")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,50 @@
Images, layout descriptions, binary blobs and string dictionaries can be included
in your application as resource files. Various Android APIs are designed to
operate on the resource IDs instead of dealing with images, strings or binary blobs
directly.
For example, a sample Android app that contains a user interface layout (main.xml),
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
would keep its resources in the "Resources" directory of the application:
Resources/
drawable-hdpi/
icon.png
drawable-ldpi/
icon.png
drawable-mdpi/
icon.png
layout/
main.xml
values/
strings.xml
In order to get the build system to recognize Android resources, set the build action to
"AndroidResource". The native Android APIs do not operate directly with filenames, but
instead operate on resource IDs. When you compile an Android application that uses resources,
the build system will package the resources for distribution and generate a class called
"Resource" that contains the tokens for each one of the resources included. For example,
for the above Resources layout, this is what the Resource class would expose:
public class Resource {
public class drawable {
public const int icon = 0x123;
}
public class layout {
public const int main = 0x456;
}
public class strings {
public const int first_string = 0xabc;
public const int second_string = 0xbcd;
}
}
You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main
to reference the layout/main.xml file, or Resource.strings.first_string to reference the first
string in the dictionary file values/strings.xml.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</LinearLayout>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="12dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/ExplainMkMasterEntry" />
<Button
android:id="@+id/btnSetupMaster"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/SetUpMkMasterEntry" />
<Button
android:id="@+id/btnSelectMaster"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/SelectMkMasterEntry" />
<Button
android:id="@+id/btnAddEntry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/AddMkEntry" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="Your name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView1" />
<EditText
android:inputType="textPersonName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/etUser" />
<TextView
android:text="Your MasterKee master password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView2" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/toggle_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/ic_menu_view" />
<EditText
android:id="@+id/entry_password"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@id/toggle_password"
android:layout_toLeftOf="@id/toggle_password"
android:hint="@string/hint_pass"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="monospace" />
<!-- Confirm Password -->
<EditText
android:id="@+id/entry_confpassword"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/entry_password"
android:hint="@string/hint_conf_pass"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="monospace" />
</RelativeLayout>
<Button
android:text="@string/button_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button_ok" />
</LinearLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ExplainMkMasterEntry">Your Master Password used for generating MasterKee passwords must be stored inside a special entry in your Keepass2Android database. Please create such an entry and then select it in your database (The current KP2A plugin interface requires this as a 2-step process). After creating and selecting the entry, you will be able to create new entries for sites.</string>
<string name="SelectMkMasterEntry">Select existing master entry</string>
<string name="SetUpMkMasterEntry">Create new master entry</string>
<string name="ApplicationName">MasterKeePlugin</string>
<string name="hint_conf_pass">confirm password</string>
<string name="hint_pass">password</string>
<string name="button_ok">OK</string>
<string name="error_pass_match">Passwords do not match.</string>
<string name="deriving_key">Calculating derived key... This might take a few seconds.</string>
<string name="AddMkEntry">Add MasterKee entry</string>
<string name="kp2aplugin_title">MasterKee Plugin</string>
<string name="kp2aplugin_shortdesc">Plugin to generate passwords compatible with the MasterPassword approach by Maarten Billemont giving you the ability to restore passwords even if your database is lost.</string>
<string name="kp2aplugin_author">Philipp Crocoll</string>
</resources>

View File

@ -0,0 +1,121 @@
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.Text;
using Android.Views;
using Android.Widget;
using KeePassLib.Utility;
using Keepass2android.Pluginsdk;
using keepass2android.Utils;
using Object = Java.Lang.Object;
namespace MasterKeePlugin
{
[Activity(Label = "Setup Master Entry")]
public class SetupMasterEntryActivity : Activity
{
private bool _showPassword;
private bool TryGetPassword(out string pass)
{
TextView passView = (TextView)FindViewById(Resource.Id.entry_password);
pass = passView.Text;
if (_showPassword)
return true;
TextView passConfView = (TextView)FindViewById(Resource.Id.entry_confpassword);
String confpass = passConfView.Text;
// Verify that passwords match
if (!pass.Equals(confpass))
{
// Passwords do not match
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
return false;
}
return true;
}
private void MakePasswordMaskedOrVisible()
{
TextView password = (TextView)FindViewById(Resource.Id.entry_password);
TextView confpassword = (TextView)FindViewById(Resource.Id.entry_confpassword);
if (_showPassword)
{
password.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
confpassword.Visibility = ViewStates.Gone;
}
else
{
password.InputType = InputTypes.ClassText | InputTypes.TextVariationPassword;
confpassword.Visibility = ViewStates.Visible;
}
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Setup);
ImageButton btnTogglePassword = (ImageButton)FindViewById(Resource.Id.toggle_password);
btnTogglePassword.Click += (sender, e) =>
{
_showPassword = !_showPassword;
MakePasswordMaskedOrVisible();
};
FindViewById(Resource.Id.button_ok).Click += delegate(object sender, EventArgs args)
{
string password;
if (!TryGetPassword(out password))
return;
string username = FindViewById<EditText>(Resource.Id.etUser).Text;
new LoadingDialog<object, object, object>(this, GetString(Resource.String.deriving_key), false,
delegate
{
return
MemUtil.ByteArrayToHexString(
MasterPassword.MpAlgorithm.GetKeyForPassword(username, password));
},
delegate(Object res)
{
string derivedKey = (string) res;
AddMasterKeeEntry(derivedKey, username);
}
).Execute();
};
}
private void AddMasterKeeEntry(string derivedKey, string username)
{
Dictionary<string, string> fields = new Dictionary<string, string>();
fields[KeepassDefs.TitleField] = "MasterKee master entry";
fields[KeepassDefs.UserNameField] = username;
fields[KeepassDefs.UrlField] = "androidapp://" + PackageName;
fields[KeepassDefs.PasswordField] = derivedKey;
try
{
StartActivityForResult(Kp2aControl.GetAddEntryIntent(fields, new List<string>()), 123);
//TODO: get created entry id and store
Finish();
}
catch (ActivityNotFoundException)
{
Toast.MakeText(this, "No Keepass2Android host app found. Please install Keepass2Android 0.9.4 or above!", ToastLength.Long).Show();
}
}
}
}

View File

@ -16,34 +16,18 @@ namespace MasterPassword
private const int MP_p = 2; private const int MP_p = 2;
private const int MP_dkLen = 64; private const int MP_dkLen = 64;
static sbyte[] ToSignedByteArray(byte[] unsigned)
{
sbyte[] signed = new sbyte[unsigned.Length];
Buffer.BlockCopy(unsigned, 0, signed, 0, unsigned.Length);
return signed;
}
static byte[] ToUnsignedByteArray(sbyte[] signed)
{
byte[] unsigned = new byte[signed.Length];
Buffer.BlockCopy(signed, 0, unsigned, 0, signed.Length);
return unsigned;
}
public static byte[] GetKeyForPassword(string user, string password) public static byte[] GetKeyForPassword(string user, string password)
{ {
var salt = Combine(Encoding.UTF8.GetBytes("com.lyndir.masterpassword"), var salt = Combine(Encoding.UTF8.GetBytes("com.lyndir.masterpassword"),
IntAsByteArray(user.Length), IntAsByteArray(user.Length),
Encoding.UTF8.GetBytes(user)); Encoding.UTF8.GetBytes(user));
var ssalt = ToSignedByteArray(salt);
var spwd = ToSignedByteArray(Encoding.UTF8.GetBytes(password));
var key = SCrypt.ComputeDerivedKey(Encoding.UTF8.GetBytes(password), var key = SCrypt.ComputeDerivedKey(Encoding.UTF8.GetBytes(password),
salt, salt,
MP_N, MP_N,
MP_r, MP_r,
MP_p,null, MP_dkLen); MP_p, null, MP_dkLen);
sbyte[] signed = ToSignedByteArray(key); return key;
return signed;
} }
@ -66,7 +50,7 @@ namespace MasterPassword
return intBytes; return intBytes;
} }
public static String GenerateContent(string elementType, string siteName, sbyte[] key, int counter, Func<byte[], byte[], byte[]> hmacFunc) public static String GenerateContent(string elementType, string siteName, byte[] key, int counter, Func<byte[], byte[], byte[]> hmacFunc)
{ {
if (counter == 0) if (counter == 0)
{ {
@ -77,12 +61,12 @@ namespace MasterPassword
byte[] nameLengthBytes = IntAsByteArray(siteName.Length); byte[] nameLengthBytes = IntAsByteArray(siteName.Length);
byte[] counterBytes =IntAsByteArray(counter); byte[] counterBytes = IntAsByteArray(counter);
sbyte[] seed = ToSignedByteArray(hmacFunc( ToUnsignedByteArray(key), Combine( Encoding.UTF8.GetBytes("com.lyndir.masterpassword"), // byte[] seed = hmacFunc(key, Combine(Encoding.UTF8.GetBytes("com.lyndir.masterpassword"), //
nameLengthBytes, // nameLengthBytes, //
Encoding.UTF8.GetBytes(siteName), // Encoding.UTF8.GetBytes(siteName), //
counterBytes ) ) ); counterBytes));
//logger.trc( "seed is: %s", CryptUtils.encodeBase64( seed ) ); //logger.trc( "seed is: %s", CryptUtils.encodeBase64( seed ) );
//Preconditions.checkState( seed.length > 0 ); //Preconditions.checkState( seed.length > 0 );
@ -91,13 +75,15 @@ namespace MasterPassword
//MPTemplate template = null; //MPTemplate template = null;
var generatedEntities = PlistData["MPElementGeneratedEntity"];
var templatesLongPwd = PlistData["MPElementGeneratedEntity"]["Long Password"]; //TODO catch wrong elementType!
string template = templatesLongPwd[templateIndex%templatesLongPwd.Count]; var templatesLongPwd = generatedEntities[elementType];
string template = templatesLongPwd[templateIndex % templatesLongPwd.Count];
//logger.trc( "type: %s, template: %s", type, template ); //logger.trc( "type: %s, template: %s", type, template );
StringBuilder password = new StringBuilder( template.Length ); StringBuilder password = new StringBuilder(template.Length);
for (int i = 0; i < template.Length; ++i) { for (int i = 0; i < template.Length; ++i)
{
int characterIndex = seed[i + 1] & 0xFF; // Mask the integer's sign. int characterIndex = seed[i + 1] & 0xFF; // Mask the integer's sign.
char c = template[i]; char c = template[i];

View File

@ -100,6 +100,9 @@
<SubType>AndroidResource</SubType> <SubType>AndroidResource</SubType>
</AndroidResource> </AndroidResource>
<AndroidResource Include="Resources\Layout\sftp_credentials.axml" /> <AndroidResource Include="Resources\Layout\sftp_credentials.axml" />
<AndroidResource Include="Resources\Layout\Setup.axml">
<SubType>AndroidResource</SubType>
</AndroidResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidResource Include="Resources\Layout\Main.axml" /> <AndroidResource Include="Resources\Layout\Main.axml" />

View File

@ -26,7 +26,6 @@
<string name="show_kill_app_summary">Show a button in password screen to kill the application process (for paranoid users)</string> <string name="show_kill_app_summary">Show a button in password screen to kill the application process (for paranoid users)</string>
<string name="application">Application</string> <string name="application">Application</string>
<string name="application_settings">Application settings</string> <string name="application_settings">Application settings</string>
<string name="security_prefs">Security</string> <string name="security_prefs">Security</string>
<string name="display_prefs">Display</string> <string name="display_prefs">Display</string>
<string name="password_access_prefs">Password entry access</string> <string name="password_access_prefs">Password entry access</string>
@ -164,7 +163,6 @@
<string name="saving_database">Saving database…</string> <string name="saving_database">Saving database…</string>
<string name="exporting_database">Exporting database…</string> <string name="exporting_database">Exporting database…</string>
<string name="export_database_successful">Database exported successfully!</string> <string name="export_database_successful">Database exported successfully!</string>
<string name="space">Space</string> <string name="space">Space</string>
<string name="search_label">Search</string> <string name="search_label">Search</string>
<string name="show_password">Show password</string> <string name="show_password">Show password</string>
@ -199,7 +197,6 @@
<string name="ShowUsernameInList_summary">Display usernames below entry titles. Useful for multiple accounts or TANs.</string> <string name="ShowUsernameInList_summary">Display usernames below entry titles. Useful for multiple accounts or TANs.</string>
<string name="RememberRecentFiles_title">Remember databases</string> <string name="RememberRecentFiles_title">Remember databases</string>
<string name="RememberRecentFiles_summary">Remember recently opened databases and show them in the Open database screen.</string> <string name="RememberRecentFiles_summary">Remember recently opened databases and show them in the Open database screen.</string>
<string name="kp2a_findUrl">Keepass2Android: Find password</string> <string name="kp2a_findUrl">Keepass2Android: Find password</string>
<string name="excludeExpiredEntries">Exclude expired entries</string> <string name="excludeExpiredEntries">Exclude expired entries</string>
<string name="search_options">Options</string> <string name="search_options">Options</string>
@ -229,13 +226,10 @@
<string name="SaveAttachmentDialog_text">Please select where to save the attachment.</string> <string name="SaveAttachmentDialog_text">Please select where to save the attachment.</string>
<string name="SaveAttachmentDialog_save">Save to SD card</string> <string name="SaveAttachmentDialog_save">Save to SD card</string>
<string name="SaveAttachmentDialog_open">Save to cache and open</string> <string name="SaveAttachmentDialog_open">Save to cache and open</string>
<string name="SaveAttachment_doneMessage">Saved file to %1$s.</string> <string name="SaveAttachment_doneMessage">Saved file to %1$s.</string>
<string name="SaveAttachment_Failed">Could not save attachment to %1$s.</string> <string name="SaveAttachment_Failed">Could not save attachment to %1$s.</string>
<string name="AddUrlToEntryDialog_title">Remember search text?</string> <string name="AddUrlToEntryDialog_title">Remember search text?</string>
<string name="AddUrlToEntryDialog_text">Would you like to store the search text "%1$s" in the selected entry in order to find it automatically next time?</string> <string name="AddUrlToEntryDialog_text">Would you like to store the search text "%1$s" in the selected entry in order to find it automatically next time?</string>
<string name="error_invalid_expiry_date">Invalid date/time format for expiry date!</string> <string name="error_invalid_expiry_date">Invalid date/time format for expiry date!</string>
<string name="error_string_key">A field name is required for each string.</string> <string name="error_string_key">A field name is required for each string.</string>
<string name="field_name">Field Name</string> <string name="field_name">Field Name</string>
@ -253,32 +247,24 @@
<string name="LockWhenScreenOff_summary">Lock the database when screen is switched off.</string> <string name="LockWhenScreenOff_summary">Lock the database when screen is switched off.</string>
<string name="UseOfflineCache_title">Database caching</string> <string name="UseOfflineCache_title">Database caching</string>
<string name="UseOfflineCache_summary">Keep a copy of remote database files in the application cache directory. This allows to use remote databases even when offline.</string> <string name="UseOfflineCache_summary">Keep a copy of remote database files in the application cache directory. This allows to use remote databases even when offline.</string>
<string name="AcceptAllServerCertificates_title">SSL certificates</string> <string name="AcceptAllServerCertificates_title">SSL certificates</string>
<string name="AcceptAllServerCertificates_summary">Define the behavior when certificate validation fails. Note: you can install certificates on your device if validation fails!</string> <string name="AcceptAllServerCertificates_summary">Define the behavior when certificate validation fails. Note: you can install certificates on your device if validation fails!</string>
<string name="ClearOfflineCache_title">Clear cache?</string> <string name="ClearOfflineCache_title">Clear cache?</string>
<string name="ClearOfflineCache_question">This will delete all cached database files. Any changes you made while being offline which have not yet been synchronized will be lost! Continue?</string> <string name="ClearOfflineCache_question">This will delete all cached database files. Any changes you made while being offline which have not yet been synchronized will be lost! Continue?</string>
<string name="CheckForFileChangesOnSave_title">Check for modifications</string> <string name="CheckForFileChangesOnSave_title">Check for modifications</string>
<string name="CheckForFileChangesOnSave_summary">Check whether the file was modified externally before saving changes.</string> <string name="CheckForFileChangesOnSave_summary">Check whether the file was modified externally before saving changes.</string>
<string name="ShowCopyToClipboardNotification_title">Clipboard notifications</string> <string name="ShowCopyToClipboardNotification_title">Clipboard notifications</string>
<string name="ShowCopyToClipboardNotification_summary">Make username and password accessible through the notification bar and clipboard. Beware of password sniffers!</string> <string name="ShowCopyToClipboardNotification_summary">Make username and password accessible through the notification bar and clipboard. Beware of password sniffers!</string>
<string name="ShowKp2aKeyboardNotification_title">KP2A keyboard notification</string> <string name="ShowKp2aKeyboardNotification_title">KP2A keyboard notification</string>
<string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard (recommended).</string> <string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard (recommended).</string>
<string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string> <string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string>
<string name="OpenKp2aKeyboardAutomatically_summary">Open keyboard selection dialog when entry is available through KP2A keyboard after search from the browser.</string> <string name="OpenKp2aKeyboardAutomatically_summary">Open keyboard selection dialog when entry is available through KP2A keyboard after search from the browser.</string>
<string name="kp2a_switch_rooted">Auto-switch on rooted devices</string> <string name="kp2a_switch_rooted">Auto-switch on rooted devices</string>
<string name="kp2a_switch_rooted_summary">On rooted devices, it is possible to automatically switch to the Keepass2Android keyboard (after search for an entry or by clicking the KP2A keyboard notification) and to switch back to the previous keyboard without showing the Input method picker. This also requires to install the Secure Settings app. See the KP2A documentation for more information!</string> <string name="kp2a_switch_rooted_summary">On rooted devices, it is possible to automatically switch to the Keepass2Android keyboard (after search for an entry or by clicking the KP2A keyboard notification) and to switch back to the previous keyboard without showing the Input method picker. This also requires to install the Secure Settings app. See the KP2A documentation for more information!</string>
<string name="ShowUnlockedNotification_title">Notification icon while unlocked</string> <string name="ShowUnlockedNotification_title">Notification icon while unlocked</string>
<string name="ShowUnlockedNotification_summary">Show a notification icon while the database is unlocked.</string> <string name="ShowUnlockedNotification_summary">Show a notification icon while the database is unlocked.</string>
<string name="PreloadDatabaseEnabled_title">Pre-load database file</string> <string name="PreloadDatabaseEnabled_title">Pre-load database file</string>
<string name="PreloadDatabaseEnabled_summary">Start background loading or downloading of the database file during password entry.</string> <string name="PreloadDatabaseEnabled_summary">Start background loading or downloading of the database file during password entry.</string>
<string name="AskOverwriteBinary">Do you want to overwrite the existing binary with the same name?</string> <string name="AskOverwriteBinary">Do you want to overwrite the existing binary with the same name?</string>
<string name="AskOverwriteBinary_title">Overwrite existing binary?</string> <string name="AskOverwriteBinary_title">Overwrite existing binary?</string>
<string name="AskOverwriteBinary_yes">Overwrite</string> <string name="AskOverwriteBinary_yes">Overwrite</string>
@ -310,7 +296,6 @@
<string name="SynchronizingDatabase">Merging changes…</string> <string name="SynchronizingDatabase">Merging changes…</string>
<string name="YesSynchronize">Yes, merge</string> <string name="YesSynchronize">Yes, merge</string>
<string name="NoOverwrite">No, overwrite</string> <string name="NoOverwrite">No, overwrite</string>
<string name="SynchronizingCachedDatabase">Synchronizing cached database…</string> <string name="SynchronizingCachedDatabase">Synchronizing cached database…</string>
<string name="DownloadingRemoteFile">Downloading remote file…</string> <string name="DownloadingRemoteFile">Downloading remote file…</string>
<string name="UploadingFile">Uploading file…</string> <string name="UploadingFile">Uploading file…</string>
@ -318,7 +303,6 @@
<string name="FilesInSync">Files are in sync.</string> <string name="FilesInSync">Files are in sync.</string>
<string name="SynchronizedDatabaseSuccessfully">Database synchronized successfully!</string> <string name="SynchronizedDatabaseSuccessfully">Database synchronized successfully!</string>
<string name="CheckingDatabaseForChanges">Checking database for changes…</string> <string name="CheckingDatabaseForChanges">Checking database for changes…</string>
<string name="CouldNotSaveToRemote">Could not save to remote: %1$s. Save again or use the Synchronize menu when remote connection is available again.</string> <string name="CouldNotSaveToRemote">Could not save to remote: %1$s. Save again or use the Synchronize menu when remote connection is available again.</string>
<string name="CouldNotLoadFromRemote">Could not open from remote: %1$s. Loaded file from local cache. You can still make changes in the database and synchronize them later.</string> <string name="CouldNotLoadFromRemote">Could not open from remote: %1$s. Loaded file from local cache. You can still make changes in the database and synchronize them later.</string>
<string name="UpdatedRemoteFileOnLoad">Updated remote file.</string> <string name="UpdatedRemoteFileOnLoad">Updated remote file.</string>
@ -326,35 +310,24 @@
<string name="LoadedFromRemoteInSync">Remote file and cache are synchronized.</string> <string name="LoadedFromRemoteInSync">Remote file and cache are synchronized.</string>
<string name="UpdatedCachedFileOnLoad">Updated local cache copy of %1$s.</string> <string name="UpdatedCachedFileOnLoad">Updated local cache copy of %1$s.</string>
<string name="RemoteDatabaseUnchanged">No changes detected.</string> <string name="RemoteDatabaseUnchanged">No changes detected.</string>
<string name="ResolvedCacheConflictByUsingRemoteOtpAux">Updated cached OTP auxiliary file: Remote counter was higher.</string> <string name="ResolvedCacheConflictByUsingRemoteOtpAux">Updated cached OTP auxiliary file: Remote counter was higher.</string>
<string name="ResolvedCacheConflictByUsingLocalOtpAux">Updated remote OTP auxiliary file: Local counter was higher.</string> <string name="ResolvedCacheConflictByUsingLocalOtpAux">Updated remote OTP auxiliary file: Local counter was higher.</string>
<string name="SynchronizingOtpAuxFile">Synchronizing OTP auxiliary file…</string> <string name="SynchronizingOtpAuxFile">Synchronizing OTP auxiliary file…</string>
<string name="database_file">database file</string> <string name="database_file">database file</string>
<string name="otp_aux_file">OTP auxiliary file</string> <string name="otp_aux_file">OTP auxiliary file</string>
<string name="ErrorOcurred">An error occured:</string> <string name="ErrorOcurred">An error occured:</string>
<string name="synchronize_database_menu">Synchronize database…</string> <string name="synchronize_database_menu">Synchronize database…</string>
<string name="CannotMoveGroupHere">Cannot move group to this group.</string> <string name="CannotMoveGroupHere">Cannot move group to this group.</string>
<string name="donate_question">Today, it\'s Oktoberfest! If you like Keepass2Android: wouldn\'t today be a good day to buy me a beer?</string> <string name="donate_question">Today, it\'s Oktoberfest! If you like Keepass2Android: wouldn\'t today be a good day to buy me a beer?</string>
<string name="donate_bday_question">May 10th? It\'s my birthday! If you like this app, why not send me some birthday greetings along with a little birthday gift? This would really make me happy! :-)</string> <string name="donate_bday_question">May 10th? It\'s my birthday! If you like this app, why not send me some birthday greetings along with a little birthday gift? This would really make me happy! :-)</string>
<string name="donate_missedbday_question">Oh, you missed my birthday on May 10th! If you like this app, why not send me some birthday greetings and a little birthday gift? It is not yet too late to make me happy! :-)</string> <string name="donate_missedbday_question">Oh, you missed my birthday on May 10th! If you like this app, why not send me some birthday greetings and a little birthday gift? It is not yet too late to make me happy! :-)</string>
<string name="ok_donate">Tell me more!</string> <string name="ok_donate">Tell me more!</string>
<string name="no_thanks">No, I don\'t like it that much</string> <string name="no_thanks">No, I don\'t like it that much</string>
<string name="hint_sftp_host">host (ex: 192.168.0.1)</string> <string name="hint_sftp_host">host (ex: 192.168.0.1)</string>
<string name="hint_sftp_port">port</string> <string name="hint_sftp_port">port</string>
<string name="initial_directory">Initial directory (optional):</string> <string name="initial_directory">Initial directory (optional):</string>
<string name="enter_sftp_login_title">Enter SFTP login data:</string> <string name="enter_sftp_login_title">Enter SFTP login data:</string>
<string name="select_storage_type">Select the storage type:</string> <string name="select_storage_type">Select the storage type:</string>
<string name="filestoragename_file">Local file</string> <string name="filestoragename_file">Local file</string>
<string name="filestoragename_androidget">Get from third-party app</string> <string name="filestoragename_androidget">Get from third-party app</string>
<string name="filestoragename_androidsend">Send to third-party app</string> <string name="filestoragename_androidsend">Send to third-party app</string>
@ -367,25 +340,19 @@
<string name="filestoragename_gdrive">Google Drive</string> <string name="filestoragename_gdrive">Google Drive</string>
<string name="filestoragename_skydrive">OneDrive</string> <string name="filestoragename_skydrive">OneDrive</string>
<string name="filestoragename_sftp">SFTP (SSH File Transfer)</string> <string name="filestoragename_sftp">SFTP (SSH File Transfer)</string>
<string name="filestorage_setup_title">File access initialization</string> <string name="filestorage_setup_title">File access initialization</string>
<string name="database_location">Database location</string> <string name="database_location">Database location</string>
<string name="help_database_location">You can store your database locally on your Android device or in the cloud (non-Offline version only). Keepass2Android makes the database available even if you are offline. As the database is securely encrypted with AES 256 bit encryption, nobody will be able to access your passwords except you. We recommend to select Dropbox: It\'s accessible on all your devices and even provides backups of previous file versions.</string> <string name="help_database_location">You can store your database locally on your Android device or in the cloud (non-Offline version only). Keepass2Android makes the database available even if you are offline. As the database is securely encrypted with AES 256 bit encryption, nobody will be able to access your passwords except you. We recommend to select Dropbox: It\'s accessible on all your devices and even provides backups of previous file versions.</string>
<string name="hint_database_location">Select where you want to store the database:</string> <string name="hint_database_location">Select where you want to store the database:</string>
<string name="button_change_location">Change location</string> <string name="button_change_location">Change location</string>
<string name="master_password">Master password</string> <string name="master_password">Master password</string>
<string name="help_master_password">Your database is encrypted with the password you enter here. Choose a strong password in order to keep the database safe! Tip: Make up a sentence or two and use the first letters of the words as password. Include punctuation marks.</string> <string name="help_master_password">Your database is encrypted with the password you enter here. Choose a strong password in order to keep the database safe! Tip: Make up a sentence or two and use the first letters of the words as password. Include punctuation marks.</string>
<string name="hint_master_password">Select a master password to protect your database:</string> <string name="hint_master_password">Select a master password to protect your database:</string>
<string name="key_file">Key file</string> <string name="key_file">Key file</string>
<string name="help_key_file">A key file is basically a password stored in a file. Key files are typically stronger than master passwords, because the key can be a lot more complicated; however it\'s also harder to keep them secret. If you store your database in the cloud, don\'t store the key file there as well! This would make it completely useless! Important: Do not change the contents of the key file after creating the database!</string> <string name="help_key_file">A key file is basically a password stored in a file. Key files are typically stronger than master passwords, because the key can be a lot more complicated; however it\'s also harder to keep them secret. If you store your database in the cloud, don\'t store the key file there as well! This would make it completely useless! Important: Do not change the contents of the key file after creating the database!</string>
<string name="hint_key_file">Choose if you want to use a key file in addition to your master password:</string> <string name="hint_key_file">Choose if you want to use a key file in addition to your master password:</string>
<string name="use_key_file">Use key file</string> <string name="use_key_file">Use key file</string>
<string name="error_adding_keyfile">Error while adding the keyfile!</string> <string name="error_adding_keyfile">Error while adding the keyfile!</string>
<string name="init_otp">Load OTP auxiliary file…</string> <string name="init_otp">Load OTP auxiliary file…</string>
<string name="otp_explanation">Enter the next One-time-passwords (OTPs). Swipe your Yubikey NEO at the back of your device to enter via NFC.</string> <string name="otp_explanation">Enter the next One-time-passwords (OTPs). Swipe your Yubikey NEO at the back of your device to enter via NFC.</string>
<string name="otp_hint">OTP %1$d</string> <string name="otp_hint">OTP %1$d</string>
@ -400,12 +367,9 @@
<string name="OtpKeyError">Failed to create OTP key! Make sure you have entered the correct OTPs.</string> <string name="OtpKeyError">Failed to create OTP key! Make sure you have entered the correct OTPs.</string>
<string name="ErrorUpdatingOtpAuxFile">Error updating OTP auxiliary file!</string> <string name="ErrorUpdatingOtpAuxFile">Error updating OTP auxiliary file!</string>
<string name="SavingOtpAuxFile">Saving auxiliary OTP file…</string> <string name="SavingOtpAuxFile">Saving auxiliary OTP file…</string>
<string name="loading">Loading…</string> <string name="loading">Loading…</string>
<string name="enable_plugin_title">Enable plug-in?</string> <string name="enable_plugin_title">Enable plug-in?</string>
<string name="enable_plugin_question">Keepass2Android detected a plug-in with name: %1$s from package name: %2$s. Do you want to enable this plug-in? It will have access to the data stored in your Keepass databases.</string> <string name="enable_plugin_question">Keepass2Android detected a plug-in with name: %1$s from package name: %2$s. Do you want to enable this plug-in? It will have access to the data stored in your Keepass databases.</string>
<string name="plugins">Plug-ins</string> <string name="plugins">Plug-ins</string>
<string name="plugin_packagename">Package name:</string> <string name="plugin_packagename">Package name:</string>
<string name="plugin_description">Description (not verified):</string> <string name="plugin_description">Description (not verified):</string>
@ -413,22 +377,16 @@
<string name="plugin_enabled">enabled</string> <string name="plugin_enabled">enabled</string>
<string name="plugin_disabled">disabled</string> <string name="plugin_disabled">disabled</string>
<string name="plugins_text">Click plug-in to enable/disable</string> <string name="plugins_text">Click plug-in to enable/disable</string>
<string name="get_regular_version">Get more storage types</string> <string name="get_regular_version">Get more storage types</string>
<string name="CertificateWarning">Warning: Server certificate validation failed: %1$s. Install appropriate root certificate on your device or see settings!</string> <string name="CertificateWarning">Warning: Server certificate validation failed: %1$s. Install appropriate root certificate on your device or see settings!</string>
<string name="CertificateFailure">Error: Server certificate validation failed! Install appropriate root certificate on your device or see settings!</string> <string name="CertificateFailure">Error: Server certificate validation failed! Install appropriate root certificate on your device or see settings!</string>
<string name="export_fileformats_title">Select file format</string> <string name="export_fileformats_title">Select file format</string>
<string name="ChangeLog_title">Change log</string> <string name="ChangeLog_title">Change log</string>
<string name="ChangeLog_0_9_3_r5"> <string name="ChangeLog_0_9_3_r5">
<b>Version 0.9.3 r5</b>\n <b>Version 0.9.3 r5</b>\n
* Incorporated fixes from Xamarin: Keepass2Android now compatible with ART on Android 4.4.2. Finally!\n * Incorporated fixes from Xamarin: Keepass2Android now compatible with ART on Android 4.4.2. Finally!\n
* Bug fixes: bugs in synchronization (refresh display, correct check for changes on http), bugs on Android 2.x devices, bugs in Google Drive and OneDrive storage implementations, clear clipboard on close database, bug opening attachments, display problems with keyboard\n * Bug fixes: bugs in synchronization (refresh display, correct check for changes on http), bugs on Android 2.x devices, bugs in Google Drive and OneDrive storage implementations, clear clipboard on close database, bug opening attachments, display problems with keyboard\n
</string> </string>
<string name="ChangeLog_0_9_3"> <string name="ChangeLog_0_9_3">
<b>Version 0.9.3</b>\n <b>Version 0.9.3</b>\n
* New keyboard with many improvements. See settings to customize.\n * New keyboard with many improvements. See settings to customize.\n
@ -437,7 +395,6 @@
* Added workaround for bug in ART (Android 4.4.2)\n * Added workaround for bug in ART (Android 4.4.2)\n
* Bug fixes\n * Bug fixes\n
</string> </string>
<string name="ChangeLog_0_9_2"> <string name="ChangeLog_0_9_2">
<b>Version 0.9.2</b>\n <b>Version 0.9.2</b>\n
* Added OTP support (compatible with OtpKeyProv plugin)\n * Added OTP support (compatible with OtpKeyProv plugin)\n
@ -448,15 +405,12 @@
* Improved SSL certificate validation\n * Improved SSL certificate validation\n
* Bug fixes\n * Bug fixes\n
</string> </string>
<string name="ChangeLog_0_9_1"> <string name="ChangeLog_0_9_1">
<b>Version 0.9.1</b>\n <b>Version 0.9.1</b>\n
* Integrated SkyDrive support (Keepass2Android regular edition only)\n * Integrated SkyDrive support (Keepass2Android regular edition only)\n
* Fixed problems with Google Drive integration\n * Fixed problems with Google Drive integration\n
* Added NTLM support * Added NTLM support
</string> </string>
<string name="ChangeLog_0_9"> <string name="ChangeLog_0_9">
<b>Version 0.9</b>\n <b>Version 0.9</b>\n
* Integrated Dropbox and Google Drive support (read/write databases; Keepass2Android regular edition only)\n * Integrated Dropbox and Google Drive support (read/write databases; Keepass2Android regular edition only)\n
@ -465,8 +419,6 @@
* Included custom font DejaVu Sans Mono for displaying passwords\n * Included custom font DejaVu Sans Mono for displaying passwords\n
* Bug fixes * Bug fixes
</string> </string>
<string name="ChangeLog_0_8_6"> <string name="ChangeLog_0_8_6">
<b>Version 0.8.6</b>\n <b>Version 0.8.6</b>\n
* Support for Twofish cipher\n * Support for Twofish cipher\n
@ -475,7 +427,6 @@
* QuickUnlock icon can be made transparent (see settings)\n * QuickUnlock icon can be made transparent (see settings)\n
* Bug fixes * Bug fixes
</string> </string>
<string name="ChangeLog_0_8_5"> <string name="ChangeLog_0_8_5">
<b>Version 0.8.5</b>\n <b>Version 0.8.5</b>\n
* Remote files are stored in the local application cache to allow offline usage (including editing and later synchronization). See settings. \n * Remote files are stored in the local application cache to allow offline usage (including editing and later synchronization). See settings. \n
@ -496,7 +447,8 @@
Thanks to Alex Vallat for his code contributions!\n Thanks to Alex Vallat for his code contributions!\n
Thanks to Niki Hüttner (www.close-cut.de) for the new logo!\n Thanks to Niki Hüttner (www.close-cut.de) for the new logo!\n
</string> </string>
<string name="ChangeLog_0_8_3"><b>Version 0.8.3</b>\n <string name="ChangeLog_0_8_3">
<b>Version 0.8.3</b>\n
* Username/TAN index displayed in entry list (see settings)\n * Username/TAN index displayed in entry list (see settings)\n
* Entries can be created if search from browser doesn\'t return results\n * Entries can be created if search from browser doesn\'t return results\n
* KP2A keyboard provides possibility to search for credentials for current app\n * KP2A keyboard provides possibility to search for credentials for current app\n
@ -505,15 +457,18 @@
* Placeholders in entry fields are replaced before copying (most placeholders supported)\n * Placeholders in entry fields are replaced before copying (most placeholders supported)\n
* minor bug fixes * minor bug fixes
</string> </string>
<string name="ChangeLog_0_8_2"><b>Version 0.8.2</b>\n <string name="ChangeLog_0_8_2">
<b>Version 0.8.2</b>\n
* Support for Digest Authentication in WebDAV\n * Support for Digest Authentication in WebDAV\n
* Bugfixes (OI File manager, Open URL) * Bugfixes (OI File manager, Open URL)
</string> </string>
<string name="ChangeLog_0_8_1"><b>Version 0.8.1</b>\n <string name="ChangeLog_0_8_1">
<b>Version 0.8.1</b>\n
* KP2A Offline and "Online" can be installed both again\n * KP2A Offline and "Online" can be installed both again\n
* Added new translations (thanks to all contributors!) * Added new translations (thanks to all contributors!)
</string> </string>
<string name="ChangeLog_0_8"><b>Version 0.8</b>\n <string name="ChangeLog_0_8">
<b>Version 0.8</b>\n
* Improved user interface especially for Android 4.x devices\n * Improved user interface especially for Android 4.x devices\n
* Allow using deliberate file managers for selecting existing files\n * Allow using deliberate file managers for selecting existing files\n
* Added safer way for opening attachments (through cache directory)\n * Added safer way for opening attachments (through cache directory)\n
@ -521,11 +476,13 @@
* probably introduced new bugs :-) * probably introduced new bugs :-)
</string> </string>
<string name="ChangeLog_keptDonate">Extended possibility to donate a beer or something else</string> <string name="ChangeLog_keptDonate">Extended possibility to donate a beer or something else</string>
<string name="ChangeLog_0_7"><b>Version 0.7</b>\n <string name="ChangeLog_0_7">
<b>Version 0.7</b>\n
* Increased loading speed: key transformations now 10x faster!\n * Increased loading speed: key transformations now 10x faster!\n
* Added Keepass2Android soft-keyboard: Switch to this keyboard for entering credentials. Shields you from clipboard-based password sniffers (disable old clipboard notifications in the options)\n * Added Keepass2Android soft-keyboard: Switch to this keyboard for entering credentials. Shields you from clipboard-based password sniffers (disable old clipboard notifications in the options)\n
* Added option to donate a beer or something else (see menu)</string> * Added option to donate a beer or something else (see menu)</string>
<string name="ChangeLog"><b>Version 0.6.2</b>\n <string name="ChangeLog">
<b>Version 0.6.2</b>\n
* Google Drive/Dropbox/... integration: Use the official Google Drive or Dropbox App and open any .kdbx-file. This will now bring up KP2A.\n * Google Drive/Dropbox/... integration: Use the official Google Drive or Dropbox App and open any .kdbx-file. This will now bring up KP2A.\n
* Improved Search Dialog \n * Improved Search Dialog \n
* Improved search results for Share URL with subdomains\n * Improved search results for Share URL with subdomains\n
@ -559,14 +516,11 @@ Initial public release
<item>Medium</item> <item>Medium</item>
<item>Large</item> <item>Large</item>
</string-array> </string-array>
<string-array name="design_options"> <string-array name="design_options">
<item>Holo Light</item> <item>Holo Light</item>
<item>Holo Dark</item> <item>Holo Dark</item>
</string-array> </string-array>
<string name="design_title">Design</string> <string name="design_title">Design</string>
<string-array name="cred_remember_modes"> <string-array name="cred_remember_modes">
<item>Do not remember username and password</item> <item>Do not remember username and password</item>
<item>Remember username only</item> <item>Remember username only</item>
@ -583,5 +537,5 @@ Initial public release
<item>Warn when validation fails</item> <item>Warn when validation fails</item>
<item>Do not accept invalid certificates</item> <item>Do not accept invalid certificates</item>
</string-array> </string-array>
<string name="button_ok">Button</string>
</resources> </resources>

View File

@ -590,10 +590,15 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
credential.setSelectedAccountName(accountName); credential.setSelectedAccountName(accountName);
return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential) return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential)
.setApplicationName("Keepass2Android") .setApplicationName(getApplicationName())
.build(); .build();
} }
protected String getApplicationName()
{
return "Keepass2Android";
}
private Drive getDriveService(String accountName) private Drive getDriveService(String accountName)
{ {
logDebug("getDriveService "+accountName); logDebug("getDriveService "+accountName);

View File

@ -116,9 +116,10 @@ public class AccessManager
Log.d(_tag, "hostPackage is empty!"); Log.d(_tag, "hostPackage is empty!");
return null; return null;
} }
Log.d(_tag, "trying to find prefs for "+hostPackage);
SharedPreferences prefs = getPrefsForHost(ctx, hostPackage); SharedPreferences prefs = getPrefsForHost(ctx, hostPackage);
String scopesString = prefs.getString(PREF_KEY_SCOPE, ""); String scopesString = prefs.getString(PREF_KEY_SCOPE, "");
Log.d(_tag, "scopes: "+ scopesString); Log.d(_tag, "available scopes: "+ scopesString);
ArrayList<String> currentScope = stringToStringArray(scopesString); ArrayList<String> currentScope = stringToStringArray(scopesString);
if (isSubset(scopes, currentScope)) if (isSubset(scopes, currentScope))
{ {
@ -147,6 +148,7 @@ public class AccessManager
String accessToken) { String accessToken) {
SharedPreferences prefs = getPrefsForHost(ctx, hostPackage); SharedPreferences prefs = getPrefsForHost(ctx, hostPackage);
Log.d(_tag, "removing AccessToken.");
if (prefs.getString(PREF_KEY_TOKEN, "").equals(accessToken)) if (prefs.getString(PREF_KEY_TOKEN, "").equals(accessToken))
{ {
Editor edit = prefs.edit(); Editor edit = prefs.edit();

View File

@ -6,6 +6,7 @@ import android.R.anim;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.util.Log;
/** /**
* Broadcast flow between Host and Plugin * Broadcast flow between Host and Plugin
@ -30,10 +31,13 @@ import android.content.Intent;
* *
*/ */
public abstract class PluginAccessBroadcastReceiver extends BroadcastReceiver { public abstract class PluginAccessBroadcastReceiver extends BroadcastReceiver {
private static final String _tag = "Kp2aPluginSDK";
@Override @Override
public void onReceive(Context ctx, Intent intent) { public void onReceive(Context ctx, Intent intent) {
String action = intent.getAction(); String action = intent.getAction();
android.util.Log.d("KP2A.pluginsdk", "received broadcast with action="+action); android.util.Log.d(_tag, "received broadcast with action="+action);
if (action == null) if (action == null)
return; return;
if (action.equals(Strings.ACTION_TRIGGER_REQUEST_ACCESS)) if (action.equals(Strings.ACTION_TRIGGER_REQUEST_ACCESS))
@ -84,7 +88,7 @@ public abstract class PluginAccessBroadcastReceiver extends BroadcastReceiver {
} }
rpi.putStringArrayListExtra(Strings.EXTRA_SCOPES, getScopes()); rpi.putStringArrayListExtra(Strings.EXTRA_SCOPES, getScopes());
Log.d(_tag, "requesting access for "+getScopes().size()+" tokens.");
ctx.sendBroadcast(rpi); ctx.sendBroadcast(rpi);
} }

View File

@ -31,11 +31,13 @@ namespace keepass2android
{ {
_valueView.Visibility = ViewStates.Gone; _valueView.Visibility = ViewStates.Gone;
_keyView.Visibility = ViewStates.Gone; _keyView.Visibility = ViewStates.Gone;
_container.Visibility = ViewStates.Gone;
} }
else else
{ {
_valueView.Visibility = ViewStates.Visible; _valueView.Visibility = ViewStates.Visible;
_keyView.Visibility = ViewStates.Visible; _keyView.Visibility = ViewStates.Visible;
_container.Visibility = ViewStates.Visible;
_valueView.Text = value; _valueView.Text = value;
} }
} }

View File

@ -908,7 +908,9 @@
<AndroidResource Include="Resources\drawable\ic_launcher_gray_bday.png" /> <AndroidResource Include="Resources\drawable\ic_launcher_gray_bday.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<TransformFile Include="Properties\AndroidManifest.xml" /> <TransformFile Include="Properties\AndroidManifest.xml">
<SubType>Designer</SubType>
</TransformFile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidResource Include="Resources\drawable\collections_new_label_holodark.png" /> <AndroidResource Include="Resources\drawable\collections_new_label_holodark.png" />