Implemented loading of Keepass 1 (kdb) files. First test passed!

This commit is contained in:
Philipp Crocoll
2014-01-26 03:51:55 -08:00
parent 12dbe597ce
commit 8bbd18d3f8
15 changed files with 210 additions and 74 deletions

View File

@@ -1,27 +1,23 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using Android.Content;
using Com.Keepassdroid.Database;
using Com.Keepassdroid.Database.Exception;
using Java.Lang;
using KeePassLib;
using KeePassLib.Cryptography;
using KeePassLib.Cryptography.Cipher;
using KeePassLib.Interfaces;
using KeePassLib.Keys;
using KeePassLib.Security;
using Exception = System.Exception;
using PwIcon = KeePassLib.PwIcon;
namespace keepass2android
{
class KdbDatabaseLoader: IDatabaseLoader
{
private Context _ctx;
public KdbDatabaseLoader(Context ctx)
{
_ctx = ctx;
}
private Dictionary<PwUuid, AdditionalGroupData> _groupData = new Dictionary<PwUuid, AdditionalGroupData>();
public void PopulateDatabaseFromStream(PwDatabase db, CompositeKey key, Stream s, IStatusLogger slLogger)
{
@@ -49,6 +45,8 @@ namespace keepass2android
var dbv3 = importer.OpenDatabase(hashingStream, password, keyfile);
db.Name = dbv3.Name;
db.RootGroup = ConvertGroup(dbv3.RootGroup);
}
catch (InvalidPasswordException e) {
@@ -71,6 +69,98 @@ namespace keepass2android
throw new Exception("hashing didn't work"); //todo remove
}
private PwGroup ConvertGroup(PwGroupV3 groupV3)
{
PwGroup pwGroup = new PwGroup(true, false);
pwGroup.Name = groupV3.Name;
pwGroup.CreationTime = ConvertTime(groupV3.TCreation);
pwGroup.LastAccessTime = ConvertTime(groupV3.TLastAccess);
pwGroup.LastModificationTime = ConvertTime(groupV3.TLastMod);
pwGroup.Expires = !PwGroupV3.NeverExpire.Equals(groupV3.TExpire);
if (pwGroup.Expires)
pwGroup.ExpiryTime = ConvertTime(groupV3.TExpire);
if (groupV3.Icon != null)
pwGroup.IconId = (PwIcon) groupV3.Icon.IconId;
_groupData.Add(pwGroup.Uuid, new AdditionalGroupData
{
Flags = groupV3.Flags,
Id = groupV3.Id.Id
});
for (int i = 0; i < groupV3.ChildGroups.Count;i++)
{
pwGroup.AddGroup(ConvertGroup(groupV3.GetGroupAt(i)), true);
}
for (int i = 0; i < groupV3.ChildEntries.Count; i++)
{
var entry = groupV3.GetEntryAt(i);
if (entry.IsMetaStream)
continue;
pwGroup.AddEntry(ConvertEntry(entry), true);
}
return pwGroup;
}
private PwEntry ConvertEntry(PwEntryV3 entryV3)
{
PwEntry pwEntry = new PwEntry(false, false);
pwEntry.Uuid = new PwUuid(entryV3.Uuid.ToArray());
pwEntry.CreationTime = ConvertTime(entryV3.TCreation);
pwEntry.LastAccessTime = ConvertTime(entryV3.TLastAccess);
pwEntry.LastModificationTime = ConvertTime(entryV3.TLastMod);
pwEntry.Expires = entryV3.Expires();
if (pwEntry.Expires)
pwEntry.ExpiryTime = ConvertTime(entryV3.TExpire);
if (entryV3.Icon != null)
pwEntry.IconId = (PwIcon) entryV3.Icon.IconId;
SetFieldIfAvailable(pwEntry, PwDefs.TitleField, false, entryV3.Title);
SetFieldIfAvailable(pwEntry, PwDefs.UserNameField, false, entryV3.Username);
SetFieldIfAvailable(pwEntry, PwDefs.UrlField, false, entryV3.Url);
SetFieldIfAvailable(pwEntry, PwDefs.PasswordField, true, entryV3.Password);
SetFieldIfAvailable(pwEntry, PwDefs.NotesField, true, entryV3.Additional);
if (entryV3.GetBinaryData() != null)
{
pwEntry.Binaries.Set(entryV3.BinaryDesc, new ProtectedBinary(true, entryV3.GetBinaryData()));
}
return pwEntry;
}
private void SetFieldIfAvailable(PwEntry pwEntry, string fieldName, bool makeProtected, string value)
{
if (value != null)
{
pwEntry.Strings.Set(fieldName, new ProtectedString(makeProtected, value));
}
}
private DateTime ConvertTime(PwDate date)
{
if (date == null)
return PwDefs.DtDefaultNow;
return JavaTimeToCSharp(date.JDate.Time);
}
private DateTime JavaTimeToCSharp(long javatime)
{
return new DateTime(1970, 1, 1).AddMilliseconds(javatime);
}
public byte[] HashOfLastStream { get; private set; }
public bool CanWrite { get { return false; } }
}
internal class AdditionalGroupData
{
public int Id { get; set; }
public int Flags { get; set; }
}
}