diff --git a/ModernKeePass/Common/DatabaseHelper.cs b/ModernKeePass/Common/DatabaseHelper.cs
index fe6a42d..afa5d44 100644
--- a/ModernKeePass/Common/DatabaseHelper.cs
+++ b/ModernKeePass/Common/DatabaseHelper.cs
@@ -4,6 +4,7 @@ using Windows.UI.Xaml.Controls;
using ModernKeePass.ViewModels;
using ModernKeePassLib;
using ModernKeePassLib.Cryptography.Cipher;
+using ModernKeePassLib.Cryptography.KeyDerivation;
using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Serialization;
@@ -118,7 +119,8 @@ namespace ModernKeePass.Common
///
public void Save()
{
- if (_pwDatabase == null || !_pwDatabase.IsOpen) return;
+ // TODO: Save is disabled for now for Argon2Kdf because it corrupts DB (read works)
+ if (_pwDatabase == null || !_pwDatabase.IsOpen /*|| KdfPool.Get(_pwDatabase.KdfParameters.KdfUuid) is Argon2Kdf*/) return;
_pwDatabase.Save(new NullStatusLogger());
}
diff --git a/ModernKeePass/ModernKeePass.csproj b/ModernKeePass/ModernKeePass.csproj
index c2833aa..d416f66 100644
--- a/ModernKeePass/ModernKeePass.csproj
+++ b/ModernKeePass/ModernKeePass.csproj
@@ -352,7 +352,6 @@
ModernKeePassLib
-
12.0
diff --git a/ModernKeePassLib.Test/Cryptography/Cipher/Chacha20Tests.cs b/ModernKeePassLib.Test/Cryptography/Cipher/Chacha20Tests.cs
new file mode 100644
index 0000000..433aab5
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/Cipher/Chacha20Tests.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Security;
+using ModernKeePassLib.Cryptography;
+using ModernKeePassLib.Cryptography.Cipher;
+using ModernKeePassLib.Utility;
+using NUnit.Framework;
+
+namespace ModernKeePassLib.Test.Cryptography.Cipher
+{
+ [TestFixture]
+ public class Chacha20Tests
+ {
+ [Test]
+ public void TestChacha20()
+ {
+ // ======================================================
+ // Test vector from RFC 7539, section 2.3.2
+
+ byte[] pbKey = new byte[32];
+ for (int i = 0; i < 32; ++i) pbKey[i] = (byte)i;
+
+ byte[] pbIV = new byte[12];
+ pbIV[3] = 0x09;
+ pbIV[7] = 0x4A;
+
+ byte[] pbExpc = new byte[64] {
+ 0x10, 0xF1, 0xE7, 0xE4, 0xD1, 0x3B, 0x59, 0x15,
+ 0x50, 0x0F, 0xDD, 0x1F, 0xA3, 0x20, 0x71, 0xC4,
+ 0xC7, 0xD1, 0xF4, 0xC7, 0x33, 0xC0, 0x68, 0x03,
+ 0x04, 0x22, 0xAA, 0x9A, 0xC3, 0xD4, 0x6C, 0x4E,
+ 0xD2, 0x82, 0x64, 0x46, 0x07, 0x9F, 0xAA, 0x09,
+ 0x14, 0xC2, 0xD7, 0x05, 0xD9, 0x8B, 0x02, 0xA2,
+ 0xB5, 0x12, 0x9C, 0xD1, 0xDE, 0x16, 0x4E, 0xB9,
+ 0xCB, 0xD0, 0x83, 0xE8, 0xA2, 0x50, 0x3C, 0x4E
+ };
+
+ byte[] pb = new byte[64];
+
+ using (ChaCha20Cipher c = new ChaCha20Cipher(pbKey, pbIV))
+ {
+ c.Seek(64, SeekOrigin.Begin); // Skip first block
+ c.Encrypt(pb, 0, pb.Length);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+ }
+
+#if DEBUG
+ // ======================================================
+ // Test vector from RFC 7539, section 2.4.2
+
+ pbIV[3] = 0;
+
+ pb = StrUtil.Utf8.GetBytes("Ladies and Gentlemen of the clas" +
+ @"s of '99: If I could offer you only one tip for " +
+ @"the future, sunscreen would be it.");
+
+ pbExpc = new byte[] {
+ 0x6E, 0x2E, 0x35, 0x9A, 0x25, 0x68, 0xF9, 0x80,
+ 0x41, 0xBA, 0x07, 0x28, 0xDD, 0x0D, 0x69, 0x81,
+ 0xE9, 0x7E, 0x7A, 0xEC, 0x1D, 0x43, 0x60, 0xC2,
+ 0x0A, 0x27, 0xAF, 0xCC, 0xFD, 0x9F, 0xAE, 0x0B,
+ 0xF9, 0x1B, 0x65, 0xC5, 0x52, 0x47, 0x33, 0xAB,
+ 0x8F, 0x59, 0x3D, 0xAB, 0xCD, 0x62, 0xB3, 0x57,
+ 0x16, 0x39, 0xD6, 0x24, 0xE6, 0x51, 0x52, 0xAB,
+ 0x8F, 0x53, 0x0C, 0x35, 0x9F, 0x08, 0x61, 0xD8,
+ 0x07, 0xCA, 0x0D, 0xBF, 0x50, 0x0D, 0x6A, 0x61,
+ 0x56, 0xA3, 0x8E, 0x08, 0x8A, 0x22, 0xB6, 0x5E,
+ 0x52, 0xBC, 0x51, 0x4D, 0x16, 0xCC, 0xF8, 0x06,
+ 0x81, 0x8C, 0xE9, 0x1A, 0xB7, 0x79, 0x37, 0x36,
+ 0x5A, 0xF9, 0x0B, 0xBF, 0x74, 0xA3, 0x5B, 0xE6,
+ 0xB4, 0x0B, 0x8E, 0xED, 0xF2, 0x78, 0x5E, 0x42,
+ 0x87, 0x4D
+ };
+
+ byte[] pb64 = new byte[64];
+
+ using (ChaCha20Cipher c = new ChaCha20Cipher(pbKey, pbIV))
+ {
+ c.Encrypt(pb64, 0, pb64.Length); // Skip first block
+ c.Encrypt(pb, 0, pb.Length);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+ }
+
+ // ======================================================
+ // Test vector from RFC 7539, appendix A.2 #2
+
+ Array.Clear(pbKey, 0, pbKey.Length);
+ pbKey[31] = 1;
+
+ Array.Clear(pbIV, 0, pbIV.Length);
+ pbIV[11] = 2;
+
+ pb = StrUtil.Utf8.GetBytes("Any submission to the IETF inten" +
+ "ded by the Contributor for publication as all or" +
+ " part of an IETF Internet-Draft or RFC and any s" +
+ "tatement made within the context of an IETF acti" +
+ "vity is considered an \"IETF Contribution\". Such " +
+ "statements include oral statements in IETF sessi" +
+ "ons, as well as written and electronic communica" +
+ "tions made at any time or place, which are addressed to");
+
+ pbExpc = MemUtil.HexStringToByteArray(
+ "A3FBF07DF3FA2FDE4F376CA23E82737041605D9F4F4F57BD8CFF2C1D4B7955EC" +
+ "2A97948BD3722915C8F3D337F7D370050E9E96D647B7C39F56E031CA5EB6250D" +
+ "4042E02785ECECFA4B4BB5E8EAD0440E20B6E8DB09D881A7C6132F420E527950" +
+ "42BDFA7773D8A9051447B3291CE1411C680465552AA6C405B7764D5E87BEA85A" +
+ "D00F8449ED8F72D0D662AB052691CA66424BC86D2DF80EA41F43ABF937D3259D" +
+ "C4B2D0DFB48A6C9139DDD7F76966E928E635553BA76C5C879D7B35D49EB2E62B" +
+ "0871CDAC638939E25E8A1E0EF9D5280FA8CA328B351C3C765989CBCF3DAA8B6C" +
+ "CC3AAF9F3979C92B3720FC88DC95ED84A1BE059C6499B9FDA236E7E818B04B0B" +
+ "C39C1E876B193BFE5569753F88128CC08AAA9B63D1A16F80EF2554D7189C411F" +
+ "5869CA52C5B83FA36FF216B9C1D30062BEBCFD2DC5BCE0911934FDA79A86F6E6" +
+ "98CED759C3FF9B6477338F3DA4F9CD8514EA9982CCAFB341B2384DD902F3D1AB" +
+ "7AC61DD29C6F21BA5B862F3730E37CFDC4FD806C22F221");
+
+ using (MemoryStream msEnc = new MemoryStream())
+ {
+ using (ChaCha20Stream c = new ChaCha20Stream(msEnc, true, pbKey, pbIV))
+ {
+ Random r = CryptoRandom.NewWeakRandom();
+ r.NextBytes(pb64);
+ c.Write(pb64, 0, pb64.Length); // Skip first block
+
+ int p = 0;
+ while (p < pb.Length)
+ {
+ int cb = r.Next(1, pb.Length - p + 1);
+ c.Write(pb, p, cb);
+ p += cb;
+ }
+ Debug.Assert(p == pb.Length);
+ }
+
+ byte[] pbEnc0 = msEnc.ToArray();
+ byte[] pbEnc = MemUtil.Mid(pbEnc0, 64, pbEnc0.Length - 64);
+ Assert.That(MemUtil.ArraysEqual(pbEnc, pbExpc), Is.True);
+
+ using (MemoryStream msCT = new MemoryStream(pbEnc0, false))
+ {
+ using (ChaCha20Stream cDec = new ChaCha20Stream(msCT, false,
+ pbKey, pbIV))
+ {
+ byte[] pbPT = MemUtil.Read(cDec, pbEnc0.Length);
+
+ Assert.That(cDec.ReadByte(), Is.LessThan(0));
+ Assert.That(MemUtil.ArraysEqual(MemUtil.Mid(pbPT, 0, 64), pb64), Is.True);
+ Assert.That(MemUtil.ArraysEqual(MemUtil.Mid(pbPT, 64, pbEnc.Length), pb), Is.True);
+ }
+ }
+ }
+
+ // ======================================================
+ // Test vector TC8 from RFC draft by J. Strombergson:
+ // https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01
+
+ pbKey = new byte[32] {
+ 0xC4, 0x6E, 0xC1, 0xB1, 0x8C, 0xE8, 0xA8, 0x78,
+ 0x72, 0x5A, 0x37, 0xE7, 0x80, 0xDF, 0xB7, 0x35,
+ 0x1F, 0x68, 0xED, 0x2E, 0x19, 0x4C, 0x79, 0xFB,
+ 0xC6, 0xAE, 0xBE, 0xE1, 0xA6, 0x67, 0x97, 0x5D
+ };
+
+ // The first 4 bytes are set to zero and a large counter
+ // is used; this makes the RFC 7539 version of ChaCha20
+ // compatible with the original specification by
+ // D. J. Bernstein.
+ pbIV = new byte[12] { 0x00, 0x00, 0x00, 0x00,
+ 0x1A, 0xDA, 0x31, 0xD5, 0xCF, 0x68, 0x82, 0x21
+ };
+
+ pb = new byte[128];
+
+ pbExpc = new byte[128] {
+ 0xF6, 0x3A, 0x89, 0xB7, 0x5C, 0x22, 0x71, 0xF9,
+ 0x36, 0x88, 0x16, 0x54, 0x2B, 0xA5, 0x2F, 0x06,
+ 0xED, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2B, 0x00,
+ 0xB5, 0xE8, 0xF8, 0x0A, 0xE9, 0xA4, 0x73, 0xAF,
+ 0xC2, 0x5B, 0x21, 0x8F, 0x51, 0x9A, 0xF0, 0xFD,
+ 0xD4, 0x06, 0x36, 0x2E, 0x8D, 0x69, 0xDE, 0x7F,
+ 0x54, 0xC6, 0x04, 0xA6, 0xE0, 0x0F, 0x35, 0x3F,
+ 0x11, 0x0F, 0x77, 0x1B, 0xDC, 0xA8, 0xAB, 0x92,
+
+ 0xE5, 0xFB, 0xC3, 0x4E, 0x60, 0xA1, 0xD9, 0xA9,
+ 0xDB, 0x17, 0x34, 0x5B, 0x0A, 0x40, 0x27, 0x36,
+ 0x85, 0x3B, 0xF9, 0x10, 0xB0, 0x60, 0xBD, 0xF1,
+ 0xF8, 0x97, 0xB6, 0x29, 0x0F, 0x01, 0xD1, 0x38,
+ 0xAE, 0x2C, 0x4C, 0x90, 0x22, 0x5B, 0xA9, 0xEA,
+ 0x14, 0xD5, 0x18, 0xF5, 0x59, 0x29, 0xDE, 0xA0,
+ 0x98, 0xCA, 0x7A, 0x6C, 0xCF, 0xE6, 0x12, 0x27,
+ 0x05, 0x3C, 0x84, 0xE4, 0x9A, 0x4A, 0x33, 0x32
+ };
+
+ using (ChaCha20Cipher c = new ChaCha20Cipher(pbKey, pbIV, true))
+ {
+ c.Decrypt(pb, 0, pb.Length);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+ }
+#endif
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePassLib.Test/Cryptography/Cipher/StandardAesEngineTests.cs b/ModernKeePassLib.Test/Cryptography/Cipher/StandardAesEngineTests.cs
index cb78604..cd775f5 100644
--- a/ModernKeePassLib.Test/Cryptography/Cipher/StandardAesEngineTests.cs
+++ b/ModernKeePassLib.Test/Cryptography/Cipher/StandardAesEngineTests.cs
@@ -14,7 +14,7 @@ using NUnit.Framework;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
-namespace ModernKeePassLib.Test.Shared.Cryptography.Cipher
+namespace ModernKeePassLib.Test.Cryptography.Cipher
{
[TestFixture()]
public class StandardAesEngineTests
diff --git a/ModernKeePassLib.Test/Cryptography/CryptoRandomStreamTests.cs b/ModernKeePassLib.Test/Cryptography/CryptoRandomStreamTests.cs
index 39ff6a0..75d3937 100644
--- a/ModernKeePassLib.Test/Cryptography/CryptoRandomStreamTests.cs
+++ b/ModernKeePassLib.Test/Cryptography/CryptoRandomStreamTests.cs
@@ -7,7 +7,7 @@ using KeePassLib.Cryptography;
using ModernKeePassLib.Cryptography;
#endif
-namespace ModernKeePassLib.Test.Shared.Cryptography
+namespace ModernKeePassLib.Test.Cryptography
{
[TestFixture ()]
public class CryptoRandomStreamTests
diff --git a/ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs b/ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
index c94b3b6..32c6c2b 100644
--- a/ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
+++ b/ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
@@ -7,7 +7,7 @@ using KeePassLib.Cryptography;
using ModernKeePassLib.Cryptography;
#endif
-namespace ModernKeePassLib.Test.Shared.Cryptography
+namespace ModernKeePassLib.Test.Cryptography
{
[TestFixture ()]
public class CryptoRandomTests
diff --git a/ModernKeePassLib.Test/Cryptography/Hash/Blake2bTests.cs b/ModernKeePassLib.Test/Cryptography/Hash/Blake2bTests.cs
new file mode 100644
index 0000000..a91591e
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/Hash/Blake2bTests.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Text;
+using ModernKeePassLib.Cryptography;
+using ModernKeePassLib.Cryptography.Hash;
+using ModernKeePassLib.Utility;
+using NUnit.Framework;
+
+namespace ModernKeePassLib.Test.Cryptography.Hash
+{
+ [TestFixture]
+ public class Blake2bTests
+ {
+ [Test]
+ public void TestBlake2b()
+ {
+ Blake2b h = new Blake2b();
+
+ // ======================================================
+ // From https://tools.ietf.org/html/rfc7693
+
+ byte[] pbData = StrUtil.Utf8.GetBytes("abc");
+ byte[] pbExpc = new byte[64] {
+ 0xBA, 0x80, 0xA5, 0x3F, 0x98, 0x1C, 0x4D, 0x0D,
+ 0x6A, 0x27, 0x97, 0xB6, 0x9F, 0x12, 0xF6, 0xE9,
+ 0x4C, 0x21, 0x2F, 0x14, 0x68, 0x5A, 0xC4, 0xB7,
+ 0x4B, 0x12, 0xBB, 0x6F, 0xDB, 0xFF, 0xA2, 0xD1,
+ 0x7D, 0x87, 0xC5, 0x39, 0x2A, 0xAB, 0x79, 0x2D,
+ 0xC2, 0x52, 0xD5, 0xDE, 0x45, 0x33, 0xCC, 0x95,
+ 0x18, 0xD3, 0x8A, 0xA8, 0xDB, 0xF1, 0x92, 0x5A,
+ 0xB9, 0x23, 0x86, 0xED, 0xD4, 0x00, 0x99, 0x23
+ };
+
+ byte[] pbC = h.ComputeHash(pbData);
+ Assert.That(MemUtil.ArraysEqual(pbC, pbExpc), Is.True);
+
+ // ======================================================
+ // Computed using the official b2sum tool
+
+ pbExpc = new byte[64] {
+ 0x78, 0x6A, 0x02, 0xF7, 0x42, 0x01, 0x59, 0x03,
+ 0xC6, 0xC6, 0xFD, 0x85, 0x25, 0x52, 0xD2, 0x72,
+ 0x91, 0x2F, 0x47, 0x40, 0xE1, 0x58, 0x47, 0x61,
+ 0x8A, 0x86, 0xE2, 0x17, 0xF7, 0x1F, 0x54, 0x19,
+ 0xD2, 0x5E, 0x10, 0x31, 0xAF, 0xEE, 0x58, 0x53,
+ 0x13, 0x89, 0x64, 0x44, 0x93, 0x4E, 0xB0, 0x4B,
+ 0x90, 0x3A, 0x68, 0x5B, 0x14, 0x48, 0xB7, 0x55,
+ 0xD5, 0x6F, 0x70, 0x1A, 0xFE, 0x9B, 0xE2, 0xCE
+ };
+
+ pbC = h.ComputeHash(MemUtil.EmptyByteArray);
+ Assert.That(MemUtil.ArraysEqual(pbC, pbExpc), Is.True);
+
+ // ======================================================
+ // Computed using the official b2sum tool
+
+ string strS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.:,;_-\r\n";
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 1000; ++i) sb.Append(strS);
+ pbData = StrUtil.Utf8.GetBytes(sb.ToString());
+
+ pbExpc = new byte[64] {
+ 0x59, 0x69, 0x8D, 0x3B, 0x83, 0xF4, 0x02, 0x4E,
+ 0xD8, 0x99, 0x26, 0x0E, 0xF4, 0xE5, 0x9F, 0x20,
+ 0xDC, 0x31, 0xEE, 0x5B, 0x45, 0xEA, 0xBB, 0xFC,
+ 0x1C, 0x0A, 0x8E, 0xED, 0xAA, 0x7A, 0xFF, 0x50,
+ 0x82, 0xA5, 0x8F, 0xBC, 0x4A, 0x46, 0xFC, 0xC5,
+ 0xEF, 0x44, 0x4E, 0x89, 0x80, 0x7D, 0x3F, 0x1C,
+ 0xC1, 0x94, 0x45, 0xBB, 0xC0, 0x2C, 0x95, 0xAA,
+ 0x3F, 0x08, 0x8A, 0x93, 0xF8, 0x75, 0x91, 0xB0
+ };
+
+ Random r = CryptoRandom.NewWeakRandom();
+ int p = 0;
+ while (p < pbData.Length)
+ {
+ int cb = r.Next(1, pbData.Length - p + 1);
+ h.TransformBlock(pbData, p, cb, pbData, p);
+ p += cb;
+ }
+ Assert.That(p, Is.EqualTo(pbData.Length));
+
+ h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
+
+ Assert.That(MemUtil.ArraysEqual(h.Hash, pbExpc), Is.True);
+
+ h.Clear();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePassLib.Test/Cryptography/Hash/HmacTests.cs b/ModernKeePassLib.Test/Cryptography/Hash/HmacTests.cs
new file mode 100644
index 0000000..ebcd198
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/Hash/HmacTests.cs
@@ -0,0 +1,82 @@
+using ModernKeePassLib.Cryptography;
+using ModernKeePassLib.Cryptography.Hash;
+using ModernKeePassLib.Utility;
+using NUnit.Framework;
+
+namespace ModernKeePassLib.Test.Cryptography.Hash
+{
+ [TestFixture]
+ public class HmacTests
+ {
+ [Test]
+ public void TestHmac1()
+ {
+ // Test vectors from RFC 4231
+
+ var pbKey = new byte[20];
+ for (var i = 0; i < pbKey.Length; ++i) pbKey[i] = 0x0B;
+ var pbMsg = StrUtil.Utf8.GetBytes("Hi There");
+ var pbExpc = new byte[]
+ {
+ 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
+ 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
+ 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
+ 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7
+ };
+ HmacEval(pbKey, pbMsg, pbExpc);
+ }
+
+ [Test]
+ public void TestHmac2()
+ {
+ var pbKey = new byte[131];
+ for (var i = 0; i < pbKey.Length; ++i) pbKey[i] = 0xAA;
+ var pbMsg = StrUtil.Utf8.GetBytes(
+ "This is a test using a larger than block-size key and " +
+ "a larger than block-size data. The key needs to be " +
+ "hashed before being used by the HMAC algorithm.");
+ var pbExpc = new byte[] {
+ 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
+ 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
+ 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
+ 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2
+ };
+ HmacEval(pbKey, pbMsg, pbExpc);
+ }
+
+ [Test]
+ public void TestHmacOtp()
+ {
+ var pbSecret = StrUtil.Utf8.GetBytes("12345678901234567890");
+ var vExp = new []{ "755224", "287082", "359152",
+ "969429", "338314", "254676", "287922", "162583", "399871",
+ "520489" };
+
+ for (var i = 0; i < vExp.Length; ++i)
+ {
+ Assert.That(HmacOtp.Generate(pbSecret, (ulong)i, 6, false, -1), Is.EqualTo(vExp[i]));
+ }
+ }
+
+ private static void HmacEval(byte[] pbKey, byte[] pbMsg,
+ byte[] pbExpc)
+ {
+ using (var h = new HMACSHA256(pbKey))
+ {
+ h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
+ h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
+
+ byte[] pbHash = h.Hash;
+ Assert.That(MemUtil.ArraysEqual(pbHash, pbExpc), Is.True);
+
+ // Reuse the object
+ h.Initialize();
+ h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
+ h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
+
+ pbHash = h.Hash;
+ Assert.That(MemUtil.ArraysEqual(pbHash, pbExpc), Is.True);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs b/ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
index 59c4980..7fd746d 100644
--- a/ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
+++ b/ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
@@ -9,7 +9,7 @@ using KeePassLib.Cryptography;
using ModernKeePassLib.Cryptography;
#endif
-namespace ModernKeePassLib.Test.Shared.Cryptography
+namespace ModernKeePassLib.Test.Cryptography
{
[TestFixture ()]
public class HashingStreamExTests
diff --git a/ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs b/ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
index 894b979..0892c6d 100644
--- a/ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
+++ b/ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
@@ -8,7 +8,7 @@ using KeePassLib.Cryptography;
using ModernKeePassLib.Cryptography;
#endif
-namespace ModernKeePassLib.Test.Shared.Cryptography
+namespace ModernKeePassLib.Test.Cryptography
{
[TestFixture ()]
public class HmacOtpTests
diff --git a/ModernKeePassLib.Test/Cryptography/KeyDerivation/AesKdfTests.cs b/ModernKeePassLib.Test/Cryptography/KeyDerivation/AesKdfTests.cs
new file mode 100644
index 0000000..b43aa71
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/KeyDerivation/AesKdfTests.cs
@@ -0,0 +1,42 @@
+using System;
+using ModernKeePassLib.Cryptography;
+using ModernKeePassLib.Cryptography.KeyDerivation;
+using ModernKeePassLib.Utility;
+using NUnit.Framework;
+
+namespace ModernKeePassLib.Test.Cryptography.KeyDerivation
+{
+ [TestFixture]
+ public class AesKdfTests
+ {
+ [Test]
+ public void TestAesKdf()
+ {
+ // Up to KeePass 2.34, the OtpKeyProv plugin used the public
+ // CompositeKey.TransformKeyManaged method (and a finalizing
+ // SHA-256 computation), which became an internal method of
+ // the AesKdf class in KeePass 2.35, thus OtpKeyProv now
+ // uses the AesKdf class; here we ensure that the results
+ // are the same
+ var r = CryptoRandom.NewWeakRandom();
+ var pbKey = new byte[32];
+ r.NextBytes(pbKey);
+ var pbSeed = new byte[32];
+ r.NextBytes(pbSeed);
+ var uRounds = (ulong)r.Next(1, 0x7FFF);
+
+ var pbMan = new byte[pbKey.Length];
+ Array.Copy(pbKey, pbMan, pbKey.Length);
+ Assert.That(AesKdf.TransformKeyManaged(pbMan, pbSeed, uRounds), Is.True);
+ pbMan = CryptoUtil.HashSha256(pbMan);
+
+ var kdf = new AesKdf();
+ var p = kdf.GetDefaultParameters();
+ p.SetUInt64(AesKdf.ParamRounds, uRounds);
+ p.SetByteArray(AesKdf.ParamSeed, pbSeed);
+ var pbKdf = kdf.Transform(pbKey, p);
+
+ Assert.That(MemUtil.ArraysEqual(pbMan, pbKdf), Is.True);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePassLib.Test/Cryptography/KeyDerivation/Argon2Tests.cs b/ModernKeePassLib.Test/Cryptography/KeyDerivation/Argon2Tests.cs
new file mode 100644
index 0000000..44c34ff
--- /dev/null
+++ b/ModernKeePassLib.Test/Cryptography/KeyDerivation/Argon2Tests.cs
@@ -0,0 +1,145 @@
+using ModernKeePassLib.Cryptography.KeyDerivation;
+using ModernKeePassLib.Utility;
+using NUnit.Framework;
+
+namespace ModernKeePassLib.Test.Cryptography.KeyDerivation
+{
+ [TestFixture]
+ public class Argon2Tests
+ {
+ [Test]
+ public void TestArgon2()
+ {
+ Argon2Kdf kdf = new Argon2Kdf();
+
+ // ======================================================
+ // From the official Argon2 1.3 reference code package
+ // (test vector for Argon2d 1.3); also on
+ // https://tools.ietf.org/html/draft-irtf-cfrg-argon2-00
+
+ var p = kdf.GetDefaultParameters();
+ kdf.Randomize(p);
+
+ Assert.That(p.GetUInt32(Argon2Kdf.ParamVersion, 0), Is.EqualTo(0x13U));
+
+ byte[] pbMsg = new byte[32];
+ for (int i = 0; i < pbMsg.Length; ++i) pbMsg[i] = 1;
+
+ p.SetUInt64(Argon2Kdf.ParamMemory, 32 * 1024);
+ p.SetUInt64(Argon2Kdf.ParamIterations, 3);
+ p.SetUInt32(Argon2Kdf.ParamParallelism, 4);
+
+ byte[] pbSalt = new byte[16];
+ for (int i = 0; i < pbSalt.Length; ++i) pbSalt[i] = 2;
+ p.SetByteArray(Argon2Kdf.ParamSalt, pbSalt);
+
+ byte[] pbKey = new byte[8];
+ for (int i = 0; i < pbKey.Length; ++i) pbKey[i] = 3;
+ p.SetByteArray(Argon2Kdf.ParamSecretKey, pbKey);
+
+ byte[] pbAssoc = new byte[12];
+ for (int i = 0; i < pbAssoc.Length; ++i) pbAssoc[i] = 4;
+ p.SetByteArray(Argon2Kdf.ParamAssocData, pbAssoc);
+
+ byte[] pbExpc = new byte[32] {
+ 0x51, 0x2B, 0x39, 0x1B, 0x6F, 0x11, 0x62, 0x97,
+ 0x53, 0x71, 0xD3, 0x09, 0x19, 0x73, 0x42, 0x94,
+ 0xF8, 0x68, 0xE3, 0xBE, 0x39, 0x84, 0xF3, 0xC1,
+ 0xA1, 0x3A, 0x4D, 0xB9, 0xFA, 0xBE, 0x4A, 0xCB
+ };
+
+ byte[] pb = kdf.Transform(pbMsg, p);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+
+ // ======================================================
+ // From the official Argon2 1.3 reference code package
+ // (test vector for Argon2d 1.0)
+
+ p.SetUInt32(Argon2Kdf.ParamVersion, 0x10);
+
+ pbExpc = new byte[32] {
+ 0x96, 0xA9, 0xD4, 0xE5, 0xA1, 0x73, 0x40, 0x92,
+ 0xC8, 0x5E, 0x29, 0xF4, 0x10, 0xA4, 0x59, 0x14,
+ 0xA5, 0xDD, 0x1F, 0x5C, 0xBF, 0x08, 0xB2, 0x67,
+ 0x0D, 0xA6, 0x8A, 0x02, 0x85, 0xAB, 0xF3, 0x2B
+ };
+
+ pb = kdf.Transform(pbMsg, p);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+
+ // ======================================================
+ // From the official 'phc-winner-argon2-20151206.zip'
+ // (test vector for Argon2d 1.0)
+
+ p.SetUInt64(Argon2Kdf.ParamMemory, 16 * 1024);
+
+ pbExpc = new byte[32] {
+ 0x57, 0xB0, 0x61, 0x3B, 0xFD, 0xD4, 0x13, 0x1A,
+ 0x0C, 0x34, 0x88, 0x34, 0xC6, 0x72, 0x9C, 0x2C,
+ 0x72, 0x29, 0x92, 0x1E, 0x6B, 0xBA, 0x37, 0x66,
+ 0x5D, 0x97, 0x8C, 0x4F, 0xE7, 0x17, 0x5E, 0xD2
+ };
+
+ pb = kdf.Transform(pbMsg, p);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+
+ // ======================================================
+ // Computed using the official 'argon2' application
+ // (test vectors for Argon2d 1.3)
+
+ p = kdf.GetDefaultParameters();
+
+ pbMsg = StrUtil.Utf8.GetBytes("ABC1234");
+
+ p.SetUInt64(Argon2Kdf.ParamMemory, (1 << 11) * 1024); // 2 MB
+ p.SetUInt64(Argon2Kdf.ParamIterations, 2);
+ p.SetUInt32(Argon2Kdf.ParamParallelism, 2);
+
+ pbSalt = StrUtil.Utf8.GetBytes("somesalt");
+ p.SetByteArray(Argon2Kdf.ParamSalt, pbSalt);
+
+ pbExpc = new byte[32] {
+ 0x29, 0xCB, 0xD3, 0xA1, 0x93, 0x76, 0xF7, 0xA2,
+ 0xFC, 0xDF, 0xB0, 0x68, 0xAC, 0x0B, 0x99, 0xBA,
+ 0x40, 0xAC, 0x09, 0x01, 0x73, 0x42, 0xCE, 0xF1,
+ 0x29, 0xCC, 0xA1, 0x4F, 0xE1, 0xC1, 0xB7, 0xA3
+ };
+
+ pb = kdf.Transform(pbMsg, p);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+
+ p.SetUInt64(Argon2Kdf.ParamMemory, (1 << 10) * 1024); // 1 MB
+ p.SetUInt64(Argon2Kdf.ParamIterations, 3);
+
+ pbExpc = new byte[32] {
+ 0x7A, 0xBE, 0x1C, 0x1C, 0x8D, 0x7F, 0xD6, 0xDC,
+ 0x7C, 0x94, 0x06, 0x3E, 0xD8, 0xBC, 0xD8, 0x1C,
+ 0x2F, 0x87, 0x84, 0x99, 0x12, 0x83, 0xFE, 0x76,
+ 0x00, 0x64, 0xC4, 0x58, 0xA4, 0xDA, 0x35, 0x70
+ };
+
+ pb = kdf.Transform(pbMsg, p);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+
+ p.SetUInt64(Argon2Kdf.ParamMemory, (1 << 20) * 1024); // 1 GB
+ p.SetUInt64(Argon2Kdf.ParamIterations, 2);
+ p.SetUInt32(Argon2Kdf.ParamParallelism, 3);
+
+ pbExpc = new byte[32] {
+ 0xE6, 0xE7, 0xCB, 0xF5, 0x5A, 0x06, 0x93, 0x05,
+ 0x32, 0xBA, 0x86, 0xC6, 0x1F, 0x45, 0x17, 0x99,
+ 0x65, 0x41, 0x77, 0xF9, 0x30, 0x55, 0x9A, 0xE8,
+ 0x3D, 0x21, 0x48, 0xC6, 0x2D, 0x0C, 0x49, 0x11
+ };
+
+ pb = kdf.Transform(pbMsg, p);
+
+ Assert.That(MemUtil.ArraysEqual(pb, pbExpc), Is.True);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePassLib.Test/Keys/CompositeKeyTests.cs b/ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
index 8afb827..ed5118c 100644
--- a/ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
+++ b/ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
@@ -2,7 +2,7 @@
using ModernKeePassLib.Cryptography.KeyDerivation;
using ModernKeePassLib.Keys;
-namespace ModernKeePassLib.Test.Shared.Keys
+namespace ModernKeePassLib.Test.Keys
{
[TestFixture ()]
public class CompositeKeyTests
diff --git a/ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs b/ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
index 0df7709..ecacde5 100644
--- a/ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
+++ b/ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
@@ -7,7 +7,7 @@ using KeePassLib.Keys;
using ModernKeePassLib.Keys;
#endif
-namespace ModernKeePassLib.Test.Shared.Keys
+namespace ModernKeePassLib.Test.Keys
{
[TestFixture ()]
public class KcpCustomKeyTests
diff --git a/ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs b/ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs
index f00ee71..06e4c75 100644
--- a/ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs
+++ b/ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs
@@ -8,7 +8,7 @@ using KeePassLib.Keys;
using ModernKeePassLib.Keys;
#endif
-namespace ModernKeePassLib.Test.Shared.Keys
+namespace ModernKeePassLib.Test.Keys
{
[TestFixture ()]
public class KcpKeyFileTests
diff --git a/ModernKeePassLib.Test/Keys/KcpPasswordTests.cs b/ModernKeePassLib.Test/Keys/KcpPasswordTests.cs
index 4dc794b..4fbc4a7 100644
--- a/ModernKeePassLib.Test/Keys/KcpPasswordTests.cs
+++ b/ModernKeePassLib.Test/Keys/KcpPasswordTests.cs
@@ -7,7 +7,7 @@ using KeePassLib.Keys;
using ModernKeePassLib.Keys;
#endif
-namespace ModernKeePassLib.Test.Shared.Keys
+namespace ModernKeePassLib.Test.Keys
{
[TestFixture ()]
public class KcpPasswordTests
diff --git a/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj b/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj
index 702570f..30b8dfe 100644
--- a/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj
+++ b/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj
@@ -54,11 +54,16 @@
+
+
+
+
+
diff --git a/ModernKeePassLib.Test/Serialization/HashedBlockStreamTests.cs b/ModernKeePassLib.Test/Serialization/HashedBlockStreamTests.cs
index 926e91a..e26d2ec 100644
--- a/ModernKeePassLib.Test/Serialization/HashedBlockStreamTests.cs
+++ b/ModernKeePassLib.Test/Serialization/HashedBlockStreamTests.cs
@@ -8,7 +8,7 @@ using KeePassLib.Serialization;
using ModernKeePassLib.Serialization;
#endif
-namespace ModernKeePassLib.Test.Shared.Serialization
+namespace ModernKeePassLib.Test.Serialization
{
[TestFixture ()]
public class HashedBlockStreamTests
diff --git a/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs b/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs
index 2cd995e..3e29219 100644
--- a/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs
+++ b/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs
@@ -20,7 +20,7 @@ using ModernKeePassLib.Serialization;
using ModernKeePassLib.Collections;
#endif
-namespace ModernKeePassLib.Test.Shared.Serialization
+namespace ModernKeePassLib.Test.Serialization
{
[TestFixture()]
public class KdbxFileTests
diff --git a/ModernKeePassLib.Test/Utility/GfxUtilTests.cs b/ModernKeePassLib.Test/Utility/GfxUtilTests.cs
index 70a551e..64da5ab 100644
--- a/ModernKeePassLib.Test/Utility/GfxUtilTests.cs
+++ b/ModernKeePassLib.Test/Utility/GfxUtilTests.cs
@@ -8,7 +8,7 @@ using Splat;
using ModernKeePassLib.Utility;
#endif
-namespace ModernKeePassLib.Test.Shared.Utility
+namespace ModernKeePassLib.Test.Utility
{
[TestFixture ()]
public class GfxUtilTests
diff --git a/ModernKeePassLib/Cryptography/Cipher/ChaCha20Engine.cs b/ModernKeePassLib/Cryptography/Cipher/ChaCha20Engine.cs
index 7b8a26c..4f1a1e9 100644
--- a/ModernKeePassLib/Cryptography/Cipher/ChaCha20Engine.cs
+++ b/ModernKeePassLib/Cryptography/Cipher/ChaCha20Engine.cs
@@ -69,7 +69,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
}
}
- internal sealed class ChaCha20Stream : Stream
+ public sealed class ChaCha20Stream : Stream
{
private Stream m_sBase;
private readonly bool m_bWriting;
diff --git a/ModernKeePassLib/Cryptography/Hash/DigestManaged.cs b/ModernKeePassLib/Cryptography/Hash/DigestManaged.cs
index 6c20e84..9622e09 100644
--- a/ModernKeePassLib/Cryptography/Hash/DigestManaged.cs
+++ b/ModernKeePassLib/Cryptography/Hash/DigestManaged.cs
@@ -5,7 +5,17 @@ namespace ModernKeePassLib.Cryptography.Hash
{
public abstract class DigestManaged: IDisposable
{
- protected IDigest Hash;
+ protected IDigest Digest;
+
+ public byte[] Hash
+ {
+ get
+ {
+ var result = new byte[Digest.GetDigestSize()];
+ Digest.DoFinal(result, 0);
+ return result;
+ }
+ }
public byte[] ComputeHash(byte[] value)
{
@@ -16,16 +26,29 @@ namespace ModernKeePassLib.Cryptography.Hash
{
if (value == null) throw new ArgumentNullException(nameof(value));
- byte[] resBuf = new byte[Hash.GetDigestSize()];
- Hash.BlockUpdate(value, 0, length);
- Hash.DoFinal(resBuf, 0);
+ byte[] resBuf = new byte[Digest.GetDigestSize()];
+ Digest.BlockUpdate(value, 0, length);
+ Digest.DoFinal(resBuf, 0);
return resBuf;
}
+
+ public void TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ Digest.BlockUpdate(inputBuffer, inputOffset, inputCount);
+ if ((outputBuffer != null) && ((inputBuffer != outputBuffer) || (inputOffset != outputOffset)))
+ Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);
+ }
+
+ public void TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+ {
+ Digest.BlockUpdate(inputBuffer, inputOffset, inputCount);
+ }
+
public void Dispose()
{
- Hash.Reset();
+ Digest.Reset();
}
}
}
diff --git a/ModernKeePassLib/Cryptography/Hash/HMAC.cs b/ModernKeePassLib/Cryptography/Hash/HMAC.cs
index 5e931b4..10c8c9b 100644
--- a/ModernKeePassLib/Cryptography/Hash/HMAC.cs
+++ b/ModernKeePassLib/Cryptography/Hash/HMAC.cs
@@ -5,7 +5,17 @@ namespace ModernKeePassLib.Cryptography.Hash
{
public class HMAC : IDisposable
{
- protected HMac _hmac;
+ protected HMac Hmac;
+
+ public byte[] Hash
+ {
+ get
+ {
+ var result = new byte[Hmac.GetMacSize()];
+ Hmac.DoFinal(result, 0);
+ return result;
+ }
+ }
public byte[] ComputeHash(byte[] value)
{
@@ -16,16 +26,33 @@ namespace ModernKeePassLib.Cryptography.Hash
{
if (value == null) throw new ArgumentNullException(nameof(value));
- byte[] resBuf = new byte[_hmac.GetMacSize()];
- _hmac.BlockUpdate(value, 0, length);
- _hmac.DoFinal(resBuf, 0);
+ byte[] resBuf = new byte[Hmac.GetMacSize()];
+ Hmac.BlockUpdate(value, 0, length);
+ Hmac.DoFinal(resBuf, 0);
return resBuf;
}
+ public void TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ Hmac.BlockUpdate(inputBuffer, inputOffset, inputCount);
+ if ((outputBuffer != null) && ((inputBuffer != outputBuffer) || (inputOffset != outputOffset)))
+ Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);
+ }
+
+ public void TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+ {
+ Hmac.BlockUpdate(inputBuffer, inputOffset, inputCount);
+ }
+
+ public void Initialize()
+ {
+ Hmac.Reset();
+ }
+
public void Dispose()
{
- _hmac.Reset();
+ Hmac.Reset();
}
}
}
diff --git a/ModernKeePassLib/Cryptography/Hash/HMACSHA1.cs b/ModernKeePassLib/Cryptography/Hash/HMACSHA1.cs
index ac298d4..c720caa 100644
--- a/ModernKeePassLib/Cryptography/Hash/HMACSHA1.cs
+++ b/ModernKeePassLib/Cryptography/Hash/HMACSHA1.cs
@@ -8,8 +8,8 @@ namespace ModernKeePassLib.Cryptography.Hash
{
public HMACSHA1(byte[] key)
{
- _hmac = new HMac(new Sha1Digest());
- _hmac.Init(new KeyParameter(key));
+ Hmac = new HMac(new Sha1Digest());
+ Hmac.Init(new KeyParameter(key));
}
}
}
diff --git a/ModernKeePassLib/Cryptography/Hash/HMACSHA256.cs b/ModernKeePassLib/Cryptography/Hash/HMACSHA256.cs
index 65cbaeb..d0d5703 100644
--- a/ModernKeePassLib/Cryptography/Hash/HMACSHA256.cs
+++ b/ModernKeePassLib/Cryptography/Hash/HMACSHA256.cs
@@ -8,23 +8,8 @@ namespace ModernKeePassLib.Cryptography.Hash
{
public HMACSHA256(byte[] key)
{
- _hmac = new HMac(new Sha256Digest());
- _hmac.Init(new KeyParameter(key));
+ Hmac = new HMac(new Sha256Digest());
+ Hmac.Init(new KeyParameter(key));
}
-
- /*internal void TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- _hmac.BlockUpdate(inputBuffer, inputOffset, inputCount);
- }
-
- internal void TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
- {
- _hmac.DoFinal(inputBuffer, inputOffset);
- }
-
- internal void Initialize()
- {
- _hmac.Reset();
- }*/
}
}
diff --git a/ModernKeePassLib/Cryptography/Hash/SHA256Managed.cs b/ModernKeePassLib/Cryptography/Hash/SHA256Managed.cs
index 55d1cbd..c5323e4 100644
--- a/ModernKeePassLib/Cryptography/Hash/SHA256Managed.cs
+++ b/ModernKeePassLib/Cryptography/Hash/SHA256Managed.cs
@@ -6,7 +6,7 @@ namespace ModernKeePassLib.Cryptography.Hash
{
public SHA256Managed()
{
- Hash = new Sha256Digest();
+ Digest = new Sha256Digest();
}
}
}
diff --git a/ModernKeePassLib/Cryptography/Hash/SHA512Managed.cs b/ModernKeePassLib/Cryptography/Hash/SHA512Managed.cs
index d98ba77..f9d5ad6 100644
--- a/ModernKeePassLib/Cryptography/Hash/SHA512Managed.cs
+++ b/ModernKeePassLib/Cryptography/Hash/SHA512Managed.cs
@@ -6,7 +6,7 @@ namespace ModernKeePassLib.Cryptography.Hash
{
public SHA512Managed()
{
- Hash = new Sha512Digest();
+ Digest = new Sha512Digest();
}
}
}
diff --git a/ModernKeePassLib/Cryptography/KeyDerivation/AesKdf.cs b/ModernKeePassLib/Cryptography/KeyDerivation/AesKdf.cs
index 9abf6da..91b7ca6 100644
--- a/ModernKeePassLib/Cryptography/KeyDerivation/AesKdf.cs
+++ b/ModernKeePassLib/Cryptography/KeyDerivation/AesKdf.cs
@@ -134,7 +134,7 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation
return null;
}
- internal static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
+ public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
ulong uNumRounds)
{
#if ModernKeePassLib || KeePassUAP
diff --git a/ModernKeePassLib/Cryptography/KeyDerivation/Argon2Kdf.Core.cs b/ModernKeePassLib/Cryptography/KeyDerivation/Argon2Kdf.Core.cs
index 1edefa8..c4b6356 100644
--- a/ModernKeePassLib/Cryptography/KeyDerivation/Argon2Kdf.Core.cs
+++ b/ModernKeePassLib/Cryptography/KeyDerivation/Argon2Kdf.Core.cs
@@ -34,7 +34,7 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
-
+using System.Threading.Tasks;
using ModernKeePassLib.Cryptography.Hash;
using ModernKeePassLib.Utility;
@@ -465,7 +465,10 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation
ti.Pass = r;
ti.Lane = (ulong)l;
ti.Slice = s;
-#if !ModernKeePassLib
+
+#if ModernKeePassLib
+ Task.Factory.StartNew(FillSegmentThr, ti);
+#else
if(!ThreadPool.QueueUserWorkItem(FillSegmentThr, ti))
{
Debug.Assert(false);
@@ -483,8 +486,8 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation
}
}
}
-
- private static void FillSegmentThr(object o)
+
+ private static void FillSegmentThr(object o)
{
Argon2ThreadInfo ti = (o as Argon2ThreadInfo);
if(ti == null) { Debug.Assert(false); return; }
diff --git a/ModernKeePassLib/Cryptography/SelfTest.cs b/ModernKeePassLib/Cryptography/SelfTest.cs
index 420c02a..4e7f627 100644
--- a/ModernKeePassLib/Cryptography/SelfTest.cs
+++ b/ModernKeePassLib/Cryptography/SelfTest.cs
@@ -417,7 +417,7 @@ namespace ModernKeePassLib.Cryptography
private static void TestBlake2b(Random r)
{
-#if !ModernKeePassLib && DEBUG
+#if DEBUG
Blake2b h = new Blake2b();
// ======================================================
@@ -676,35 +676,6 @@ namespace ModernKeePassLib.Cryptography
private static void HmacEval(byte[] pbKey, byte[] pbMsg,
byte[] pbExpc, string strID)
{
-#if ModernKeePassLib
- /*
- // WinRT
- var h = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256).CreateHash(CryptographicBuffer.CreateFromByteArray(pbKey));
- h.Append(CryptographicBuffer.CreateFromByteArray(pbMsg));
- var pbHash = h.GetValueAndReset().ToArray();
- if (!MemUtil.ArraysEqual(pbHash, pbExpc))
- throw new SecurityException("HMAC-SHA-256-" + strID);
-
- h.Append(CryptographicBuffer.CreateFromByteArray(pbMsg));
- pbHash = h.GetValueAndReset().ToArray();
- if (!MemUtil.ArraysEqual(pbHash, pbExpc))
- throw new SecurityException("HMAC-SHA-256-" + strID + "-R");
-
- // BouncyCastle
- // var h = new HMac(new Sha256Digest());
- //h.BlockUpdate(pbMsg, 0, pbMsg.Length);
- //byte[] pbHash = MemUtil.EmptyByteArray;
- //h.DoFinal(pbHash, 0);
- //if (!MemUtil.ArraysEqual(pbHash, pbExpc))
- // throw new SecurityException("HMAC-SHA-256-" + strID);
-
- // h.Reset();
- //h.BlockUpdate(pbMsg, 0, pbMsg.Length);
- //h.DoFinal(pbHash, 0);
- //if (!MemUtil.ArraysEqual(pbHash, pbExpc))
- // throw new SecurityException("HMAC-SHA-256-" + strID + "-R");*/
-#else
- // Original
using(HMACSHA256 h = new HMACSHA256(pbKey))
{
h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
@@ -723,7 +694,6 @@ namespace ModernKeePassLib.Cryptography
if(!MemUtil.ArraysEqual(pbHash, pbExpc))
throw new SecurityException("HMAC-SHA-256-" + strID + "-R");
}
-#endif
}
#endif
diff --git a/ModernKeePassLib/ModernKeePassLib.nuspec b/ModernKeePassLib/ModernKeePassLib.nuspec
index 099270b..7c8113f 100644
--- a/ModernKeePassLib/ModernKeePassLib.nuspec
+++ b/ModernKeePassLib/ModernKeePassLib.nuspec
@@ -10,7 +10,7 @@
https://github.com/wismna/ModernKeePass
false
Portable KeePass Password Management Library that targets .Net Standard and WinRT. Allows reading, editing and writing to KeePass 2.x databases.
- HMAC and Blake2B re-implemented.
+ KDBX 4 file format supported
Copyright © 2017 Geoffroy Bonneville
KeePass KeePassLib Portable PCL NetStandard
diff --git a/ModernKeePassLib/Serialization/HmacBlockStream.cs b/ModernKeePassLib/Serialization/HmacBlockStream.cs
index 70f80d6..a64a203 100644
--- a/ModernKeePassLib/Serialization/HmacBlockStream.cs
+++ b/ModernKeePassLib/Serialization/HmacBlockStream.cs
@@ -22,14 +22,15 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
-using Windows.Security.Cryptography;
-using Windows.Security.Cryptography.Core;
+
+#if ModernKeePassLib
using ModernKeePassLib.Cryptography.Hash;
+#elif !KeePassUAP
+using System.Security.Cryptography;
+#endif
+
using ModernKeePassLib.Resources;
using ModernKeePassLib.Utility;
-using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Crypto.Macs;
-using Org.BouncyCastle.Crypto.Parameters;
namespace ModernKeePassLib.Serialization
{
@@ -149,15 +150,7 @@ namespace ModernKeePassLib.Serialization
// We are computing the HMAC using SHA-256, whose internal
// block size is 512 bits; thus create a key that is 512
// bits long (using SHA-512)
-#if ModernKeePassLib
- byte[] pbBlockKey = MemUtil.EmptyByteArray;
- byte[] pbIndex = MemUtil.UInt64ToBytes(uBlockIndex);
- var h = new Sha512Digest();
- h.BlockUpdate(pbIndex, 0, pbIndex.Length);
- h.BlockUpdate(pbKey, 0, pbKey.Length);
- h.DoFinal(pbBlockKey, 0);
- h.Reset();
-#else
+
byte[] pbBlockKey;
using(SHA512Managed h = new SHA512Managed())
{
@@ -169,7 +162,6 @@ namespace ModernKeePassLib.Serialization
pbBlockKey = h.Hash;
}
-#endif
#if DEBUG
byte[] pbZero = new byte[64];
@@ -244,18 +236,6 @@ namespace ModernKeePassLib.Serialization
{
byte[] pbCmpHmac;
byte[] pbBlockKey = GetHmacKey64(m_pbKey, m_uBlockIndex);
-
-#if ModernKeePassLib
- var h = new HMac(new Sha256Digest());
- h.Init(new KeyParameter(pbBlockKey));
- h.BlockUpdate(pbBlockIndex, 0, pbBlockIndex.Length);
- h.BlockUpdate(pbBlockSize, 0, pbBlockSize.Length);
- if (m_pbBuffer.Length > 0)
- h.BlockUpdate(m_pbBuffer, 0, m_pbBuffer.Length);
- pbCmpHmac = MemUtil.EmptyByteArray;
- h.DoFinal(pbCmpHmac, 0);
- h.Reset();
-#else
using(HMACSHA256 h = new HMACSHA256(pbBlockKey))
{
h.TransformBlock(pbBlockIndex, 0, pbBlockIndex.Length,
@@ -271,7 +251,6 @@ namespace ModernKeePassLib.Serialization
pbCmpHmac = h.Hash;
}
-#endif
MemUtil.ZeroByteArray(pbBlockKey);
if(!MemUtil.ArraysEqual(pbCmpHmac, pbStoredHmac))
@@ -318,19 +297,6 @@ namespace ModernKeePassLib.Serialization
byte[] pbBlockHmac;
byte[] pbBlockKey = GetHmacKey64(m_pbKey, m_uBlockIndex);
-
-#if ModernKeePassLib
- var h = new HMac(new Sha256Digest());
- h.Init(new KeyParameter(pbBlockKey));
- h.BlockUpdate(pbBlockIndex, 0, pbBlockIndex.Length);
- h.BlockUpdate(pbBlockSize, 0, pbBlockSize.Length);
- if (cbBlockSize > 0)
- h.BlockUpdate(m_pbBuffer, 0, cbBlockSize);
-
- pbBlockHmac = MemUtil.EmptyByteArray;
- h.DoFinal(pbBlockHmac, 0);
- h.Reset();
-#else
using(HMACSHA256 h = new HMACSHA256(pbBlockKey))
{
h.TransformBlock(pbBlockIndex, 0, pbBlockIndex.Length,
@@ -345,7 +311,6 @@ namespace ModernKeePassLib.Serialization
pbBlockHmac = h.Hash;
}
-#endif
MemUtil.ZeroByteArray(pbBlockKey);
MemUtil.Write(m_sBase, pbBlockHmac);
diff --git a/ModernKeePassLib/Utility/MemUtil.cs b/ModernKeePassLib/Utility/MemUtil.cs
index 28a9ec1..18ea610 100644
--- a/ModernKeePassLib/Utility/MemUtil.cs
+++ b/ModernKeePassLib/Utility/MemUtil.cs
@@ -37,7 +37,7 @@ namespace ModernKeePassLib.Utility
///
public static class MemUtil
{
- internal static readonly byte[] EmptyByteArray = new byte[0];
+ public static readonly byte[] EmptyByteArray = new byte[0];
private static readonly uint[] m_vSBox = new uint[256] {
0xCD2FACB3, 0xE78A7F5C, 0x6F0803FC, 0xBCF6E230,