diff --git a/KeePass2PCL.Test.Desktop/KeePass2PCL.Test.Desktop.csproj b/KeePass2PCL.Test.Desktop/KeePass2PCL.Test.Desktop.csproj
new file mode 100644
index 0000000..e7ca24b
--- /dev/null
+++ b/KeePass2PCL.Test.Desktop/KeePass2PCL.Test.Desktop.csproj
@@ -0,0 +1,102 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {0BD8B544-EB60-461F-9A71-605A6DFCBB19}
+ Library
+ KeePass2PCL.Test.Desktop
+ KeePass2PCL.Test.Desktop
+ v4.5
+
+
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ false
+
+
+ full
+ true
+ bin\Release
+ prompt
+ 4
+ false
+
+
+
+ ..\packages\Castle.Core.4.1.1\lib\net45\Castle.Core.dll
+
+
+
+
+ ..\packages\Moq.4.7.99\lib\net45\Moq.dll
+
+
+ ..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll
+
+
+ ..\packages\PCLCrypto.2.0.147\lib\net45\PCLCrypto.dll
+
+
+ ..\packages\PInvoke.BCrypt.0.5.97\lib\net45\PInvoke.BCrypt.dll
+
+
+ ..\packages\PInvoke.Kernel32.0.5.97\lib\net45\PInvoke.Kernel32.dll
+
+
+ ..\packages\PInvoke.NCrypt.0.5.97\lib\net45\PInvoke.NCrypt.dll
+
+
+ ..\packages\PInvoke.Windows.Core.0.5.97\lib\net35\PInvoke.Windows.Core.dll
+
+
+ ..\packages\Splat.GtkSharp.1.6.2\lib\net45\Splat.dll
+
+
+
+ ..\packages\PCLStorage.1.0.2\lib\net45\PCLStorage.dll
+
+
+ ..\packages\PCLStorage.1.0.2\lib\net45\PCLStorage.Abstractions.dll
+
+
+ ..\packages\Mono.Security.3.2.3.0\lib\net45\Mono.Security.dll
+
+
+
+
+ ..\packages\Validation.2.4.15\lib\net45\Validation.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {2e710089-9559-4967-846c-e763dd1f3acb}
+ KeePass2PCL
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test.Desktop/app.config b/KeePass2PCL.Test.Desktop/app.config
new file mode 100644
index 0000000..6d631fa
--- /dev/null
+++ b/KeePass2PCL.Test.Desktop/app.config
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test.Desktop/packages.config b/KeePass2PCL.Test.Desktop/packages.config
new file mode 100644
index 0000000..57fbffd
--- /dev/null
+++ b/KeePass2PCL.Test.Desktop/packages.config
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test.Shared/Cryptography/Cipher/StandardAesEngineTests.cs b/KeePass2PCL.Test.Shared/Cryptography/Cipher/StandardAesEngineTests.cs
new file mode 100644
index 0000000..b248752
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Cryptography/Cipher/StandardAesEngineTests.cs
@@ -0,0 +1,65 @@
+using System;
+using System.IO;
+
+#if KeePassLib
+using KeePassLib.Cryptography.Cipher;
+#else
+using KeePass2PCL.Cryptography.Cipher;
+#endif
+
+using NUnit.Framework;
+
+namespace KeePass2PCL.Test.Shared.Cryptography.Cipher
+{
+ [TestFixture ()]
+ public class StandardAesEngineTests
+ {
+ [Test ()]
+ public void TestEncryptStream ()
+ {
+ // Test vector (official ECB test vector #356)
+ var pbIV = new byte[16];
+ var pbTestKey = new byte[32];
+ var pbTestData = new byte[16];
+ var pbReferenceCT = new byte[16] {
+ 0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
+ 0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7
+ };
+
+ pbTestData[0] = 0x04;
+
+ var outStream = new MemoryStream (new byte[16]);
+ var aes = new StandardAesEngine ();
+ var inStream = aes.EncryptStream (outStream, pbTestKey, pbIV);
+ new BinaryWriter (inStream).Write (pbTestData);
+ Assert.That (outStream.Position, Is.EqualTo (16));
+ outStream.Position = 0;
+ var outBytes = new BinaryReader (outStream).ReadBytes (16);
+ Assert.That(outBytes, Is.EqualTo (pbReferenceCT));
+ }
+
+ [Test ()]
+ public void TestDecryptStream ()
+ {
+ // Test vector (official ECB test vector #356)
+ var pbIV = new byte[16];
+ var pbTestKey = new byte[32];
+ var pbTestData = new byte[16];
+ var pbReferenceCT = new byte[16] {
+ 0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
+ 0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7
+ };
+
+ pbTestData[0] = 0x04;
+
+ // Possible Mono Bug? This only works with size >= 48
+ var inStream = new MemoryStream (new byte[48]);
+ inStream.Write (pbReferenceCT, 0, pbReferenceCT.Length);
+ inStream.Position = 0;
+ var aes = new StandardAesEngine ();
+ var outStream = aes.DecryptStream (inStream, pbTestKey, pbIV);
+ var outBytes = new BinaryReader (outStream).ReadBytes (16);
+ Assert.That(outBytes, Is.EqualTo (pbTestData));
+ }
+ }
+}
diff --git a/KeePass2PCL.Test.Shared/Cryptography/CryptoRandomStreamTests.cs b/KeePass2PCL.Test.Shared/Cryptography/CryptoRandomStreamTests.cs
new file mode 100644
index 0000000..cf585f2
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Cryptography/CryptoRandomStreamTests.cs
@@ -0,0 +1,60 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Cryptography;
+#else
+using ModernKeePassLibPCL.Cryptography;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Cryptography
+{
+ [TestFixture ()]
+ public class CryptoRandomStreamTests
+ {
+ void TestGetRandomBytes(CryptoRandomStream stream)
+ {
+ const uint length = 16;
+ var bytes1 = stream.GetRandomBytes (length);
+ Assert.That (bytes1.Length, Is.EqualTo (length));
+ var bytes2 = stream.GetRandomBytes (length);
+ Assert.That (bytes2, Is.Not.EqualTo (bytes1));
+ }
+
+ [Test ()]
+ public void TestGetRandomBytesCrsAlgorithmSalsa20 ()
+ {
+ var stream = new CryptoRandomStream (CrsAlgorithm.Salsa20, new byte[16]);
+ TestGetRandomBytes (stream);
+ }
+
+ [Test ()]
+ public void TestGetRandomBytesCrsAlgorithmArcFourVariant ()
+ {
+ var stream = new CryptoRandomStream (CrsAlgorithm.ArcFourVariant, new byte[16]);
+ TestGetRandomBytes (stream);
+ }
+
+ void TestGetRandomInt64 (CryptoRandomStream stream)
+ {
+ var value1 = stream.GetRandomUInt64 ();
+ var value2 = stream.GetRandomUInt64 ();
+ Assert.That (value2, Is.Not.EqualTo (value1));
+ }
+
+ [Test ()]
+ public void TestGetRandomInt64AlgorithmSalsa20 ()
+ {
+ var stream = new CryptoRandomStream (CrsAlgorithm.Salsa20, new byte[16]);
+ TestGetRandomInt64 (stream);
+ }
+
+ [Test ()]
+ public void TestGetRandomInt64AlgorithmArcFourVariant ()
+ {
+ var stream = new CryptoRandomStream (CrsAlgorithm.ArcFourVariant, new byte[16]);
+ TestGetRandomInt64 (stream);
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/Cryptography/CryptoRandomTests.cs b/KeePass2PCL.Test.Shared/Cryptography/CryptoRandomTests.cs
new file mode 100644
index 0000000..90d8db8
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Cryptography/CryptoRandomTests.cs
@@ -0,0 +1,44 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Cryptography;
+#else
+using KeePass2PCL.Cryptography;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Cryptography
+{
+ [TestFixture ()]
+ public class CryptoRandomTests
+ {
+ [Test ()]
+ public void TestAddEntropy ()
+ {
+ // just making sure it does not throw an exception
+ CryptoRandom.Instance.AddEntropy (new byte[1]);
+ }
+
+ [Test ()]
+ public void TestGetRandomBytes ()
+ {
+ const int length = 32;
+ var bytes1 = CryptoRandom.Instance.GetRandomBytes (length);
+ Assert.That (bytes1.Length, Is.EqualTo (length));
+ var bytes2 = CryptoRandom.Instance.GetRandomBytes (length);
+ Assert.That (bytes2, Is.Not.EqualTo (bytes1));
+ }
+
+ [Test ()]
+ public void TestGeneratedBytesCount ()
+ {
+ const int length = 1;
+ CryptoRandom.Instance.GetRandomBytes (length);
+ var count1 = CryptoRandom.Instance.GeneratedBytesCount;
+ CryptoRandom.Instance.GetRandomBytes (length);
+ var count2 = CryptoRandom.Instance.GeneratedBytesCount;
+ Assert.That (count2, Is.GreaterThan (count1));
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/Cryptography/HashingStreamExTests.cs b/KeePass2PCL.Test.Shared/Cryptography/HashingStreamExTests.cs
new file mode 100644
index 0000000..8db9b59
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Cryptography/HashingStreamExTests.cs
@@ -0,0 +1,77 @@
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Text;
+
+#if KeePassLib
+using KeePassLib.Cryptography;
+#else
+using KeePass2PCL.Cryptography;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Cryptography
+{
+ [TestFixture ()]
+ public class HashingStreamExTests
+ {
+ const string data = "test";
+
+ // The expected hash includes the \n added by WriteLine
+ static readonly byte[] sha256HashOfData = {
+ 0xf2, 0xca, 0x1b, 0xb6, 0xc7, 0xe9, 0x07, 0xd0,
+ 0x6d, 0xaf, 0xe4, 0x68, 0x7e, 0x57, 0x9f, 0xce,
+ 0x76, 0xb3, 0x7e, 0x4e, 0x93, 0xb7, 0x60, 0x50,
+ 0x22, 0xda, 0x52, 0xe6, 0xcc, 0xc2, 0x6f, 0xd2
+ };
+
+ [Test ()]
+ public void TestRead ()
+ {
+ // if we use larger size, StreamReader will read past newline and cause bad hash
+ var bytes = new byte[data.Length + 1];
+ using (var ms = new MemoryStream (bytes)) {
+ using (var sw = new StreamWriter (ms)) {
+ // set NewLine to ensure we don't run into cross-platform issues on Windows
+ sw.NewLine = "\n";
+ sw.WriteLine (data);
+ }
+ }
+ using (var ms = new MemoryStream (bytes)) {
+ using (var hs = new HashingStreamEx (ms, false, null)) {
+ using (var sr = new StreamReader (hs)) {
+ var read = sr.ReadLine ();
+ Assert.That (read, Is.EqualTo (data));
+ }
+ // When the StreamReader is disposed, it calls Dispose on the
+ //HasingStreamEx, which computes the hash.
+ Assert.That (hs.Hash, Is.EqualTo (sha256HashOfData));
+ }
+ }
+ }
+
+ [Test ()]
+ public void TestWrite ()
+ {
+ var bytes = new byte[16];
+ using (var ms = new MemoryStream (bytes)) {
+ using (var hs = new HashingStreamEx (ms, true, null)) {
+ using (var sw = new StreamWriter (hs)) {
+ // set NewLine to ensure we don't run into cross-platform issues on Windows
+ sw.NewLine = "\n";
+ sw.WriteLine (data);
+ }
+ // When the StreamWriter is disposed, it calls Dispose on the
+ //HasingStreamEx, which computes the hash.
+ Assert.That (hs.Hash, Is.EqualTo (sha256HashOfData));
+ }
+ }
+ using (var ms = new MemoryStream (bytes)) {
+ using (var sr = new StreamReader (ms)) {
+ var read = sr.ReadLine ();
+ Assert.That (read, Is.EqualTo (data));
+ }
+ }
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/Cryptography/HmacOtpTests.cs b/KeePass2PCL.Test.Shared/Cryptography/HmacOtpTests.cs
new file mode 100644
index 0000000..ce3307b
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Cryptography/HmacOtpTests.cs
@@ -0,0 +1,36 @@
+using NUnit.Framework;
+using System;
+using System.Text;
+
+#if KeePassLib
+using KeePassLib.Cryptography;
+#else
+using KeePass2PCL.Cryptography;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Cryptography
+{
+ [TestFixture ()]
+ public class HmacOtpTests
+ {
+ // Using the test case from Appendix D of RFC 4226
+
+ const string secret = "12345678901234567890";
+ static readonly string[] expectedHOTP = new string[] {
+ "755224", "287082", "359152", "969429", "338314",
+ "254676", "287922", "162583", "399871", "520489"
+ };
+
+ [Test ()]
+ public void TestGenerate ()
+ {
+ var secretBytes = Encoding.UTF8.GetBytes (secret);
+
+ for (ulong i = 0; i < 10; i++) {
+ var hotp = HmacOtp.Generate (secretBytes, i, 6, false, -1);
+ Assert.That (hotp, Is.EqualTo (expectedHOTP[i]));
+ }
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/KeePass2PCL.Test.Shared.projitems b/KeePass2PCL.Test.Shared/KeePass2PCL.Test.Shared.projitems
new file mode 100644
index 0000000..fff96bf
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/KeePass2PCL.Test.Shared.projitems
@@ -0,0 +1,30 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ {17F1C1A7-AE14-47AD-AE9A-ECFB9C45A559}
+
+
+ KeePass2PCL.Test.Shared
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test.Shared/KeePass2PCL.Test.Shared.shproj b/KeePass2PCL.Test.Shared/KeePass2PCL.Test.Shared.shproj
new file mode 100644
index 0000000..1f5f298
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/KeePass2PCL.Test.Shared.shproj
@@ -0,0 +1,11 @@
+
+
+
+ {17F1C1A7-AE14-47AD-AE9A-ECFB9C45A559}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test.Shared/Keys/CompositeKeyTests.cs b/KeePass2PCL.Test.Shared/Keys/CompositeKeyTests.cs
new file mode 100644
index 0000000..e033962
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Keys/CompositeKeyTests.cs
@@ -0,0 +1,34 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Keys;
+#else
+using KeePass2PCL.Keys;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Keys
+{
+ [TestFixture ()]
+ public class CompositeKeyTests
+ {
+ [Test ()]
+ public void TestGenerateKey32 ()
+ {
+ var originalKey = new byte[32];
+ var expectedKey = new byte[32] {
+ 0xF0, 0xED, 0x57, 0xD5, 0xF0, 0xDA, 0xF3, 0x47,
+ 0x90, 0xD0, 0xDB, 0x43, 0x25, 0xC6, 0x81, 0x2C,
+ 0x81, 0x6A, 0x0D, 0x94, 0x96, 0xA9, 0x03, 0xE1,
+ 0x20, 0xD4, 0x3A, 0x3E, 0x45, 0xAD, 0x02, 0x65
+ };
+ const ulong rounds = 1;
+
+ var composite = new CompositeKey ();
+ var key = composite.GenerateKey32 (originalKey, rounds);
+ Assert.That (key, Is.Not.Null);
+ var keyData = key.ReadData ();
+ Assert.That (keyData, Is.EqualTo (expectedKey));
+ }
+ }
+}
diff --git a/KeePass2PCL.Test.Shared/Keys/KcpCustomKeyTests.cs b/KeePass2PCL.Test.Shared/Keys/KcpCustomKeyTests.cs
new file mode 100644
index 0000000..597f051
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Keys/KcpCustomKeyTests.cs
@@ -0,0 +1,39 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Keys;
+#else
+using KeePass2PCL.Keys;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Keys
+{
+ [TestFixture ()]
+ public class KcpCustomKeyTests
+ {
+ static readonly byte[] testData = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ [Test ()]
+ public void TestConstruct ()
+ {
+ var expectedHash = new byte[32] {
+ 0xAF, 0x55, 0x70, 0xF5, 0xA1, 0x81, 0x0B, 0x7A,
+ 0xF7, 0x8C, 0xAF, 0x4B, 0xC7, 0x0A, 0x66, 0x0F,
+ 0x0D, 0xF5, 0x1E, 0x42, 0xBA, 0xF9, 0x1D, 0x4D,
+ 0xE5, 0xB2, 0x32, 0x8D, 0xE0, 0xE8, 0x3D, 0xFC
+ };
+
+ var key = new KcpCustomKey ("test1", testData, false);
+ var keyData = key.KeyData.ReadData ();
+ Assert.That (keyData, Is.EqualTo (testData));
+
+ key = new KcpCustomKey ("test2", testData, true);
+ keyData = key.KeyData.ReadData ();
+ Assert.That (keyData, Is.EqualTo (expectedHash));
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/Keys/KcpKeyFileTests.cs b/KeePass2PCL.Test.Shared/Keys/KcpKeyFileTests.cs
new file mode 100644
index 0000000..8cc0871
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Keys/KcpKeyFileTests.cs
@@ -0,0 +1,76 @@
+using NUnit.Framework;
+using System;
+using System.IO;
+
+#if KeePassLib
+using KeePassLib.Keys;
+#else
+using KeePass2PCL.Keys;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Keys
+{
+ [TestFixture ()]
+ public class KcpKeyFileTests
+ {
+ const string testCreateFile = "TestCreate.xml";
+ const string testKey = "0123456789";
+
+ const string expectedFileStart =
+ "\r\n" +
+ "\r\n" +
+ "\t\r\n" +
+ "\t\t1.00\r\n" +
+ "\t\r\n" +
+ "\t\r\n" +
+ "\t\t";
+
+ const string expectedFileEnd = "\t\r\n" +
+ "\r\n";
+
+ [Test ()]
+ public void TestConstruct ()
+ {
+ var expectedKeyData = new byte[32] {
+ 0xC1, 0xB1, 0x12, 0x77, 0x23, 0xB8, 0x99, 0xB8,
+ 0xB9, 0x3B, 0x1B, 0xFF, 0x6C, 0xBE, 0xA1, 0x5B,
+ 0x8B, 0x99, 0xAC, 0xBD, 0x99, 0x51, 0x85, 0x95,
+ 0x31, 0xAA, 0x14, 0x3D, 0x95, 0xBF, 0x63, 0xFF
+ };
+
+ var fullPath = Path.Combine(Path.GetTempPath(), testCreateFile);
+ using (var fs = new FileStream(fullPath, FileMode.Create)) {
+ using (var sw = new StreamWriter(fs)) {
+ sw.Write (expectedFileStart);
+ sw.Write (testKey);
+ sw.Write (expectedFileEnd);
+ }
+ }
+
+ try {
+ var keyFile = new KcpKeyFile (fullPath);
+ var keyData = keyFile.KeyData.ReadData ();
+ Assert.That (keyData, Is.EqualTo (expectedKeyData));
+ } finally {
+ File.Delete (fullPath);
+ }
+ }
+
+ [Test ()]
+ public void TestCreate ()
+ {
+ var fullPath = Path.Combine(Path.GetTempPath(), testCreateFile);
+ File.Create(fullPath).Close();
+ KcpKeyFile.Create (fullPath, null);
+ try {
+ var fileContents = File.ReadAllText (fullPath);
+ Assert.That (fileContents.Length, Is.EqualTo (187));
+ Assert.That (fileContents, Does.StartWith (expectedFileStart));
+ Assert.That (fileContents, Does.EndWith (expectedFileEnd));
+ } finally {
+ File.Delete (fullPath);
+ }
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/Keys/KcpPasswordTests.cs b/KeePass2PCL.Test.Shared/Keys/KcpPasswordTests.cs
new file mode 100644
index 0000000..533b5a7
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Keys/KcpPasswordTests.cs
@@ -0,0 +1,33 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Keys;
+#else
+using KeePass2PCL.Keys;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Keys
+{
+ [TestFixture ()]
+ public class KcpPasswordTests
+ {
+ const string testPassword = "password";
+
+ [Test ()]
+ public void TestConstruct ()
+ {
+ var expectedHash = new byte[32] {
+ 0x5E, 0x88, 0x48, 0x98, 0xDA, 0x28, 0x04, 0x71,
+ 0x51, 0xD0, 0xE5, 0x6F, 0x8D, 0xC6, 0x29, 0x27,
+ 0x73, 0x60, 0x3D, 0x0D, 0x6A, 0xAB, 0xBD, 0xD6,
+ 0x2A, 0x11, 0xEF, 0x72, 0x1D, 0x15, 0x42, 0xD8
+ };
+
+ var key = new KcpPassword (testPassword);
+ var keyData = key.KeyData.ReadData ();
+ Assert.That (keyData, Is.EqualTo (expectedHash));
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/MyClass.cs b/KeePass2PCL.Test.Shared/MyClass.cs
new file mode 100644
index 0000000..f57acff
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/MyClass.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace KeePass2PCL.Test.Shared
+{
+ public class MyClass
+ {
+ public MyClass ()
+ {
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/Serialization/HashedBlockStreamTests.cs b/KeePass2PCL.Test.Shared/Serialization/HashedBlockStreamTests.cs
new file mode 100644
index 0000000..b76122c
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Serialization/HashedBlockStreamTests.cs
@@ -0,0 +1,71 @@
+using NUnit.Framework;
+using System;
+using System.IO;
+
+#if KeePassLib
+using KeePassLib.Serialization;
+#else
+using KeePass2PCL.Serialization;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Serialization
+{
+ [TestFixture ()]
+ public class HashedBlockStreamTests
+ {
+ static readonly byte[] data = new byte[16];
+
+ static readonly byte[] hashStreamData = new byte[] {
+ // The first 4 bytes are an integer indicating the block index
+ 0x00, 0x00, 0x00, 0x00,
+ // Then the SHA-256 hash of the data
+ 0x37, 0x47, 0x08, 0xFF, 0xF7, 0x71, 0x9D, 0xD5,
+ 0x97, 0x9E, 0xC8, 0x75, 0xD5, 0x6C, 0xD2, 0x28,
+ 0x6F, 0x6D, 0x3C, 0xF7, 0xEC, 0x31, 0x7A, 0x3B,
+ 0x25, 0x63, 0x2A, 0xAB, 0x28, 0xEC, 0x37, 0xBB,
+ // then an integer that is the length of the data
+ 0x10, 0x00, 0x00, 0x00,
+ // and finally the data itself
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Next, a terminating block
+ 0x01, 0x00, 0x00, 0x00,
+ // terminating block is indicated by a hash of all 0s...
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // ...and by a size of 0
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ [Test ()]
+ public void TestRead ()
+ {
+ using (var ms = new MemoryStream (hashStreamData)) {
+ using (var hbs = new HashedBlockStream (ms, false)) {
+ using (var br = new BinaryReader(hbs)) {
+ var bytes = br.ReadBytes (data.Length);
+ Assert.That (bytes, Is.EqualTo (data));
+ Assert.That (() => br.ReadByte (), Throws.InstanceOf ());
+ }
+ }
+ }
+ }
+
+ [Test ()]
+ public void TestWrite ()
+ {
+ var buffer = new byte[hashStreamData.Length];
+ using (var ms = new MemoryStream (buffer)) {
+ using (var hbs = new HashedBlockStream (ms, true)) {
+ using (var bw = new BinaryWriter(hbs)) {
+ bw.Write (data);
+ }
+ }
+ Assert.That (buffer, Is.EqualTo (hashStreamData));
+ }
+ }
+ }
+}
+
diff --git a/KeePass2PCL.Test.Shared/Serialization/KdbxFileTests.cs b/KeePass2PCL.Test.Shared/Serialization/KdbxFileTests.cs
new file mode 100644
index 0000000..47cbc5e
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Serialization/KdbxFileTests.cs
@@ -0,0 +1,181 @@
+using NUnit.Framework;
+using System;
+using System.Drawing;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+
+
+#if KeePassLib
+using KeePassLib;
+using KeePassLib.Keys;
+using KeePassLib.Security;
+using KeePassLib.Serialization;
+using KeePassLib.Collections;
+#else
+using KeePass2PCL.Keys;
+using KeePass2PCL.Security;
+using KeePass2PCL.Serialization;
+using KeePass2PCL.Collections;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Serialization
+{
+ [TestFixture()]
+ public class KdbxFileTests
+ {
+ const string testLocalizedAppName = "My Localized App Name";
+
+ const string testDatabaseName = "My Database Name";
+ const string testDatabaseDescription = "My Database Description";
+ const string testDefaultUserName = "My Default User Name";
+ const string testColor = "#FF0000"; // Red
+
+ const string testRootGroupName = "My Root Group Name";
+ const string testRootGroupNotes = "My Root Group Notes";
+ const string testRootGroupDefaultAutoTypeSequence = "My Root Group Default Auto Type Sequence";
+
+ const string testDatabase = "\r\n" +
+ "\r\n" +
+ "\t\r\n" +
+ "\t\t" + testLocalizedAppName + "\r\n" +
+ "\t\t" + testDatabaseName + "\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t" + testDatabaseDescription + "\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t" + testDefaultUserName + "\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t365\r\n" +
+ "\t\t" + testColor + "\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t-1\r\n" +
+ "\t\t-1\r\n" +
+ "\t\t\r\n" +
+ "\t\t\tFalse\r\n" +
+ "\t\t\tFalse\r\n" +
+ "\t\t\tTrue\r\n" +
+ "\t\t\tFalse\r\n" +
+ "\t\t\tFalse\r\n" +
+ "\t\t\r\n" +
+ "\t\tTrue\r\n" +
+ "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t10\r\n" +
+ "\t\t6291456\r\n" +
+ "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t\r\n" +
+ "\t\t\r\n" +
+ "\t\r\n" +
+ "\t\r\n" +
+ "\t\t\r\n" +
+ "\t\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t\t" + testRootGroupName + "\r\n" +
+ "\t\t\t" + testRootGroupNotes + "\r\n" +
+ "\t\t\t49\r\n" +
+ "\t\t\t\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\tFalse\r\n" +
+ "\t\t\t\t0\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\r\n" +
+ "\t\t\tTrue\r\n" +
+ "\t\t\t" + testRootGroupDefaultAutoTypeSequence + "\r\n" +
+ "\t\t\tnull\r\n" +
+ "\t\t\tnull\r\n" +
+ "\t\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t\r\n" +
+ "\t\t\r\n" +
+ "\t\r\n" +
+ "";
+
+ const string testDate = "2015-03-14T03:15:26Z";
+
+ [Test()]
+ public void TestLoad()
+ {
+ var database = new PwDatabase();
+ using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(testDatabase)))
+ {
+ var file = new KdbxFile(database);
+ file.Load(ms, KdbxFormat.PlainXml, null);
+ }
+ Assert.That(database.Color.ToArgb(), Is.EqualTo(Color.Red.ToArgb()));
+ Assert.That(database.Compression, Is.EqualTo(PwCompressionAlgorithm.GZip));
+ //Assert.That (database.CustomData, Is.EqualTo ());
+ Assert.That(database.CustomIcons, Is.Empty);
+ }
+
+ [Test()]
+ public void TestSave()
+ {
+ var buffer = new byte[4096];
+ using (var ms = new MemoryStream(buffer))
+ {
+ var database = new PwDatabase();
+ database.New(new IOConnectionInfo(), new CompositeKey());
+ var date = DateTime.Parse(testDate);
+ PwDatabase.LocalizedAppName = testLocalizedAppName;
+ database.Name = testDatabaseName;
+ database.NameChanged = date;
+ database.Description = testDatabaseDescription;
+ database.DescriptionChanged = date;
+ database.DefaultUserName = testDefaultUserName;
+ database.DefaultUserNameChanged = date;
+ database.Color = Color.Red;
+ database.MasterKeyChanged = date;
+ database.RecycleBinChanged = date;
+ database.EntryTemplatesGroupChanged = date;
+ database.RootGroup.Uuid = PwUuid.Zero;
+ database.RootGroup.Name = testRootGroupName;
+ database.RootGroup.Notes = testRootGroupNotes;
+ database.RootGroup.DefaultAutoTypeSequence = testRootGroupDefaultAutoTypeSequence;
+ database.RootGroup.CreationTime = date;
+ database.RootGroup.LastModificationTime = date;
+ database.RootGroup.LastAccessTime = date;
+ database.RootGroup.ExpiryTime = date;
+ database.RootGroup.LocationChanged = date;
+ var file = new KdbxFile(database);
+ file.Save(ms, null, KdbxFormat.PlainXml, null);
+ }
+ var fileContents = Encoding.UTF8.GetString(buffer).Replace("\0", "");
+ if (typeof(KdbxFile).Namespace.StartsWith("KeePassLib.")
+ && Environment.OSVersion.Platform != PlatformID.Win32NT)
+ {
+ // Upstream KeePassLib does not specify line endings for XmlTextWriter,
+ // so it uses native line endings.
+ fileContents = fileContents.Replace("\n", "\r\n");
+ }
+ Assert.That(fileContents, Is.EqualTo(testDatabase));
+ }
+
+ [Test]
+ public void TestSearch()
+ {
+ var database = new PwDatabase();
+ using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(testDatabase)))
+ {
+ var file = new KdbxFile(database);
+ file.Load(ms, KdbxFormat.PlainXml, null);
+ }
+ var sp = new SearchParameters()
+ {
+ SearchString = "sfsoiwsefsi"
+ };
+ var listStorage = new PwObjectList();
+ database.RootGroup.SearchEntries(sp, listStorage);
+ Assert.AreEqual(0U, listStorage.UCount);
+ var entry = new PwEntry(true, true);
+ entry.Strings.Set("Title", new ProtectedString(false, "NaMe"));
+ database.RootGroup.AddEntry(entry, true);
+ sp.SearchString = "name";
+ database.RootGroup.SearchEntries(sp, listStorage);
+ Assert.AreEqual(1U, listStorage.UCount);
+ }
+ }
+}
diff --git a/KeePass2PCL.Test.Shared/Utility/GfxUtilTests.cs b/KeePass2PCL.Test.Shared/Utility/GfxUtilTests.cs
new file mode 100644
index 0000000..ce25156
--- /dev/null
+++ b/KeePass2PCL.Test.Shared/Utility/GfxUtilTests.cs
@@ -0,0 +1,32 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Utility;
+#else
+using Splat;
+using KeePass2PCL.Utility;
+#endif
+
+namespace KeePass2PCL.Test.Shared.Utility
+{
+ [TestFixture ()]
+ public class GfxUtilTests
+ {
+ // 16x16 all white PNG file, base64 encoded
+ const string testImageData =
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAA" +
+ "LEwEAmpwYAAAAB3RJTUUH3wMOFgIgmTCUMQAAABl0RVh0Q29tbWVudABDcmVhdG" +
+ "VkIHdpdGggR0lNUFeBDhcAAAAaSURBVCjPY/z//z8DKYCJgUQwqmFUw9DRAABVb" +
+ "QMdny4VogAAAABJRU5ErkJggg==";
+
+ [Test ()]
+ public void TestLoadImage ()
+ {
+ var testData = Convert.FromBase64String (testImageData);
+ var image = GfxUtil.LoadImage (testData);
+ Assert.That (image.Width, Is.EqualTo (16));
+ Assert.That (image.Height, Is.EqualTo (16));
+ }
+ }
+}
diff --git a/KeePass2PCL.Test.UWP/Assets/LockScreenLogo.scale-200.png b/KeePass2PCL.Test.UWP/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 0000000..735f57a
Binary files /dev/null and b/KeePass2PCL.Test.UWP/Assets/LockScreenLogo.scale-200.png differ
diff --git a/KeePass2PCL.Test.UWP/Assets/SplashScreen.scale-200.png b/KeePass2PCL.Test.UWP/Assets/SplashScreen.scale-200.png
new file mode 100644
index 0000000..023e7f1
Binary files /dev/null and b/KeePass2PCL.Test.UWP/Assets/SplashScreen.scale-200.png differ
diff --git a/KeePass2PCL.Test.UWP/Assets/Square150x150Logo.scale-200.png b/KeePass2PCL.Test.UWP/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 0000000..af49fec
Binary files /dev/null and b/KeePass2PCL.Test.UWP/Assets/Square150x150Logo.scale-200.png differ
diff --git a/KeePass2PCL.Test.UWP/Assets/Square44x44Logo.scale-200.png b/KeePass2PCL.Test.UWP/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 0000000..ce342a2
Binary files /dev/null and b/KeePass2PCL.Test.UWP/Assets/Square44x44Logo.scale-200.png differ
diff --git a/KeePass2PCL.Test.UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/KeePass2PCL.Test.UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 0000000..f6c02ce
Binary files /dev/null and b/KeePass2PCL.Test.UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/KeePass2PCL.Test.UWP/Assets/StoreLogo.png b/KeePass2PCL.Test.UWP/Assets/StoreLogo.png
new file mode 100644
index 0000000..7385b56
Binary files /dev/null and b/KeePass2PCL.Test.UWP/Assets/StoreLogo.png differ
diff --git a/KeePass2PCL.Test.UWP/Assets/Wide310x150Logo.scale-200.png b/KeePass2PCL.Test.UWP/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 0000000..288995b
Binary files /dev/null and b/KeePass2PCL.Test.UWP/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/KeePass2PCL.Test.UWP/KeePass2PCL.Test.UWP.csproj b/KeePass2PCL.Test.UWP/KeePass2PCL.Test.UWP.csproj
new file mode 100644
index 0000000..d11dd36
--- /dev/null
+++ b/KeePass2PCL.Test.UWP/KeePass2PCL.Test.UWP.csproj
@@ -0,0 +1,172 @@
+
+
+
+
+ Debug
+ x86
+ {4E21AE3C-13FF-4773-824C-D51542AD1A7B}
+ AppContainerExe
+ Properties
+ KeePass2PCL.Test.UWP
+ KeePass2PCL.Test.UWP
+ en-US
+ UAP
+ 10.0.15063.0
+ 10.0.10240.0
+ 14
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ KeePass2PCL.Test.UWP_TemporaryKey.pfx
+ $(VisualStudioVersion)
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ PackageReference
+
+
+
+
+
+
+
+
+ UnitTestApp.xaml
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5.4.0
+
+
+ 1.1.18
+
+
+ 1.1.18
+
+
+ 2.0.147
+
+
+ 1.1.0
+
+
+ 1.0.2
+
+
+ 2.0.0
+
+
+
+
+ {2e710089-9559-4967-846c-e763dd1f3acb}
+ KeePass2PCL
+
+
+
+
+
+
+ 14.0
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test.UWP/KeePass2PCL.Test.UWP_TemporaryKey.pfx b/KeePass2PCL.Test.UWP/KeePass2PCL.Test.UWP_TemporaryKey.pfx
new file mode 100644
index 0000000..f04aea4
Binary files /dev/null and b/KeePass2PCL.Test.UWP/KeePass2PCL.Test.UWP_TemporaryKey.pfx differ
diff --git a/KeePass2PCL.Test.UWP/Package.appxmanifest b/KeePass2PCL.Test.UWP/Package.appxmanifest
new file mode 100644
index 0000000..a869c8e
--- /dev/null
+++ b/KeePass2PCL.Test.UWP/Package.appxmanifest
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+ KeePass2PCL.Test.UWP
+ anpan
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test.UWP/Properties/AssemblyInfo.cs b/KeePass2PCL.Test.UWP/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..175ba33
--- /dev/null
+++ b/KeePass2PCL.Test.UWP/Properties/AssemblyInfo.cs
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("KeePass2PCL.Test.UWP")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("KeePass2PCL.Test.UWP")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyMetadata("TargetPlatform","UAP")]
+
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
\ No newline at end of file
diff --git a/KeePass2PCL.Test.UWP/Properties/UnitTestApp.rd.xml b/KeePass2PCL.Test.UWP/Properties/UnitTestApp.rd.xml
new file mode 100644
index 0000000..efee59d
--- /dev/null
+++ b/KeePass2PCL.Test.UWP/Properties/UnitTestApp.rd.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test.UWP/PwDatabaseTests.cs b/KeePass2PCL.Test.UWP/PwDatabaseTests.cs
new file mode 100644
index 0000000..868aa95
--- /dev/null
+++ b/KeePass2PCL.Test.UWP/PwDatabaseTests.cs
@@ -0,0 +1,117 @@
+using System.Reflection;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using PCLStorage;
+using System.IO;
+using KeePass2PCL.Serialization;
+using KeePass2PCL.Keys;
+
+namespace KeePass2PCL.Test.UWP
+{
+ [TestClass]
+ public class PwDatabaseTests
+ {
+ [TestMethod]
+ public void Open_With_Wrong_Password_Test()
+ {
+ IFolder folder = SpecialFolder.Current.Local;
+ IFolder testData = folder.CreateFolderAsync("TestData",
+ CreationCollisionOption.OpenIfExists).Result;
+ IFile file = testData.CreateFileAsync("1.kdbx",
+ CreationCollisionOption.ReplaceExisting).Result;
+ var fileStream = file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite).Result;
+ var assembly = typeof(PwDatabaseTests).GetTypeInfo().Assembly;
+ var stream = assembly.GetManifestResourceStream(
+ "KeePass2PCL.Test.UWP.TestData.1.kdbx");
+ using (var reader = new BinaryReader(stream))
+ using (var fileWriter = new BinaryWriter(fileStream))
+ {
+ fileWriter.Write(reader.ReadBytes((int)stream.Length));
+ }
+
+ var ci = new IOConnectionInfo();
+ ci.Path = file.Path;
+ var key = new CompositeKey();
+ key.AddUserKey(new KcpPassword("0"));
+ var db = new PwDatabase();
+ bool wasException = false;
+ try
+ {
+ db.Open(ci, key, null);
+ }
+ catch (InvalidCompositeKeyException)
+ {
+ wasException = true;
+ }
+ Assert.IsTrue(wasException);
+ file.DeleteAsync().Wait();
+ testData.DeleteAsync().Wait();
+ }
+
+ [TestMethod]
+ public void Open_With_KeyFile_Test()
+ {
+ IFolder folder = SpecialFolder.Current.Local;
+ IFolder testData = folder.CreateFolderAsync("TestData",
+ CreationCollisionOption.OpenIfExists).Result;
+ IFile keyFile = testData.CreateFileAsync("1.key",
+ CreationCollisionOption.ReplaceExisting).Result;
+ var fileStream = keyFile.OpenAsync(PCLStorage.FileAccess.ReadAndWrite).Result;
+ var assembly = typeof(PwDatabaseTests).GetTypeInfo().Assembly;
+ var stream = assembly.GetManifestResourceStream(
+ "KeePass2PCL.Test.UWP.TestData.1.key");
+ using (var reader = new BinaryReader(stream))
+ using (var fileWriter = new BinaryWriter(fileStream))
+ {
+ fileWriter.Write(reader.ReadBytes((int)stream.Length));
+ }
+
+ IFile file = testData.CreateFileAsync("1key.kdbx",
+ CreationCollisionOption.ReplaceExisting).Result;
+ fileStream = file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite).Result;
+ assembly = typeof(PwDatabaseTests).GetTypeInfo().Assembly;
+ stream = assembly.GetManifestResourceStream(
+ "KeePass2PCL.Test.UWP.TestData.1key.kdbx");
+ using (var reader = new BinaryReader(stream))
+ using (var fileWriter = new BinaryWriter(fileStream))
+ {
+ fileWriter.Write(reader.ReadBytes((int)stream.Length));
+ }
+
+ var ci = new IOConnectionInfo();
+ ci.Path = file.Path;
+ var key = new CompositeKey();
+ key.AddUserKey(new KcpKeyFile(keyFile.Path));
+ var db = new PwDatabase();
+ db.Open(ci, key, null);
+ keyFile.DeleteAsync().Wait();
+ file.DeleteAsync().Wait();
+ testData.DeleteAsync().Wait();
+ }
+
+ [TestMethod]
+ public void New_Test()
+ {
+ IFolder folder = SpecialFolder.Current.Local;
+ IFolder testData = folder.CreateFolderAsync("TestData",
+ CreationCollisionOption.OpenIfExists).Result;
+ IFile file = testData.CreateFileAsync("1.kdbx",
+ CreationCollisionOption.ReplaceExisting).Result;
+
+ var ci = new IOConnectionInfo();
+ ci.Path = file.Path;
+ var key = new CompositeKey();
+ key.AddUserKey(new KcpPassword("0"));
+ var db = new PwDatabase();
+ db.New(ci, key);
+ var initialEnitiesCount = db.RootGroup.GetEntriesCount(true);
+ Assert.AreNotEqual(0, initialEnitiesCount);
+ db.Save(null);
+ db.Close();
+ Assert.IsNull(db.RootGroup);
+ db = new PwDatabase();
+ db.Open(ci, key, null);
+ Assert.AreEqual(initialEnitiesCount,
+ db.RootGroup.GetEntriesCount(true));
+ }
+ }
+}
diff --git a/KeePass2PCL.Test.UWP/TestData/1.kdbx b/KeePass2PCL.Test.UWP/TestData/1.kdbx
new file mode 100644
index 0000000..9a6ea8a
Binary files /dev/null and b/KeePass2PCL.Test.UWP/TestData/1.kdbx differ
diff --git a/KeePass2PCL.Test.UWP/TestData/1.key b/KeePass2PCL.Test.UWP/TestData/1.key
new file mode 100644
index 0000000..fcbc781
--- /dev/null
+++ b/KeePass2PCL.Test.UWP/TestData/1.key
@@ -0,0 +1,9 @@
+
+
+
+ 1.00
+
+
+ M+5k7gXYzjN8Vwp5akdSwaPeUhBq0bC0q5qnSYlJmAw=
+
+
diff --git a/KeePass2PCL.Test.UWP/TestData/1key.kdbx b/KeePass2PCL.Test.UWP/TestData/1key.kdbx
new file mode 100644
index 0000000..838ad6c
Binary files /dev/null and b/KeePass2PCL.Test.UWP/TestData/1key.kdbx differ
diff --git a/KeePass2PCL.Test.UWP/UnitTestApp.xaml b/KeePass2PCL.Test.UWP/UnitTestApp.xaml
new file mode 100644
index 0000000..04a2d2b
--- /dev/null
+++ b/KeePass2PCL.Test.UWP/UnitTestApp.xaml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/KeePass2PCL.Test.UWP/UnitTestApp.xaml.cs b/KeePass2PCL.Test.UWP/UnitTestApp.xaml.cs
new file mode 100644
index 0000000..22ee43c
--- /dev/null
+++ b/KeePass2PCL.Test.UWP/UnitTestApp.xaml.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+namespace KeePass2PCL.Test.UWP
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ sealed partial class App : Application
+ {
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ this.Suspending += OnSuspending;
+ }
+
+ ///
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used such as when the application is launched to open a specific file.
+ ///
+ /// Details about the launch request and process.
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
+ {
+
+#if DEBUG
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ this.DebugSettings.EnableFrameRateCounter = true;
+ }
+#endif
+
+ Frame rootFrame = Window.Current.Content as Frame;
+
+ // Do not repeat app initialization when the Window already has content,
+ // just ensure that the window is active
+ if (rootFrame == null)
+ {
+ // Create a Frame to act as the navigation context and navigate to the first page
+ rootFrame = new Frame();
+
+ rootFrame.NavigationFailed += OnNavigationFailed;
+
+ if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
+ {
+ //TODO: Load state from previously suspended application
+ }
+
+ // Place the frame in the current Window
+ Window.Current.Content = rootFrame;
+ }
+
+ Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
+
+ // Ensure the current window is active
+ Window.Current.Activate();
+
+ Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.Run(e.Arguments);
+ }
+
+ ///
+ /// Invoked when Navigation to a certain page fails
+ ///
+ /// The Frame which failed navigation
+ /// Details about the navigation failure
+ void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
+ {
+ throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
+ }
+
+ ///
+ /// Invoked when application execution is being suspended. Application state is saved
+ /// without knowing whether the application will be terminated or resumed with the contents
+ /// of memory still intact.
+ ///
+ /// The source of the suspend request.
+ /// Details about the suspend request.
+ private void OnSuspending(object sender, SuspendingEventArgs e)
+ {
+ var deferral = e.SuspendingOperation.GetDeferral();
+ //TODO: Save application state and stop any background activity
+ deferral.Complete();
+ }
+ }
+}
diff --git a/KeePass2PCL.Test/KeePass2PCL.Test.KeePassLib.csproj b/KeePass2PCL.Test/KeePass2PCL.Test.KeePassLib.csproj
new file mode 100644
index 0000000..a40e2e8
--- /dev/null
+++ b/KeePass2PCL.Test/KeePass2PCL.Test.KeePassLib.csproj
@@ -0,0 +1,65 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {2637FAA9-838C-43AB-81F3-BB231E0E1DCA}
+ Library
+ KeePass2PCL.Test.KeePassLib
+ KeePass2PCL.Test.KeePassLib
+ v4.5
+
+
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;KeePassLib
+ prompt
+ 4
+ false
+
+
+ true
+ bin\Release
+ KeePassLib;
+ prompt
+ 4
+ false
+
+
+
+ ..\packages\Castle.Core.4.1.1\lib\net45\Castle.Core.dll
+
+
+ ..\packages\pt.KeePassLib.2.35.2\lib\net20\KeePassLib.dll
+
+
+ ..\packages\Moq.4.7.99\lib\net45\Moq.dll
+
+
+ ..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test/app.config b/KeePass2PCL.Test/app.config
new file mode 100644
index 0000000..81b66be
--- /dev/null
+++ b/KeePass2PCL.Test/app.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeePass2PCL.Test/packages.config b/KeePass2PCL.Test/packages.config
new file mode 100644
index 0000000..58f1691
--- /dev/null
+++ b/KeePass2PCL.Test/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ModernKeePass.sln b/ModernKeePass.sln
index 4c7e596..afc08f4 100644
--- a/ModernKeePass.sln
+++ b/ModernKeePass.sln
@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePass", "ModernKeeP
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLibPCL", "ModernKeePassLib\ModernKeePassLibPCL.csproj", "{2E710089-9559-4967-846C-E763DD1F3ACB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib.Test", "ModernKeePassLib.Test\ModernKeePassLib.Test.csproj", "{067456C0-086C-46A8-B37F-1405717B7BFC}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -59,6 +61,22 @@ Global
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x64.Build.0 = Release|Any CPU
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x86.ActiveCfg = Release|Any CPU
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x86.Build.0 = Release|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|ARM.Build.0 = Debug|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x64.Build.0 = Debug|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x86.Build.0 = Debug|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|ARM.ActiveCfg = Release|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|ARM.Build.0 = Release|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x64.ActiveCfg = Release|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x64.Build.0 = Release|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x86.ActiveCfg = Release|Any CPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/ModernKeePass/Common/DatabaseHelper.cs b/ModernKeePass/Common/DatabaseHelper.cs
index d0e2ed5..4306b92 100644
--- a/ModernKeePass/Common/DatabaseHelper.cs
+++ b/ModernKeePass/Common/DatabaseHelper.cs
@@ -31,8 +31,11 @@ namespace ModernKeePass.Common
_pwDatabase.Open(IOConnectionInfo.FromFile(databaseFile), key, new NullStatusLogger());
//_pwDatabase.Open(IOConnectionInfo.FromPath(databaseFile.Path), key, new NullStatusLogger());
IsOpen = _pwDatabase.IsOpen;
- Name = databaseFile.DisplayName;
- RootGroup = new GroupVm(_pwDatabase.RootGroup);
+ if (IsOpen)
+ {
+ Name = databaseFile.DisplayName;
+ RootGroup = new GroupVm(_pwDatabase.RootGroup);
+ }
}
catch (ArgumentNullException)
{
diff --git a/ModernKeePass/MainPage.xaml b/ModernKeePass/MainPage.xaml
index 3ecfd71..b0a737e 100644
--- a/ModernKeePass/MainPage.xaml
+++ b/ModernKeePass/MainPage.xaml
@@ -20,7 +20,7 @@
-
+
@@ -37,6 +37,7 @@
New
File
Recent files - Coming soon
+ Url files - Coming soon
@@ -56,6 +57,6 @@
-
+
diff --git a/ModernKeePass/MainPage.xaml.cs b/ModernKeePass/MainPage.xaml.cs
index 979e752..35535fb 100644
--- a/ModernKeePass/MainPage.xaml.cs
+++ b/ModernKeePass/MainPage.xaml.cs
@@ -1,7 +1,7 @@
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
-
+using Windows.UI.Xaml.Navigation;
using ModernKeePass.Pages;
using ModernKeePass.ViewModels;
@@ -48,7 +48,8 @@ namespace ModernKeePass
var homeVm = DataContext as HomeVm;
var app = ((App)Application.Current);
homeVm.ErrorMessage = app.Database.Open(homeVm.Password);
- if (!app.Database.IsOpen) homeVm.NotifyPropertyChanged("ErrorMessage");
+
+ if (!string.IsNullOrEmpty(homeVm.ErrorMessage)) homeVm.NotifyPropertyChanged("ErrorMessage");
else Frame.Navigate(typeof(GroupDetailPage), app.Database.RootGroup);
}
@@ -71,5 +72,15 @@ namespace ModernKeePass
SelectGrid.Visibility = Visibility.Collapsed;
}
}
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ base.OnNavigatedTo(e);
+ var app = (App)Application.Current;
+ if (app.Database == null) return;
+ var homeVm = DataContext as HomeVm;
+ homeVm.IsOpen = app.Database.IsOpen;
+ homeVm.NotifyPropertyChanged("IsOpen");
+ }
}
}
diff --git a/ModernKeePass/ModernKeePass.csproj b/ModernKeePass/ModernKeePass.csproj
index 64ecfb0..55188a3 100644
--- a/ModernKeePass/ModernKeePass.csproj
+++ b/ModernKeePass/ModernKeePass.csproj
@@ -163,8 +163,8 @@
..\packages\Portable.BouncyCastle.1.8.1.1\lib\netstandard1.0\crypto.dll
True
-
- ..\packages\ModernKeePassLibPCL.2.28.1.22258\lib\netstandard1.2\ModernKeePassLibPCL.dll
+
+ ..\packages\ModernKeePassLibPCL.2.28.1.31251\lib\netstandard1.2\ModernKeePassLibPCL.dll
True
diff --git a/ModernKeePass/Pages/GroupDetailPage.xaml b/ModernKeePass/Pages/GroupDetailPage.xaml
index d0f54d1..07fd5e1 100644
--- a/ModernKeePass/Pages/GroupDetailPage.xaml
+++ b/ModernKeePass/Pages/GroupDetailPage.xaml
@@ -65,7 +65,7 @@
-
+
@@ -77,8 +77,6 @@
-
-
diff --git a/ModernKeePass/Pages/GroupDetailPage.xaml.cs b/ModernKeePass/Pages/GroupDetailPage.xaml.cs
index 4f1117c..fa2ad71 100644
--- a/ModernKeePass/Pages/GroupDetailPage.xaml.cs
+++ b/ModernKeePass/Pages/GroupDetailPage.xaml.cs
@@ -89,11 +89,5 @@ namespace ModernKeePass.Pages
var listView = sender as ListView;
Frame.Navigate(typeof(EntryDetailPage), listView.SelectedItem as EntryVm);
}
-
- private void addGroupButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
- {
- var group = DataContext as GroupVm;
- group.AddGroup("New group");
- }
}
}
diff --git a/ModernKeePass/ViewModels/EntryVm.cs b/ModernKeePass/ViewModels/EntryVm.cs
index e1ed8d5..7c6761d 100644
--- a/ModernKeePass/ViewModels/EntryVm.cs
+++ b/ModernKeePass/ViewModels/EntryVm.cs
@@ -5,7 +5,7 @@ namespace ModernKeePass.ViewModels
{
public class EntryVm : INotifyPropertyChanged
{
- public string Title { get; private set; }
+ public string Title { get; set; }
public string UserName { get; private set; }
public string Password { get; private set; }
public string URL { get; private set; }
diff --git a/ModernKeePass/ViewModels/GroupVm.cs b/ModernKeePass/ViewModels/GroupVm.cs
index aba6fb3..624f12f 100644
--- a/ModernKeePass/ViewModels/GroupVm.cs
+++ b/ModernKeePass/ViewModels/GroupVm.cs
@@ -32,27 +32,34 @@ namespace ModernKeePass.ViewModels
Name = "GroupName";
Entries = new ObservableCollection();
Groups = new ObservableCollection();
-
}
- public GroupVm(PwGroup group)
+ public GroupVm(PwGroup pwGroup)
{
- _pwGroup = group;
- Name = group.Name;
- Entries = new ObservableCollection(group.Entries.Select(e => new EntryVm(e)));
- Groups = new ObservableCollection(group.Groups.Select(g => new GroupVm(g)));
+ _pwGroup = pwGroup;
+ Name = pwGroup.Name;
+ Entries = new ObservableCollection(pwGroup.Entries.Select(e => new EntryVm(e)));
+ //Entries.Insert(0, new EntryVm { Title = " + New entry" });
+ Groups = new ObservableCollection(pwGroup.Groups.Select(g => new GroupVm(g)));
+ //Groups.Insert(0, new GroupVm { Name = " + New group" });
}
- public void AddGroup(string title)
+ public void CreateNewGroup(string title)
{
- var pwGroup = new PwGroup
- {
- Name = title
- };
+ var pwGroup = new PwGroup(true, true, title, PwIcon.Folder);
+ _pwGroup.AddGroup(pwGroup, true);
Groups.Add(new GroupVm(pwGroup));
NotifyPropertyChanged("Groups");
- this._pwGroup.Groups.Add(pwGroup);
}
+
+ public void CreateNewEntry(string title)
+ {
+ var pwEntry = new PwEntry(true, true);
+ _pwGroup.AddEntry(pwEntry, true);
+ Entries.Add(new EntryVm(pwEntry));
+ NotifyPropertyChanged("Entries");
+ }
+
public event PropertyChangedEventHandler PropertyChanged;
diff --git a/ModernKeePass/ViewModels/HomeVm.cs b/ModernKeePass/ViewModels/HomeVm.cs
index 67b781d..a2f71f9 100644
--- a/ModernKeePass/ViewModels/HomeVm.cs
+++ b/ModernKeePass/ViewModels/HomeVm.cs
@@ -8,6 +8,7 @@ namespace ModernKeePass.ViewModels
public string Password { get; set; }
public Visibility Visibility { get; set; }
public string ErrorMessage { get; set; }
+ public bool IsOpen { get; set; }
public HomeVm()
{
diff --git a/ModernKeePass/packages.config b/ModernKeePass/packages.config
index 2843967..8a95652 100644
--- a/ModernKeePass/packages.config
+++ b/ModernKeePass/packages.config
@@ -4,7 +4,7 @@
-
+
diff --git a/ModernKeePassLib.Test/Cryptography/Cipher/StandardAesEngineTests.cs b/ModernKeePassLib.Test/Cryptography/Cipher/StandardAesEngineTests.cs
new file mode 100644
index 0000000..81ac274
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/Cipher/StandardAesEngineTests.cs
@@ -0,0 +1,65 @@
+using System;
+using System.IO;
+
+#if KeePassLib
+using KeePassLib.Cryptography.Cipher;
+#else
+using ModernKeePassLibPCL.Cryptography.Cipher;
+#endif
+
+using NUnit.Framework;
+
+namespace ModernKeePassLib.Test.Shared.Cryptography.Cipher
+{
+ [TestFixture ()]
+ public class StandardAesEngineTests
+ {
+ [Test ()]
+ public void TestEncryptStream ()
+ {
+ // Test vector (official ECB test vector #356)
+ var pbIV = new byte[16];
+ var pbTestKey = new byte[32];
+ var pbTestData = new byte[16];
+ var pbReferenceCT = new byte[16] {
+ 0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
+ 0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7
+ };
+
+ pbTestData[0] = 0x04;
+
+ var outStream = new MemoryStream (new byte[16]);
+ var aes = new StandardAesEngine ();
+ var inStream = aes.EncryptStream (outStream, pbTestKey, pbIV);
+ new BinaryWriter (inStream).Write (pbTestData);
+ Assert.That (outStream.Position, Is.EqualTo (16));
+ outStream.Position = 0;
+ var outBytes = new BinaryReader (outStream).ReadBytes (16);
+ Assert.That(outBytes, Is.EqualTo (pbReferenceCT));
+ }
+
+ [Test ()]
+ public void TestDecryptStream ()
+ {
+ // Test vector (official ECB test vector #356)
+ var pbIV = new byte[16];
+ var pbTestKey = new byte[32];
+ var pbTestData = new byte[16];
+ var pbReferenceCT = new byte[16] {
+ 0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
+ 0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7
+ };
+
+ pbTestData[0] = 0x04;
+
+ // Possible Mono Bug? This only works with size >= 48
+ var inStream = new MemoryStream (new byte[48]);
+ inStream.Write (pbReferenceCT, 0, pbReferenceCT.Length);
+ inStream.Position = 0;
+ var aes = new StandardAesEngine ();
+ var outStream = aes.DecryptStream (inStream, pbTestKey, pbIV);
+ var outBytes = new BinaryReader (outStream).ReadBytes (16);
+ Assert.That(outBytes, Is.EqualTo (pbTestData));
+ }
+ }
+}
diff --git a/ModernKeePassLib.Test/Cryptography/CryptoRandomStreamTests.cs b/ModernKeePassLib.Test/Cryptography/CryptoRandomStreamTests.cs
new file mode 100644
index 0000000..e71feb0
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/CryptoRandomStreamTests.cs
@@ -0,0 +1,60 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Cryptography;
+#else
+using ModernKeePassLibPCL.Cryptography;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Cryptography
+{
+ [TestFixture ()]
+ public class CryptoRandomStreamTests
+ {
+ void TestGetRandomBytes(CryptoRandomStream stream)
+ {
+ const uint length = 16;
+ var bytes1 = stream.GetRandomBytes (length);
+ Assert.That (bytes1.Length, Is.EqualTo (length));
+ var bytes2 = stream.GetRandomBytes (length);
+ Assert.That (bytes2, Is.Not.EqualTo (bytes1));
+ }
+
+ [Test ()]
+ public void TestGetRandomBytesCrsAlgorithmSalsa20 ()
+ {
+ var stream = new CryptoRandomStream (CrsAlgorithm.Salsa20, new byte[16]);
+ TestGetRandomBytes (stream);
+ }
+
+ [Test ()]
+ public void TestGetRandomBytesCrsAlgorithmArcFourVariant ()
+ {
+ var stream = new CryptoRandomStream (CrsAlgorithm.ArcFourVariant, new byte[16]);
+ TestGetRandomBytes (stream);
+ }
+
+ void TestGetRandomInt64 (CryptoRandomStream stream)
+ {
+ var value1 = stream.GetRandomUInt64 ();
+ var value2 = stream.GetRandomUInt64 ();
+ Assert.That (value2, Is.Not.EqualTo (value1));
+ }
+
+ [Test ()]
+ public void TestGetRandomInt64AlgorithmSalsa20 ()
+ {
+ var stream = new CryptoRandomStream (CrsAlgorithm.Salsa20, new byte[16]);
+ TestGetRandomInt64 (stream);
+ }
+
+ [Test ()]
+ public void TestGetRandomInt64AlgorithmArcFourVariant ()
+ {
+ var stream = new CryptoRandomStream (CrsAlgorithm.ArcFourVariant, new byte[16]);
+ TestGetRandomInt64 (stream);
+ }
+ }
+}
+
diff --git a/ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs b/ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
new file mode 100644
index 0000000..e1d3eae
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
@@ -0,0 +1,44 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Cryptography;
+#else
+using ModernKeePassLibPCL.Cryptography;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Cryptography
+{
+ [TestFixture ()]
+ public class CryptoRandomTests
+ {
+ [Test ()]
+ public void TestAddEntropy ()
+ {
+ // just making sure it does not throw an exception
+ CryptoRandom.Instance.AddEntropy (new byte[1]);
+ }
+
+ [Test ()]
+ public void TestGetRandomBytes ()
+ {
+ const int length = 32;
+ var bytes1 = CryptoRandom.Instance.GetRandomBytes (length);
+ Assert.That (bytes1.Length, Is.EqualTo (length));
+ var bytes2 = CryptoRandom.Instance.GetRandomBytes (length);
+ Assert.That (bytes2, Is.Not.EqualTo (bytes1));
+ }
+
+ [Test ()]
+ public void TestGeneratedBytesCount ()
+ {
+ const int length = 1;
+ CryptoRandom.Instance.GetRandomBytes (length);
+ var count1 = CryptoRandom.Instance.GeneratedBytesCount;
+ CryptoRandom.Instance.GetRandomBytes (length);
+ var count2 = CryptoRandom.Instance.GeneratedBytesCount;
+ Assert.That (count2, Is.GreaterThan (count1));
+ }
+ }
+}
+
diff --git a/ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs b/ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
new file mode 100644
index 0000000..a1d1b2a
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
@@ -0,0 +1,77 @@
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Text;
+
+#if KeePassLib
+using KeePassLib.Cryptography;
+#else
+using ModernKeePassLibPCL.Cryptography;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Cryptography
+{
+ [TestFixture ()]
+ public class HashingStreamExTests
+ {
+ const string data = "test";
+
+ // The expected hash includes the \n added by WriteLine
+ static readonly byte[] sha256HashOfData = {
+ 0xf2, 0xca, 0x1b, 0xb6, 0xc7, 0xe9, 0x07, 0xd0,
+ 0x6d, 0xaf, 0xe4, 0x68, 0x7e, 0x57, 0x9f, 0xce,
+ 0x76, 0xb3, 0x7e, 0x4e, 0x93, 0xb7, 0x60, 0x50,
+ 0x22, 0xda, 0x52, 0xe6, 0xcc, 0xc2, 0x6f, 0xd2
+ };
+
+ [Test ()]
+ public void TestRead ()
+ {
+ // if we use larger size, StreamReader will read past newline and cause bad hash
+ var bytes = new byte[data.Length + 1];
+ using (var ms = new MemoryStream (bytes)) {
+ using (var sw = new StreamWriter (ms)) {
+ // set NewLine to ensure we don't run into cross-platform issues on Windows
+ sw.NewLine = "\n";
+ sw.WriteLine (data);
+ }
+ }
+ using (var ms = new MemoryStream (bytes)) {
+ using (var hs = new HashingStreamEx (ms, false, null)) {
+ using (var sr = new StreamReader (hs)) {
+ var read = sr.ReadLine ();
+ Assert.That (read, Is.EqualTo (data));
+ }
+ // When the StreamReader is disposed, it calls Dispose on the
+ //HasingStreamEx, which computes the hash.
+ Assert.That (hs.Hash, Is.EqualTo (sha256HashOfData));
+ }
+ }
+ }
+
+ [Test ()]
+ public void TestWrite ()
+ {
+ var bytes = new byte[16];
+ using (var ms = new MemoryStream (bytes)) {
+ using (var hs = new HashingStreamEx (ms, true, null)) {
+ using (var sw = new StreamWriter (hs)) {
+ // set NewLine to ensure we don't run into cross-platform issues on Windows
+ sw.NewLine = "\n";
+ sw.WriteLine (data);
+ }
+ // When the StreamWriter is disposed, it calls Dispose on the
+ //HasingStreamEx, which computes the hash.
+ Assert.That (hs.Hash, Is.EqualTo (sha256HashOfData));
+ }
+ }
+ using (var ms = new MemoryStream (bytes)) {
+ using (var sr = new StreamReader (ms)) {
+ var read = sr.ReadLine ();
+ Assert.That (read, Is.EqualTo (data));
+ }
+ }
+ }
+ }
+}
+
diff --git a/ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs b/ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
new file mode 100644
index 0000000..563c29d
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
@@ -0,0 +1,36 @@
+using NUnit.Framework;
+using System;
+using System.Text;
+
+#if KeePassLib
+using KeePassLib.Cryptography;
+#else
+using ModernKeePassLibPCL.Cryptography;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Cryptography
+{
+ [TestFixture ()]
+ public class HmacOtpTests
+ {
+ // Using the test case from Appendix D of RFC 4226
+
+ const string secret = "12345678901234567890";
+ static readonly string[] expectedHOTP = new string[] {
+ "755224", "287082", "359152", "969429", "338314",
+ "254676", "287922", "162583", "399871", "520489"
+ };
+
+ [Test ()]
+ public void TestGenerate ()
+ {
+ var secretBytes = Encoding.UTF8.GetBytes (secret);
+
+ for (ulong i = 0; i < 10; i++) {
+ var hotp = HmacOtp.Generate (secretBytes, i, 6, false, -1);
+ Assert.That (hotp, Is.EqualTo (expectedHOTP[i]));
+ }
+ }
+ }
+}
+
diff --git a/ModernKeePassLib.Test/Keys/CompositeKeyTests.cs b/ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
new file mode 100644
index 0000000..a5a4b4a
--- /dev/null
+++ b/ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
@@ -0,0 +1,34 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Keys;
+#else
+using ModernKeePassLibPCL.Keys;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Keys
+{
+ [TestFixture ()]
+ public class CompositeKeyTests
+ {
+ [Test ()]
+ public void TestGenerateKey32 ()
+ {
+ var originalKey = new byte[32];
+ var expectedKey = new byte[32] {
+ 0xF0, 0xED, 0x57, 0xD5, 0xF0, 0xDA, 0xF3, 0x47,
+ 0x90, 0xD0, 0xDB, 0x43, 0x25, 0xC6, 0x81, 0x2C,
+ 0x81, 0x6A, 0x0D, 0x94, 0x96, 0xA9, 0x03, 0xE1,
+ 0x20, 0xD4, 0x3A, 0x3E, 0x45, 0xAD, 0x02, 0x65
+ };
+ const ulong rounds = 1;
+
+ var composite = new CompositeKey ();
+ var key = composite.GenerateKey32 (originalKey, rounds);
+ Assert.That (key, Is.Not.Null);
+ var keyData = key.ReadData ();
+ Assert.That (keyData, Is.EqualTo (expectedKey));
+ }
+ }
+}
diff --git a/ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs b/ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
new file mode 100644
index 0000000..62ad9a2
--- /dev/null
+++ b/ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
@@ -0,0 +1,39 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Keys;
+#else
+using ModernKeePassLibPCL.Keys;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Keys
+{
+ [TestFixture ()]
+ public class KcpCustomKeyTests
+ {
+ static readonly byte[] testData = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ [Test ()]
+ public void TestConstruct ()
+ {
+ var expectedHash = new byte[32] {
+ 0xAF, 0x55, 0x70, 0xF5, 0xA1, 0x81, 0x0B, 0x7A,
+ 0xF7, 0x8C, 0xAF, 0x4B, 0xC7, 0x0A, 0x66, 0x0F,
+ 0x0D, 0xF5, 0x1E, 0x42, 0xBA, 0xF9, 0x1D, 0x4D,
+ 0xE5, 0xB2, 0x32, 0x8D, 0xE0, 0xE8, 0x3D, 0xFC
+ };
+
+ var key = new KcpCustomKey ("test1", testData, false);
+ var keyData = key.KeyData.ReadData ();
+ Assert.That (keyData, Is.EqualTo (testData));
+
+ key = new KcpCustomKey ("test2", testData, true);
+ keyData = key.KeyData.ReadData ();
+ Assert.That (keyData, Is.EqualTo (expectedHash));
+ }
+ }
+}
+
diff --git a/ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs b/ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs
new file mode 100644
index 0000000..0cd3053
--- /dev/null
+++ b/ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs
@@ -0,0 +1,76 @@
+using NUnit.Framework;
+using System;
+using System.IO;
+
+#if KeePassLib
+using KeePassLib.Keys;
+#else
+using ModernKeePassLibPCL.Keys;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Keys
+{
+ [TestFixture ()]
+ public class KcpKeyFileTests
+ {
+ const string testCreateFile = "TestCreate.xml";
+ const string testKey = "0123456789";
+
+ const string expectedFileStart =
+ "\r\n" +
+ "\r\n" +
+ "\t\r\n" +
+ "\t\t1.00\r\n" +
+ "\t\r\n" +
+ "\t\r\n" +
+ "\t\t";
+
+ const string expectedFileEnd = "\t\r\n" +
+ "\r\n";
+
+ [Test ()]
+ public void TestConstruct ()
+ {
+ var expectedKeyData = new byte[32] {
+ 0xC1, 0xB1, 0x12, 0x77, 0x23, 0xB8, 0x99, 0xB8,
+ 0xB9, 0x3B, 0x1B, 0xFF, 0x6C, 0xBE, 0xA1, 0x5B,
+ 0x8B, 0x99, 0xAC, 0xBD, 0x99, 0x51, 0x85, 0x95,
+ 0x31, 0xAA, 0x14, 0x3D, 0x95, 0xBF, 0x63, 0xFF
+ };
+
+ var fullPath = Path.Combine(Path.GetTempPath(), testCreateFile);
+ using (var fs = new FileStream(fullPath, FileMode.Create)) {
+ using (var sw = new StreamWriter(fs)) {
+ sw.Write (expectedFileStart);
+ sw.Write (testKey);
+ sw.Write (expectedFileEnd);
+ }
+ }
+
+ try {
+ var keyFile = new KcpKeyFile (fullPath);
+ var keyData = keyFile.KeyData.ReadData ();
+ Assert.That (keyData, Is.EqualTo (expectedKeyData));
+ } finally {
+ File.Delete (fullPath);
+ }
+ }
+
+ [Test ()]
+ public void TestCreate ()
+ {
+ var fullPath = Path.Combine(Path.GetTempPath(), testCreateFile);
+ File.Create(fullPath).Close();
+ KcpKeyFile.Create (fullPath, null);
+ try {
+ var fileContents = File.ReadAllText (fullPath);
+ Assert.That (fileContents.Length, Is.EqualTo (187));
+ Assert.That (fileContents, Does.StartWith (expectedFileStart));
+ Assert.That (fileContents, Does.EndWith (expectedFileEnd));
+ } finally {
+ File.Delete (fullPath);
+ }
+ }
+ }
+}
+
diff --git a/ModernKeePassLib.Test/Keys/KcpPasswordTests.cs b/ModernKeePassLib.Test/Keys/KcpPasswordTests.cs
new file mode 100644
index 0000000..779115b
--- /dev/null
+++ b/ModernKeePassLib.Test/Keys/KcpPasswordTests.cs
@@ -0,0 +1,33 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Keys;
+#else
+using ModernKeePassLibPCL.Keys;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Keys
+{
+ [TestFixture ()]
+ public class KcpPasswordTests
+ {
+ const string testPassword = "password";
+
+ [Test ()]
+ public void TestConstruct ()
+ {
+ var expectedHash = new byte[32] {
+ 0x5E, 0x88, 0x48, 0x98, 0xDA, 0x28, 0x04, 0x71,
+ 0x51, 0xD0, 0xE5, 0x6F, 0x8D, 0xC6, 0x29, 0x27,
+ 0x73, 0x60, 0x3D, 0x0D, 0x6A, 0xAB, 0xBD, 0xD6,
+ 0x2A, 0x11, 0xEF, 0x72, 0x1D, 0x15, 0x42, 0xD8
+ };
+
+ var key = new KcpPassword (testPassword);
+ var keyData = key.KeyData.ReadData ();
+ Assert.That (keyData, Is.EqualTo (expectedHash));
+ }
+ }
+}
+
diff --git a/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj b/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj
new file mode 100644
index 0000000..73a6a5b
--- /dev/null
+++ b/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj
@@ -0,0 +1,124 @@
+
+
+
+ Debug
+ AnyCPU
+ {067456C0-086C-46A8-B37F-1405717B7BFC}
+ Library
+ Properties
+ ModernKeePassLib.Test
+ ModernKeePassLib.Test
+ v4.6.2
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\ModernKeePassLibPCL.2.28.1.32947\lib\portable46-net451+win81+wpa81\ModernKeePassLibPCL.dll
+ True
+
+
+ ..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
+ True
+
+
+ ..\packages\PCLCrypto.2.0.147\lib\net45\PCLCrypto.dll
+ True
+
+
+ ..\packages\PCLStorage.1.0.2\lib\net45\PCLStorage.dll
+ True
+
+
+ ..\packages\PCLStorage.1.0.2\lib\net45\PCLStorage.Abstractions.dll
+ True
+
+
+ ..\packages\PInvoke.BCrypt.0.5.97\lib\net45\PInvoke.BCrypt.dll
+ True
+
+
+ ..\packages\PInvoke.Kernel32.0.5.97\lib\net45\PInvoke.Kernel32.dll
+ True
+
+
+ ..\packages\PInvoke.NCrypt.0.5.97\lib\net45\PInvoke.NCrypt.dll
+ True
+
+
+ ..\packages\PInvoke.Windows.Core.0.5.97\lib\net35\PInvoke.Windows.Core.dll
+ True
+
+
+ ..\packages\Splat.2.0.0\lib\Net45\Splat.dll
+ True
+
+
+
+
+
+
+
+ False
+ ..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.1\System.Runtime.WindowsRuntime.dll
+
+
+ ..\packages\Validation.2.4.15\lib\net45\Validation.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/ModernKeePassLib.Test/Properties/AssemblyInfo.cs b/ModernKeePassLib.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f71cb15
--- /dev/null
+++ b/ModernKeePassLib.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 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("ModernKeePassLib.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ModernKeePassLib.Test")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("067456c0-086c-46a8-b37f-1405717b7bfc")]
+
+// 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")]
diff --git a/ModernKeePassLib.Test/Serialization/HashedBlockStreamTests.cs b/ModernKeePassLib.Test/Serialization/HashedBlockStreamTests.cs
new file mode 100644
index 0000000..07f3ba4
--- /dev/null
+++ b/ModernKeePassLib.Test/Serialization/HashedBlockStreamTests.cs
@@ -0,0 +1,71 @@
+using NUnit.Framework;
+using System;
+using System.IO;
+
+#if KeePassLib
+using KeePassLib.Serialization;
+#else
+using ModernKeePassLibPCL.Serialization;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Serialization
+{
+ [TestFixture ()]
+ public class HashedBlockStreamTests
+ {
+ static readonly byte[] data = new byte[16];
+
+ static readonly byte[] hashStreamData = new byte[] {
+ // The first 4 bytes are an integer indicating the block index
+ 0x00, 0x00, 0x00, 0x00,
+ // Then the SHA-256 hash of the data
+ 0x37, 0x47, 0x08, 0xFF, 0xF7, 0x71, 0x9D, 0xD5,
+ 0x97, 0x9E, 0xC8, 0x75, 0xD5, 0x6C, 0xD2, 0x28,
+ 0x6F, 0x6D, 0x3C, 0xF7, 0xEC, 0x31, 0x7A, 0x3B,
+ 0x25, 0x63, 0x2A, 0xAB, 0x28, 0xEC, 0x37, 0xBB,
+ // then an integer that is the length of the data
+ 0x10, 0x00, 0x00, 0x00,
+ // and finally the data itself
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Next, a terminating block
+ 0x01, 0x00, 0x00, 0x00,
+ // terminating block is indicated by a hash of all 0s...
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // ...and by a size of 0
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ [Test ()]
+ public void TestRead ()
+ {
+ using (var ms = new MemoryStream (hashStreamData)) {
+ using (var hbs = new HashedBlockStream (ms, false)) {
+ using (var br = new BinaryReader(hbs)) {
+ var bytes = br.ReadBytes (data.Length);
+ Assert.That (bytes, Is.EqualTo (data));
+ Assert.That (() => br.ReadByte (), Throws.InstanceOf ());
+ }
+ }
+ }
+ }
+
+ [Test ()]
+ public void TestWrite ()
+ {
+ var buffer = new byte[hashStreamData.Length];
+ using (var ms = new MemoryStream (buffer)) {
+ using (var hbs = new HashedBlockStream (ms, true)) {
+ using (var bw = new BinaryWriter(hbs)) {
+ bw.Write (data);
+ }
+ }
+ Assert.That (buffer, Is.EqualTo (hashStreamData));
+ }
+ }
+ }
+}
+
diff --git a/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs b/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs
new file mode 100644
index 0000000..861e2dc
--- /dev/null
+++ b/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs
@@ -0,0 +1,182 @@
+using NUnit.Framework;
+using System;
+using System.Drawing;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using Windows.UI;
+#if KeePassLib
+using KeePassLib;
+using KeePassLib.Keys;
+using KeePassLib.Security;
+using KeePassLib.Serialization;
+using KeePassLib.Collections;
+#else
+using ModernKeePassLibPCL;
+using ModernKeePassLibPCL.Keys;
+using ModernKeePassLibPCL.Security;
+using ModernKeePassLibPCL.Serialization;
+using ModernKeePassLibPCL.Collections;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Serialization
+{
+ [TestFixture()]
+ public class KdbxFileTests
+ {
+ const string testLocalizedAppName = "My Localized App Name";
+
+ const string testDatabaseName = "My Database Name";
+ const string testDatabaseDescription = "My Database Description";
+ const string testDefaultUserName = "My Default User Name";
+ const string testColor = "#FF0000"; // Red
+
+ const string testRootGroupName = "My Root Group Name";
+ const string testRootGroupNotes = "My Root Group Notes";
+ const string testRootGroupDefaultAutoTypeSequence = "My Root Group Default Auto Type Sequence";
+
+ const string testDatabase = "\r\n" +
+ "\r\n" +
+ "\t\r\n" +
+ "\t\t" + testLocalizedAppName + "\r\n" +
+ "\t\t" + testDatabaseName + "\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t" + testDatabaseDescription + "\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t" + testDefaultUserName + "\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t365\r\n" +
+ //"\t\t" + testColor + "\r\n" +
+ "\t\t\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t-1\r\n" +
+ "\t\t-1\r\n" +
+ "\t\t\r\n" +
+ "\t\t\tFalse\r\n" +
+ "\t\t\tFalse\r\n" +
+ "\t\t\tTrue\r\n" +
+ "\t\t\tFalse\r\n" +
+ "\t\t\tFalse\r\n" +
+ "\t\t\r\n" +
+ "\t\tTrue\r\n" +
+ "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t10\r\n" +
+ "\t\t6291456\r\n" +
+ "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t\r\n" +
+ "\t\t\r\n" +
+ "\t\r\n" +
+ "\t\r\n" +
+ "\t\t\r\n" +
+ "\t\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t\t" + testRootGroupName + "\r\n" +
+ "\t\t\t" + testRootGroupNotes + "\r\n" +
+ "\t\t\t49\r\n" +
+ "\t\t\t\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\tFalse\r\n" +
+ "\t\t\t\t0\r\n" +
+ "\t\t\t\t2015-03-14T03:15:26Z\r\n" +
+ "\t\t\t\r\n" +
+ "\t\t\tTrue\r\n" +
+ "\t\t\t" + testRootGroupDefaultAutoTypeSequence + "\r\n" +
+ "\t\t\tnull\r\n" +
+ "\t\t\tnull\r\n" +
+ "\t\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" +
+ "\t\t\r\n" +
+ "\t\t\r\n" +
+ "\t\r\n" +
+ "";
+
+ const string testDate = "2015-03-14T03:15:26Z";
+
+ [Test()]
+ public void TestLoad()
+ {
+ var database = new PwDatabase();
+ using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(testDatabase)))
+ {
+ var file = new KdbxFile(database);
+ file.Load(ms, KdbxFormat.PlainXml, null);
+ }
+ //Assert.That(database.Color.ToArgb(), Is.EqualTo(Color.Red.ToArgb()));
+ Assert.That(database.Compression, Is.EqualTo(PwCompressionAlgorithm.GZip));
+ //Assert.That (database.CustomData, Is.EqualTo ());
+ Assert.That(database.CustomIcons, Is.Empty);
+ }
+
+ [Test()]
+ public void TestSave()
+ {
+ var buffer = new byte[4096];
+ using (var ms = new MemoryStream(buffer))
+ {
+ var database = new PwDatabase();
+ database.New(new IOConnectionInfo(), new CompositeKey());
+ var date = DateTime.Parse(testDate);
+ PwDatabase.LocalizedAppName = testLocalizedAppName;
+ database.Name = testDatabaseName;
+ database.NameChanged = date;
+ database.Description = testDatabaseDescription;
+ database.DescriptionChanged = date;
+ database.DefaultUserName = testDefaultUserName;
+ database.DefaultUserNameChanged = date;
+ //database.Color = Color.Red;
+ database.MasterKeyChanged = date;
+ database.RecycleBinChanged = date;
+ database.EntryTemplatesGroupChanged = date;
+ database.RootGroup.Uuid = PwUuid.Zero;
+ database.RootGroup.Name = testRootGroupName;
+ database.RootGroup.Notes = testRootGroupNotes;
+ database.RootGroup.DefaultAutoTypeSequence = testRootGroupDefaultAutoTypeSequence;
+ database.RootGroup.CreationTime = date;
+ database.RootGroup.LastModificationTime = date;
+ database.RootGroup.LastAccessTime = date;
+ database.RootGroup.ExpiryTime = date;
+ database.RootGroup.LocationChanged = date;
+ var file = new KdbxFile(database);
+ file.Save(ms, null, KdbxFormat.PlainXml, null);
+ }
+ var fileContents = Encoding.UTF8.GetString(buffer).Replace("\0", "");
+ if (typeof(KdbxFile).Namespace.StartsWith("KeePassLib.")
+ && Environment.OSVersion.Platform != PlatformID.Win32NT)
+ {
+ // Upstream KeePassLib does not specify line endings for XmlTextWriter,
+ // so it uses native line endings.
+ fileContents = fileContents.Replace("\n", "\r\n");
+ }
+ Assert.That(fileContents, Is.EqualTo(testDatabase));
+ }
+
+ [Test]
+ public void TestSearch()
+ {
+ var database = new PwDatabase();
+ using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(testDatabase)))
+ {
+ var file = new KdbxFile(database);
+ file.Load(ms, KdbxFormat.PlainXml, null);
+ }
+ var sp = new SearchParameters()
+ {
+ SearchString = "sfsoiwsefsi"
+ };
+ var listStorage = new PwObjectList();
+ database.RootGroup.SearchEntries(sp, listStorage);
+ Assert.AreEqual(0U, listStorage.UCount);
+ var entry = new PwEntry(true, true);
+ entry.Strings.Set("Title", new ProtectedString(false, "NaMe"));
+ database.RootGroup.AddEntry(entry, true);
+ sp.SearchString = "name";
+ database.RootGroup.SearchEntries(sp, listStorage);
+ Assert.AreEqual(1U, listStorage.UCount);
+ }
+ }
+}
diff --git a/ModernKeePassLib.Test/Utility/GfxUtilTests.cs b/ModernKeePassLib.Test/Utility/GfxUtilTests.cs
new file mode 100644
index 0000000..66fd853
--- /dev/null
+++ b/ModernKeePassLib.Test/Utility/GfxUtilTests.cs
@@ -0,0 +1,32 @@
+using NUnit.Framework;
+using System;
+
+#if KeePassLib
+using KeePassLib.Utility;
+#else
+using Splat;
+using ModernKeePassLibPCL.Utility;
+#endif
+
+namespace ModernKeePassLib.Test.Shared.Utility
+{
+ [TestFixture ()]
+ public class GfxUtilTests
+ {
+ // 16x16 all white PNG file, base64 encoded
+ const string testImageData =
+ "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAA" +
+ "LEwEAmpwYAAAAB3RJTUUH3wMOFgIgmTCUMQAAABl0RVh0Q29tbWVudABDcmVhdG" +
+ "VkIHdpdGggR0lNUFeBDhcAAAAaSURBVCjPY/z//z8DKYCJgUQwqmFUw9DRAABVb" +
+ "QMdny4VogAAAABJRU5ErkJggg==";
+
+ [Test ()]
+ public void TestLoadImage ()
+ {
+ var testData = Convert.FromBase64String (testImageData);
+ var image = GfxUtil.LoadImage (testData);
+ Assert.That (image.Width, Is.EqualTo (16));
+ Assert.That (image.Height, Is.EqualTo (16));
+ }
+ }
+}
diff --git a/ModernKeePassLib.Test/app.config b/ModernKeePassLib.Test/app.config
new file mode 100644
index 0000000..869e12a
--- /dev/null
+++ b/ModernKeePassLib.Test/app.config
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ModernKeePassLib.Test/packages.config b/ModernKeePassLib.Test/packages.config
new file mode 100644
index 0000000..8b06047
--- /dev/null
+++ b/ModernKeePassLib.Test/packages.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ModernKeePassLib/Keys/KcpKeyFile.cs b/ModernKeePassLib/Keys/KcpKeyFile.cs
index aa3e450..0959f34 100644
--- a/ModernKeePassLib/Keys/KcpKeyFile.cs
+++ b/ModernKeePassLib/Keys/KcpKeyFile.cs
@@ -87,9 +87,9 @@ namespace ModernKeePassLibPCL.Keys
Construct(iocKeyFile, bThrowIfDbFile);
}
- private async void Construct(IOConnectionInfo iocFile, bool bThrowIfDbFile)
+ private void Construct(IOConnectionInfo iocFile, bool bThrowIfDbFile)
{
- byte[] pbFileData = await IOConnection.ReadFile(iocFile);
+ byte[] pbFileData = IOConnection.ReadFile(iocFile);
if(pbFileData == null) throw new FileNotFoundException();
if(bThrowIfDbFile && (pbFileData.Length >= 8))
@@ -310,7 +310,7 @@ namespace ModernKeePassLibPCL.Keys
return pbKeyData;
}
- private static async void CreateXmlKeyFile(string strFile, byte[] pbKeyData)
+ private static void CreateXmlKeyFile(string strFile, byte[] pbKeyData)
{
Debug.Assert(strFile != null);
if(strFile == null) throw new ArgumentNullException("strFile");
@@ -318,7 +318,7 @@ namespace ModernKeePassLibPCL.Keys
if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
- var sOut = await IOConnection.OpenWrite(ioc);
+ var sOut = IOConnection.OpenWrite(ioc);
#if ModernKeePassLibPCL
var settings = new XmlWriterSettings() { Encoding = StrUtil.Utf8 };
diff --git a/ModernKeePassLib/PwDatabase.cs b/ModernKeePassLib/PwDatabase.cs
index fccda81..0a15333 100644
--- a/ModernKeePassLib/PwDatabase.cs
+++ b/ModernKeePassLib/PwDatabase.cs
@@ -566,7 +566,7 @@ namespace ModernKeePassLibPCL
/// IO connection to load the database from.
/// Key used to open the specified database.
/// Logger, which gets all status messages.
- public async void Open(IOConnectionInfo ioSource, CompositeKey pwKey,
+ public void Open(IOConnectionInfo ioSource, CompositeKey pwKey,
IStatusLogger slLogger)
{
Debug.Assert(ioSource != null);
@@ -589,7 +589,7 @@ namespace ModernKeePassLibPCL
KdbxFile kdbx = new KdbxFile(this);
kdbx.DetachBinaries = m_strDetachBins;
- var s = await IOConnection.OpenRead(ioSource);
+ var s = IOConnection.OpenRead(ioSource);
kdbx.Load(s, KdbxFormat.Default, slLogger);
s.Dispose();
@@ -612,7 +612,7 @@ namespace ModernKeePassLibPCL
/// it has been opened from.
///
/// Logger that recieves status information.
- public async void Save(IStatusLogger slLogger)
+ public void Save(IStatusLogger slLogger)
{
Debug.Assert(ValidateUuidUniqueness());
@@ -622,7 +622,7 @@ namespace ModernKeePassLibPCL
{
FileTransactionEx ft = new FileTransactionEx(m_ioSource,
m_bUseFileTransactions);
- var s = await ft.OpenWrite();
+ var s = ft.OpenWrite();
KdbxFile kdb = new KdbxFile(this);
kdb.Save(s, null, KdbxFormat.Default, slLogger);
diff --git a/ModernKeePassLib/Serialization/FileLock.cs b/ModernKeePassLib/Serialization/FileLock.cs
index 6a11e6e..c4d318a 100644
--- a/ModernKeePassLib/Serialization/FileLock.cs
+++ b/ModernKeePassLib/Serialization/FileLock.cs
@@ -123,9 +123,9 @@ namespace ModernKeePassLibPCL.Serialization
return sb.ToString();
}
- public static async Task Load(IOConnectionInfo iocLockFile)
+ public static LockFileInfo Load(IOConnectionInfo iocLockFile)
{
- using (var s = await IOConnection.OpenRead(iocLockFile))
+ using (var s = IOConnection.OpenRead(iocLockFile))
try
{
if(s == null) return null;
@@ -158,7 +158,7 @@ namespace ModernKeePassLibPCL.Serialization
}
// Throws on error
- public static async Task Create(IOConnectionInfo iocLockFile)
+ public static LockFileInfo Create(IOConnectionInfo iocLockFile)
{
byte[] pbID = CryptoRandom.Instance.GetRandomBytes(16);
string strTime = TimeUtil.SerializeUtc(DateTime.Now);
@@ -175,11 +175,11 @@ namespace ModernKeePassLibPCL.Serialization
sb.AppendLine(lfi.Machine);
sb.AppendLine(lfi.Domain);
- using (var s = await IOConnection.OpenWrite(iocLockFile))
+ using (var s = IOConnection.OpenWrite(iocLockFile))
{
byte[] pbFile = StrUtil.Utf8.GetBytes(sb.ToString());
if (s == null) throw new IOException(iocLockFile.GetDisplayName());
- await s.WriteAsync(pbFile.AsBuffer());
+ s.WriteAsync(pbFile.AsBuffer()).GetAwaiter().GetResult();
}
return lfi;
@@ -193,7 +193,7 @@ namespace ModernKeePassLibPCL.Serialization
m_iocLockFile = iocBaseFile.CloneDeep();
m_iocLockFile.Path += LockFileExt;
- LockFileInfo lfiEx = LockFileInfo.Load(m_iocLockFile).Result;
+ LockFileInfo lfiEx = LockFileInfo.Load(m_iocLockFile);
if(lfiEx != null)
{
m_iocLockFile = null; // Otherwise Dispose deletes the existing one
diff --git a/ModernKeePassLib/Serialization/FileTransactionEx.cs b/ModernKeePassLib/Serialization/FileTransactionEx.cs
index 5187831..79d75cd 100644
--- a/ModernKeePassLib/Serialization/FileTransactionEx.cs
+++ b/ModernKeePassLib/Serialization/FileTransactionEx.cs
@@ -79,7 +79,7 @@ namespace ModernKeePassLibPCL.Serialization
else m_iocTemp = m_iocBase;
}
- public async Task OpenWrite()
+ public IRandomAccessStream OpenWrite()
{
if(!m_bTransacted) m_bMadeUnhidden = UrlUtil.UnhideFile(m_iocTemp.Path);
else // m_bTransacted
@@ -88,7 +88,7 @@ namespace ModernKeePassLibPCL.Serialization
catch(Exception) { }
}
- return await IOConnection.OpenWrite(m_iocTemp);
+ return IOConnection.OpenWrite(m_iocTemp);
}
public void CommitWrite()
diff --git a/ModernKeePassLib/Serialization/IOConnection.cs b/ModernKeePassLib/Serialization/IOConnection.cs
index cd752c8..cdbc056 100644
--- a/ModernKeePassLib/Serialization/IOConnection.cs
+++ b/ModernKeePassLib/Serialization/IOConnection.cs
@@ -422,17 +422,17 @@ namespace ModernKeePassLibPCL.Serialization
new Uri(ioc.Path)));
}
#else
- public static async Task OpenRead(IOConnectionInfo ioc)
+ public static IRandomAccessStream OpenRead(IOConnectionInfo ioc)
{
RaiseIOAccessPreEvent(ioc, IOAccessType.Read);
- return await OpenReadLocal(ioc);
+ return OpenReadLocal(ioc);
}
#endif
- private static async Task OpenReadLocal(IOConnectionInfo ioc)
+ private static IRandomAccessStream OpenReadLocal(IOConnectionInfo ioc)
{
- return await ioc.StorageFile.OpenAsync(FileAccessMode.Read);
+ return ioc.StorageFile.OpenAsync(FileAccessMode.Read).GetAwaiter().GetResult();
}
#if (!ModernKeePassLibPCL && !KeePassLibSD && !KeePassRT)
@@ -458,17 +458,17 @@ namespace ModernKeePassLibPCL.Serialization
return IocStream.WrapIfRequired(s);
}
#else
- public static async Task OpenWrite(IOConnectionInfo ioc)
+ public static IRandomAccessStream OpenWrite(IOConnectionInfo ioc)
{
RaiseIOAccessPreEvent(ioc, IOAccessType.Write);
- return await OpenWriteLocal(ioc);
+ return OpenWriteLocal(ioc);
}
#endif
- private static async Task OpenWriteLocal(IOConnectionInfo ioc)
+ private static IRandomAccessStream OpenWriteLocal(IOConnectionInfo ioc)
{
- return await ioc.StorageFile.OpenAsync(FileAccessMode.ReadWrite);
+ return ioc.StorageFile.OpenAsync(FileAccessMode.ReadWrite).GetAwaiter().GetResult();
}
public static bool FileExists(IOConnectionInfo ioc)
@@ -486,12 +486,12 @@ namespace ModernKeePassLibPCL.Serialization
return ioc.StorageFile.IsAvailable;
}
- public static async void DeleteFile(IOConnectionInfo ioc)
+ public static void DeleteFile(IOConnectionInfo ioc)
{
RaiseIOAccessPreEvent(ioc, IOAccessType.Delete);
if (!ioc.IsLocalFile()) return;
- await ioc.StorageFile?.DeleteAsync();
+ ioc.StorageFile?.DeleteAsync().GetAwaiter().GetResult();
}
///
@@ -503,12 +503,12 @@ namespace ModernKeePassLibPCL.Serialization
///
/// Source file path.
/// Target file path.
- public static async void RenameFile(IOConnectionInfo iocFrom, IOConnectionInfo iocTo)
+ public static void RenameFile(IOConnectionInfo iocFrom, IOConnectionInfo iocTo)
{
RaiseIOAccessPreEvent(iocFrom, iocTo, IOAccessType.Move);
if (!iocFrom.IsLocalFile()) return;
- await iocFrom.StorageFile?.RenameAsync(iocTo.Path);
+ iocFrom.StorageFile?.RenameAsync(iocTo.Path).GetAwaiter().GetResult();
}
#if (!ModernKeePassLibPCL && !KeePassLibSD && !KeePassRT)
@@ -544,13 +544,13 @@ namespace ModernKeePassLibPCL.Serialization
catch(Exception) { Debug.Assert(false); }
}
#endif
- public static async Task ReadFile(IOConnectionInfo ioc)
+ public static byte[] ReadFile(IOConnectionInfo ioc)
{
IRandomAccessStream sIn = null;
MemoryStream ms = null;
try
{
- sIn = await OpenRead(ioc);
+ sIn = OpenRead(ioc);
if(sIn == null) return null;
ms = new MemoryStream();
diff --git a/ModernKeePassLib/Serialization/KdbxFile.Read.cs b/ModernKeePassLib/Serialization/KdbxFile.Read.cs
index 3881607..538cd13 100644
--- a/ModernKeePassLib/Serialization/KdbxFile.Read.cs
+++ b/ModernKeePassLib/Serialization/KdbxFile.Read.cs
@@ -58,10 +58,10 @@ namespace ModernKeePassLibPCL.Serialization
/// File to load.
/// Format specifier.
/// Status logger (optional).
- public async void Load(string strFilePath, KdbxFormat kdbFormat, IStatusLogger slLogger)
+ public void Load(string strFilePath, KdbxFormat kdbFormat, IStatusLogger slLogger)
{
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFilePath);
- Load(await IOConnection.OpenRead(ioc), kdbFormat, slLogger);
+ Load(IOConnection.OpenRead(ioc), kdbFormat, slLogger);
}
///