diff --git a/src/KeePassLib2Android/Keys/IUserKey.cs b/src/KeePassLib2Android/Keys/IUserKey.cs
index d4739bb2..3f7af817 100644
--- a/src/KeePassLib2Android/Keys/IUserKey.cs
+++ b/src/KeePassLib2Android/Keys/IUserKey.cs
@@ -38,9 +38,11 @@ namespace KeePassLib.Keys
get;
}
- // ///
- // /// Clear the key and securely erase all security-critical information.
- // ///
- // void Clear();
+ // ///
+ // /// Clear the key and securely erase all security-critical information.
+ // ///
+ // void Clear();
+
+ uint GetMinKdbxVersion();
}
}
diff --git a/src/KeePassLib2Android/Keys/KcpCustomKey.cs b/src/KeePassLib2Android/Keys/KcpCustomKey.cs
index 9f5deb96..fc26e24a 100644
--- a/src/KeePassLib2Android/Keys/KcpCustomKey.cs
+++ b/src/KeePassLib2Android/Keys/KcpCustomKey.cs
@@ -45,7 +45,12 @@ namespace KeePassLib.Keys
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(pbKeyData != null); if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");
diff --git a/src/KeePassLib2Android/Keys/KcpKeyFile.cs b/src/KeePassLib2Android/Keys/KcpKeyFile.cs
index 68abb84a..e5ef2b07 100644
--- a/src/KeePassLib2Android/Keys/KcpKeyFile.cs
+++ b/src/KeePassLib2Android/Keys/KcpKeyFile.cs
@@ -64,7 +64,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; }
}
- public IOConnectionInfo Ioc
+ public uint GetMinKdbxVersion()
+ {
+ return 0;
+ }
+
+ public IOConnectionInfo Ioc
{
get { return m_ioc; }
}
diff --git a/src/KeePassLib2Android/Keys/KcpPassword.cs b/src/KeePassLib2Android/Keys/KcpPassword.cs
index f1627784..ac0be666 100644
--- a/src/KeePassLib2Android/Keys/KcpPassword.cs
+++ b/src/KeePassLib2Android/Keys/KcpPassword.cs
@@ -53,7 +53,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; }
}
- public KcpPassword(byte[] pbPasswordUtf8)
+ public uint GetMinKdbxVersion()
+ {
+ return 0;
+ }
+
+ public KcpPassword(byte[] pbPasswordUtf8)
{
SetKey(pbPasswordUtf8);
}
diff --git a/src/KeePassLib2Android/Keys/KcpUserAccount.cs b/src/KeePassLib2Android/Keys/KcpUserAccount.cs
index 39079b80..529af0aa 100644
--- a/src/KeePassLib2Android/Keys/KcpUserAccount.cs
+++ b/src/KeePassLib2Android/Keys/KcpUserAccount.cs
@@ -60,7 +60,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; }
}
- ///
+ public uint GetMinKdbxVersion()
+ {
+ return 0;
+ }
+
+ ///
/// Construct a user account key.
///
public KcpUserAccount()
diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.cs b/src/KeePassLib2Android/Serialization/KdbxFile.cs
index e61e2632..4a4e3a33 100644
--- a/src/KeePassLib2Android/Serialization/KdbxFile.cs
+++ b/src/KeePassLib2Android/Serialization/KdbxFile.cs
@@ -23,6 +23,7 @@ using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Security;
using System.Text;
using System.Xml;
@@ -126,8 +127,8 @@ namespace KeePassLib.Serialization
///
private const uint FileVersion32 = 0x00040000;
- internal const uint FileVersion32_4 = 0x00040000; // First of 4.x series
- internal const uint FileVersion32_3 = 0x00030001; // Old format 3.1
+ public const uint FileVersion32_4 = 0x00040000; // First of 4.x series
+ public const uint FileVersion32_3 = 0x00030001; // Old format 3.1
private const uint FileVersionCriticalMask = 0xFFFF0000;
@@ -372,16 +373,19 @@ namespace KeePassLib.Serialization
{
if(m_uForceVersion != 0) return m_uForceVersion;
- // See also KeePassKdb2x3.Export (KDBX 3.1 export module)
-
- AesKdf kdfAes = new AesKdf();
+ // See also KeePassKdb2x3.Export (KDBX 3.1 export module)
+ uint minVersionForKeys = m_pwDatabase.MasterKey.UserKeys.Select(key => key.GetMinKdbxVersion()).Max();
+
+ AesKdf kdfAes = new AesKdf();
if(!kdfAes.Uuid.Equals(m_pwDatabase.KdfParameters.KdfUuid))
- return FileVersion32;
+ return Math.Max(FileVersion32, minVersionForKeys);
if(m_pwDatabase.PublicCustomData.Count > 0)
- return FileVersion32;
+ return Math.Max(FileVersion32, minVersionForKeys);
- bool bCustomData = false;
+
+
+ bool bCustomData = false;
GroupHandler gh = delegate(PwGroup pg)
{
if(pg == null) { Debug.Assert(false); return true; }
@@ -396,9 +400,10 @@ namespace KeePassLib.Serialization
};
gh(m_pwDatabase.RootGroup);
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,
diff --git a/src/keepass2android/ChallengeXCKey.cs b/src/keepass2android/ChallengeXCKey.cs
index 72a469ea..8303cfe5 100644
--- a/src/keepass2android/ChallengeXCKey.cs
+++ b/src/keepass2android/ChallengeXCKey.cs
@@ -2,6 +2,7 @@ using Java.Lang;
using KeePassLib.Cryptography;
using KeePassLib.Keys;
using KeePassLib.Security;
+using KeePassLib.Serialization;
using Exception = System.Exception;
namespace keepass2android
@@ -62,6 +63,11 @@ namespace keepass2android
}
}
+ public uint GetMinKdbxVersion()
+ {
+ return KdbxFile.FileVersion32_4;
+ }
+
private byte[] _kdfSeed;
public ChallengeXCKey(LockingActivity activity, int requestCode)