make sure we always save database as KDBX4 when using ChallengeXCKey (for compatibility with KeepassXC), closes #596

This commit is contained in:
Philipp Crocoll
2018-11-20 06:08:30 +01:00
parent 2132ea416b
commit 8512bae997
7 changed files with 51 additions and 18 deletions

View File

@@ -38,9 +38,11 @@ namespace KeePassLib.Keys
get; get;
} }
// /// <summary> // /// <summary>
// /// Clear the key and securely erase all security-critical information. // /// Clear the key and securely erase all security-critical information.
// /// </summary> // /// </summary>
// void Clear(); // void Clear();
uint GetMinKdbxVersion();
} }
} }

View File

@@ -45,7 +45,12 @@ namespace KeePassLib.Keys
get { return m_pbKey; } get { return m_pbKey; }
} }
public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash) public uint GetMinKdbxVersion()
{
return 0;
}
public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash)
{ {
Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName"); Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName");
Debug.Assert(pbKeyData != null); if(pbKeyData == null) throw new ArgumentNullException("pbKeyData"); Debug.Assert(pbKeyData != null); if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");

View File

@@ -64,7 +64,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; } get { return m_pbKeyData; }
} }
public IOConnectionInfo Ioc public uint GetMinKdbxVersion()
{
return 0;
}
public IOConnectionInfo Ioc
{ {
get { return m_ioc; } get { return m_ioc; }
} }

View File

@@ -53,7 +53,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; } get { return m_pbKeyData; }
} }
public KcpPassword(byte[] pbPasswordUtf8) public uint GetMinKdbxVersion()
{
return 0;
}
public KcpPassword(byte[] pbPasswordUtf8)
{ {
SetKey(pbPasswordUtf8); SetKey(pbPasswordUtf8);
} }

View File

@@ -60,7 +60,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; } get { return m_pbKeyData; }
} }
/// <summary> public uint GetMinKdbxVersion()
{
return 0;
}
/// <summary>
/// Construct a user account key. /// Construct a user account key.
/// </summary> /// </summary>
public KcpUserAccount() public KcpUserAccount()

View File

@@ -23,6 +23,7 @@ using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Security; using System.Security;
using System.Text; using System.Text;
using System.Xml; using System.Xml;
@@ -126,8 +127,8 @@ namespace KeePassLib.Serialization
/// </summary> /// </summary>
private const uint FileVersion32 = 0x00040000; private const uint FileVersion32 = 0x00040000;
internal const uint FileVersion32_4 = 0x00040000; // First of 4.x series public const uint FileVersion32_4 = 0x00040000; // First of 4.x series
internal const uint FileVersion32_3 = 0x00030001; // Old format 3.1 public const uint FileVersion32_3 = 0x00030001; // Old format 3.1
private const uint FileVersionCriticalMask = 0xFFFF0000; private const uint FileVersionCriticalMask = 0xFFFF0000;
@@ -372,16 +373,19 @@ namespace KeePassLib.Serialization
{ {
if(m_uForceVersion != 0) return m_uForceVersion; if(m_uForceVersion != 0) return m_uForceVersion;
// See also KeePassKdb2x3.Export (KDBX 3.1 export module) // See also KeePassKdb2x3.Export (KDBX 3.1 export module)
uint minVersionForKeys = m_pwDatabase.MasterKey.UserKeys.Select(key => key.GetMinKdbxVersion()).Max();
AesKdf kdfAes = new AesKdf(); AesKdf kdfAes = new AesKdf();
if(!kdfAes.Uuid.Equals(m_pwDatabase.KdfParameters.KdfUuid)) if(!kdfAes.Uuid.Equals(m_pwDatabase.KdfParameters.KdfUuid))
return FileVersion32; return Math.Max(FileVersion32, minVersionForKeys);
if(m_pwDatabase.PublicCustomData.Count > 0) if(m_pwDatabase.PublicCustomData.Count > 0)
return FileVersion32; return Math.Max(FileVersion32, minVersionForKeys);
bool bCustomData = false;
bool bCustomData = false;
GroupHandler gh = delegate(PwGroup pg) GroupHandler gh = delegate(PwGroup pg)
{ {
if(pg == null) { Debug.Assert(false); return true; } if(pg == null) { Debug.Assert(false); return true; }
@@ -396,9 +400,10 @@ namespace KeePassLib.Serialization
}; };
gh(m_pwDatabase.RootGroup); gh(m_pwDatabase.RootGroup);
m_pwDatabase.RootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh); m_pwDatabase.RootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh);
if(bCustomData) return FileVersion32; if(bCustomData)
return Math.Max(FileVersion32, minVersionForKeys);
return FileVersion32_3; // KDBX 3.1 is sufficient return Math.Max(FileVersion32_3, minVersionForKeys); ; // KDBX 3.1 is sufficient
} }
private void ComputeKeys(out byte[] pbCipherKey, int cbCipherKey, private void ComputeKeys(out byte[] pbCipherKey, int cbCipherKey,

View File

@@ -2,6 +2,7 @@ using Java.Lang;
using KeePassLib.Cryptography; using KeePassLib.Cryptography;
using KeePassLib.Keys; using KeePassLib.Keys;
using KeePassLib.Security; using KeePassLib.Security;
using KeePassLib.Serialization;
using Exception = System.Exception; using Exception = System.Exception;
namespace keepass2android namespace keepass2android
@@ -62,6 +63,11 @@ namespace keepass2android
} }
} }
public uint GetMinKdbxVersion()
{
return KdbxFile.FileVersion32_4;
}
private byte[] _kdfSeed; private byte[] _kdfSeed;
public ChallengeXCKey(LockingActivity activity, int requestCode) public ChallengeXCKey(LockingActivity activity, int requestCode)