Setup solution

This commit is contained in:
Geoffroy BONNEVILLE
2019-07-25 16:39:43 +02:00
parent 81509be167
commit 1b2007e6dd
136 changed files with 35834 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
using System.IO;
using System.Text;
using ModernKeePassLib.Serialization;
using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Utility;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Xunit;
using System.Security.Cryptography;
using ModernKeePassLib.Cryptography;
namespace ModernKeePassLib.Test.Cryptography.Cipher
{
public class AesTests
{
// Test vector (official ECB test vector #356)
private readonly byte[] _pbReferenceCt =
{
0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7
};
private readonly byte[] _pbIv = new byte[16];
private readonly byte[] _pbTestKey = new byte[32];
private readonly byte[] _pbTestData =
{
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
[Fact]
public void TestEncryptStream()
{
var a = CryptoUtil.CreateAes();
if (a.BlockSize != 128) // AES block size
{
//Debug.Assert(false);
a.BlockSize = 128;
}
a.IV = _pbIv;
a.KeySize = 256;
a.Key = _pbTestKey;
a.Mode = CipherMode.ECB;
var iCrypt = a.CreateEncryptor();
iCrypt.TransformBlock(_pbTestData, 0, 16, _pbTestData, 0);
Assert.True(MemUtil.ArraysEqual(_pbTestData, _pbReferenceCt));
}
[Fact]
public void TestDecryptStream()
{
// Possible Mono Bug? This only works with size >= 48
using (var inStream = new MemoryStream(new byte[32]))
{
inStream.Write(_pbReferenceCt, 0, _pbReferenceCt.Length);
inStream.Position = 0;
var aes = new StandardAesEngine();
using (var outStream = aes.DecryptStream(inStream, _pbTestKey, _pbIv))
{
var outBytes = new BinaryReaderEx(outStream, Encoding.UTF8, string.Empty).ReadBytes(16);
Assert.True(MemUtil.ArraysEqual(outBytes, _pbTestData));
}
}
}
[Fact]
public void TestBouncyCastleAes()
{
var aesEngine = new AesEngine();
//var parametersWithIv = new ParametersWithIV(new KeyParameter(pbTestKey), pbIV);
aesEngine.Init(true, new KeyParameter(_pbTestKey));
Assert.Equal(_pbTestData.Length, aesEngine.GetBlockSize());
aesEngine.ProcessBlock(_pbTestData, 0, _pbTestData, 0);
Assert.True(MemUtil.ArraysEqual(_pbReferenceCt,_pbTestData));
}
}
}

View File

@@ -0,0 +1,203 @@
using System;
using System.Diagnostics;
using System.IO;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography.Cipher
{
public class Chacha20Tests
{
[Fact]
public void TestChacha20Cipher()
{
// ======================================================
// Test vector from RFC 7539, section 2.3.2
var pbKey = new byte[32];
for (var i = 0; i < 32; ++i) pbKey[i] = (byte)i;
var pbIV = new byte[12];
pbIV[3] = 0x09;
pbIV[7] = 0x4A;
var 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
};
var pb = new byte[64];
using (var c = new ChaCha20Cipher(pbKey, pbIV))
{
c.Seek(64, SeekOrigin.Begin); // Skip first block
c.Encrypt(pb, 0, pb.Length);
Assert.True(MemUtil.ArraysEqual(pb, pbExpc));
}
#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
};
var pb64 = new byte[64];
using (var c = new ChaCha20Cipher(pbKey, pbIV))
{
c.Encrypt(pb64, 0, pb64.Length); // Skip first block
c.Encrypt(pb, 0, pb.Length);
Assert.True(MemUtil.ArraysEqual(pb, pbExpc));
}
// ======================================================
// 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 (var msEnc = new MemoryStream())
{
using (var c = new ChaCha20Stream(msEnc, true, pbKey, pbIV))
{
var r = CryptoRandom.NewWeakRandom();
r.NextBytes(pb64);
c.Write(pb64, 0, pb64.Length); // Skip first block
var p = 0;
while (p < pb.Length)
{
var cb = r.Next(1, pb.Length - p + 1);
c.Write(pb, p, cb);
p += cb;
}
Debug.Assert(p == pb.Length);
}
var pbEnc0 = msEnc.ToArray();
var pbEnc = MemUtil.Mid(pbEnc0, 64, pbEnc0.Length - 64);
Assert.True(MemUtil.ArraysEqual(pbEnc, pbExpc));
using (var msCT = new MemoryStream(pbEnc0, false))
{
using (var cDec = new ChaCha20Stream(msCT, false,
pbKey, pbIV))
{
var pbPT = MemUtil.Read(cDec, pbEnc0.Length);
Assert.True(cDec.ReadByte() < 0);
Assert.True(MemUtil.ArraysEqual(MemUtil.Mid(pbPT, 0, 64), pb64));
Assert.True(MemUtil.ArraysEqual(MemUtil.Mid(pbPT, 64, pbEnc.Length), pb));
}
}
}
// ======================================================
// 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 (var c = new ChaCha20Cipher(pbKey, pbIV, true))
{
c.Decrypt(pb, 0, pb.Length);
Assert.True(MemUtil.ArraysEqual(pb, pbExpc));
}
#endif
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography.Cipher
{
public class Salsa20Tests
{
[Fact]
public void TestSalsa20Cipher()
{
var r = CryptoRandom.NewWeakRandom();
// Test values from official set 6, vector 3
var pbKey = new byte[] {
0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54,
0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC,
0x3F, 0x92, 0xE5, 0x38, 0x8B, 0xDE, 0x31, 0x84,
0xD7, 0x2A, 0x7D, 0xD0, 0x23, 0x76, 0xC9, 0x1C
};
var pbIv = new byte[] { 0x28, 0x8F, 0xF6, 0x5D,
0xC4, 0x2B, 0x92, 0xF9 };
var pbExpected = new byte[] {
0x5E, 0x5E, 0x71, 0xF9, 0x01, 0x99, 0x34, 0x03,
0x04, 0xAB, 0xB2, 0x2A, 0x37, 0xB6, 0x62, 0x5B
};
var pb = new byte[16];
var c = new Salsa20Cipher(pbKey, pbIv);
c.Encrypt(pb, 0, pb.Length);
Assert.True(MemUtil.ArraysEqual(pb, pbExpected));
// Extended test
var pbExpected2 = new byte[] {
0xAB, 0xF3, 0x9A, 0x21, 0x0E, 0xEE, 0x89, 0x59,
0x8B, 0x71, 0x33, 0x37, 0x70, 0x56, 0xC2, 0xFE
};
var pbExpected3 = new byte[] {
0x1B, 0xA8, 0x9D, 0xBD, 0x3F, 0x98, 0x83, 0x97,
0x28, 0xF5, 0x67, 0x91, 0xD5, 0xB7, 0xCE, 0x23
};
var nPos = Salsa20ToPos(c, r, pb.Length, 65536);
Array.Clear(pb, 0, pb.Length);
c.Encrypt(pb, 0, pb.Length);
Assert.True(MemUtil.ArraysEqual(pb, pbExpected2));
Salsa20ToPos(c, r, nPos + pb.Length, 131008);
Array.Clear(pb, 0, pb.Length);
c.Encrypt(pb, 0, pb.Length);
Assert.True(MemUtil.ArraysEqual(pb, pbExpected3));
var d = new Dictionary<string, bool>();
const int nRounds = 100;
for (var i = 0; i < nRounds; ++i)
{
var z = new byte[32];
c = new Salsa20Cipher(z, MemUtil.Int64ToBytes(i));
c.Encrypt(z, 0, z.Length);
d[MemUtil.ByteArrayToHexString(z)] = true;
}
Assert.Equal(nRounds, d.Count);
}
private static int Salsa20ToPos(Salsa20Cipher c, Random r, int nPos,
int nTargetPos)
{
var pb = new byte[512];
while (nPos < nTargetPos)
{
var x = r.Next(1, 513);
var nGen = Math.Min(nTargetPos - nPos, x);
c.Encrypt(pb, 0, nGen);
nPos += nGen;
}
return nTargetPos;
}
}
}

View File

@@ -0,0 +1,54 @@
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography
{
public class CryptoRandomStreamTests
{
private void TestGetRandomBytes(CryptoRandomStream stream)
{
const uint length = 16;
var bytes1 = stream.GetRandomBytes(length);
Assert.Equal(bytes1.Length, (int)length);
var bytes2 = stream.GetRandomBytes(length);
Assert.False(MemUtil.ArraysEqual(bytes2, bytes1));
}
[Fact]
public void TestGetRandomBytesCrsAlgorithmSalsa20()
{
var stream = new CryptoRandomStream(CrsAlgorithm.Salsa20, new byte[16]);
TestGetRandomBytes(stream);
}
[Fact]
public void TestGetRandomBytesCrsAlgorithmArcFourVariant()
{
var stream = new CryptoRandomStream(CrsAlgorithm.ArcFourVariant, new byte[16]);
TestGetRandomBytes(stream);
}
private void TestGetRandomInt64(CryptoRandomStream stream)
{
var value1 = stream.GetRandomUInt64();
var value2 = stream.GetRandomUInt64();
Assert.NotEqual(value2, value1);
}
[Fact]
public void TestGetRandomInt64AlgorithmSalsa20()
{
var stream = new CryptoRandomStream(CrsAlgorithm.Salsa20, new byte[16]);
TestGetRandomInt64(stream);
}
[Fact]
public void TestGetRandomInt64AlgorithmArcFourVariant()
{
var stream = new CryptoRandomStream(CrsAlgorithm.ArcFourVariant, new byte[16]);
TestGetRandomInt64(stream);
}
}
}

View File

@@ -0,0 +1,37 @@
using ModernKeePassLib.Cryptography;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography
{
public class CryptoRandomTests
{
[Fact]
public void TestAddEntropy()
{
// just making sure it does not throw an exception
CryptoRandom.Instance.AddEntropy(new byte[1]);
}
[Fact]
public void TestGetRandomBytes()
{
const int length = 32;
var bytes1 = CryptoRandom.Instance.GetRandomBytes(length);
Assert.Equal(bytes1.Length, length);
var bytes2 = CryptoRandom.Instance.GetRandomBytes(length);
Assert.NotEqual(bytes2, bytes1);
}
[Fact]
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.True(count2 > count1);
}
}
}

View File

@@ -0,0 +1,100 @@
using System;
using System.Text;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Cryptography.Hash;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography.Hash
{
public class Blake2bTests
{
[Fact]
public void TestBlake2bUtf8()
{
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.True(MemUtil.ArraysEqual(pbC, pbExpc));
}
[Fact]
public void TestBlake2bEmpty()
{
// ======================================================
// Computed using the official b2sum tool
Blake2b h = new Blake2b();
var 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
};
var pbC = h.ComputeHash(new byte[0]);
Assert.True(MemUtil.ArraysEqual(pbC, pbExpc));
}
[Fact]
public void TestBlake2bString()
{
// ======================================================
// Computed using the official b2sum tool
Blake2b h = new Blake2b();
string strS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.:,;_-\r\n";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; ++i) sb.Append(strS);
var pbData = StrUtil.Utf8.GetBytes(sb.ToString());
var 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.Equal(p, pbData.Length);
h.TransformFinalBlock(new byte[0], 0, 0);
Assert.True(MemUtil.ArraysEqual(h.Hash, pbExpc));
h.Clear();
}
}
}

View File

@@ -0,0 +1,116 @@
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Utility;
using System.Security.Cryptography;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography.Hash
{
public class HmacTests
{
[Fact]
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);
}
[Fact]
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);
}
[Fact]
public void TestHmacSha1ComputeHash()
{
var expectedHash = "AC2C2E614882CE7158F69B7E3B12114465945D01";
var message = StrUtil.Utf8.GetBytes("testing123");
var key = StrUtil.Utf8.GetBytes("hello");
using (var result = new HMACSHA1(key))
{
Assert.Equal(ByteToString(result.ComputeHash(message)), expectedHash);
}
}
[Fact]
public void TestHmacSha256ComputeHash()
{
var expectedHash = "09C1BD2DE4E5659C0EFAF9E6AE4723E9CF96B69609B4E562F6AFF1745D7BF4E0";
var message = StrUtil.Utf8.GetBytes("testing123");
var key = StrUtil.Utf8.GetBytes("hello");
using (var result = new HMACSHA256(key))
{
Assert.Equal(ByteToString(result.ComputeHash(message)), expectedHash);
}
}
private static string ByteToString(byte[] buff)
{
string sbinary = "";
for (int i = 0; i < buff.Length; i++)
{
sbinary += buff[i].ToString("X2"); // hex format
}
return (sbinary);
}
[Fact]
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.Equal(HmacOtp.Generate(pbSecret, (ulong)i, 6, false, -1), 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(new byte[0], 0, 0);
byte[] pbHash = h.Hash;
Assert.True(MemUtil.ArraysEqual(pbHash, pbExpc));
// Reuse the object
h.Initialize();
h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
h.TransformFinalBlock(new byte[0], 0, 0);
pbHash = h.Hash;
Assert.True(MemUtil.ArraysEqual(pbHash, pbExpc));
}
}
}
}

View File

@@ -0,0 +1,73 @@
using ModernKeePassLib.Utility;
using System.Security.Cryptography;
using ModernKeePassLib.Cryptography;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography.Hash
{
public class ShaManagedTests
{
[Fact]
public void TestSha256()
{
var r = CryptoRandom.NewWeakRandom();
var pbData = new byte[517];
r.NextBytes(pbData);
byte[] pbH1;
using (var h1 = new SHA256Managed())
{
var i = 0;
while (i != pbData.Length)
{
var cb = r.Next(pbData.Length - i) + 1;
h1.TransformBlock(pbData, i, cb, pbData, i);
i += cb;
}
h1.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
pbH1 = h1.Hash;
}
byte[] pbH2;
using (var h2 = new SHA256Managed())
{
pbH2 = h2.ComputeHash(pbData);
}
Assert.True(MemUtil.ArraysEqual(pbH1, pbH2));
}
[Fact]
public void TestSha256ComputeHash()
{
var expectedHash = "B822F1CD2DCFC685B47E83E3980289FD5D8E3FF3A82DEF24D7D1D68BB272EB32";
var message = StrUtil.Utf8.GetBytes("testing123");
using (var result = new SHA256Managed())
{
Assert.Equal(ByteToString(result.ComputeHash(message)), expectedHash);
}
}
[Fact]
public void TestSha512ComputeHash()
{
var expectedHash = "4120117B3190BA5E24044732B0B09AA9ED50EB1567705ABCBFA78431A4E0A96B1152ED7F4925966B1C82325E186A8100E692E6D2FCB6702572765820D25C7E9E";
var message = StrUtil.Utf8.GetBytes("testing123");
using (var result = new SHA512Managed())
{
Assert.Equal(ByteToString(result.ComputeHash(message)), expectedHash);
}
}
private static string ByteToString(byte[] buff)
{
var sbinary = "";
for (var i = 0; i < buff.Length; i++)
{
sbinary += buff[i].ToString("X2"); // hex format
}
return (sbinary);
}
}
}

View File

@@ -0,0 +1,81 @@
using System.IO;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography
{
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
};
[Fact]
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.Equal(read, data);
}
// When the StreamReader is disposed, it calls Dispose on the
//HasingStreamEx, which computes the hash.
Assert.True(MemUtil.ArraysEqual(hs.Hash, sha256HashOfData));
}
}
}
[Fact]
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.True(MemUtil.ArraysEqual(hs.Hash, sha256HashOfData));
}
}
using (var ms = new MemoryStream(bytes))
{
using (var sr = new StreamReader(ms))
{
var read = sr.ReadLine();
Assert.Equal(read, data);
}
}
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Text;
using ModernKeePassLib.Cryptography;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography
{
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"
};
[Fact]
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.Equal(hotp, expectedHOTP[i]);
}
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Cryptography.KeyDerivation;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography.KeyDerivation
{
public class AesKdfTests
{
[Fact]
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.True(AesKdf.TransformKeyManaged(pbMan, pbSeed, uRounds));
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.True(MemUtil.ArraysEqual(pbMan, pbKdf));
}
}
}

View File

@@ -0,0 +1,145 @@
using ModernKeePassLib.Cryptography.KeyDerivation;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Cryptography.KeyDerivation
{
public class Argon2Tests
{
[Fact]
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.Equal(0x13U, p.GetUInt32(Argon2Kdf.ParamVersion, 0));
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.True(MemUtil.ArraysEqual(pb, pbExpc));
// ======================================================
// 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.True(MemUtil.ArraysEqual(pb, pbExpc));
// ======================================================
// 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.True(MemUtil.ArraysEqual(pb, pbExpc));
// ======================================================
// 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.True(MemUtil.ArraysEqual(pb, pbExpc));
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.True(MemUtil.ArraysEqual(pb, pbExpc));
// TODO: Out of memory exception
/*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.IsTrue(MemUtil.ArraysEqual(pb, pbExpc));*/
}
}
}

View File

@@ -0,0 +1,34 @@
using ModernKeePassLib.Cryptography.KeyDerivation;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Keys
{
public class CompositeKeyTests
{
[Fact]
public void TestGenerateKey32()
{
var originalKey = new byte[32];
var expectedKey = new byte[]
{
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();
AesKdf kdf = new AesKdf();
KdfParameters p = kdf.GetDefaultParameters();
p.SetUInt64(AesKdf.ParamRounds, rounds);
p.SetByteArray(AesKdf.ParamSeed, originalKey);
var key = composite.GenerateKey32(p);
Assert.NotNull(key);
var keyData = key.ReadData();
Assert.True(MemUtil.ArraysEqual(keyData, expectedKey));
}
}
}

View File

@@ -0,0 +1,34 @@
using ModernKeePassLib.Keys;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Keys
{
public class KcpCustomKeyTests
{
static readonly byte[] testData =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
[Fact]
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.True(MemUtil.ArraysEqual(keyData, testData));
key = new KcpCustomKey("test2", testData, true);
keyData = key.KeyData.ReadData();
Assert.True(MemUtil.ArraysEqual(keyData, expectedHash));
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.IO;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Utility;
using Windows.Storage;
using Xunit;
namespace ModernKeePassLib.Test.Keys
{
public class KcpKeyFileTests
{
private const string TestCreateFile = "TestCreate.xml";
private const string TestKey = "0123456789";
private const string ExpectedFileStart =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
"<KeyFile>\r\n" +
"\t<Meta>\r\n" +
"\t\t<Version>1.00</Version>\r\n" +
"\t</Meta>\r\n" +
"\t<Key>\r\n" +
"\t\t<Data>";
private const string ExpectedFileEnd = "</Data>\r\n\t</Key>\r\n</KeyFile>";
[Fact]
public void TestConstruct()
{
var expectedKeyData = new byte[]
{
0x95, 0x94, 0xdc, 0xb9, 0x91, 0xc6, 0x65, 0xa0,
0x81, 0xf6, 0x6f, 0xca, 0x07, 0x1a, 0x30, 0xd1,
0x1d, 0x65, 0xcf, 0x8d, 0x9c, 0x60, 0xfb, 0xe6,
0x45, 0xfc, 0xc8, 0x92, 0xbd, 0xeb, 0xaf, 0xc3
};
var folder = StorageFolder.GetFolderFromPathAsync(Path.GetTempPath()).GetAwaiter().GetResult();
var file = folder.CreateFileAsync(TestCreateFile, CreationCollisionOption.ReplaceExisting).GetAwaiter().GetResult();
using (var fs = file.OpenStreamForWriteAsync().GetAwaiter().GetResult())
{
using (var sw = new StreamWriter(fs))
{
sw.Write(ExpectedFileStart);
sw.Write(TestKey);
sw.Write(ExpectedFileEnd);
}
}
try
{
var keyFile = new KcpKeyFile(file);
var keyData = keyFile.KeyData.ReadData();
Assert.True(MemUtil.ArraysEqual(keyData, expectedKeyData));
}
finally
{
file.DeleteAsync().GetAwaiter().GetResult();
}
}
[Fact]
public void TestCreate()
{
var folder = StorageFolder.GetFolderFromPathAsync(Path.GetTempPath()).GetAwaiter().GetResult();
var file = folder.CreateFileAsync(TestCreateFile, CreationCollisionOption.ReplaceExisting).GetAwaiter().GetResult();
KcpKeyFile.Create(file, null);
try
{
var fileContents = FileIO.ReadTextAsync(file).GetAwaiter().GetResult();
Assert.Equal(185, fileContents.Length);
Assert.StartsWith(ExpectedFileStart, fileContents);
Assert.EndsWith(ExpectedFileEnd, fileContents);
}
finally
{
file.DeleteAsync().GetAwaiter().GetResult();
}
}
}
}

View File

@@ -0,0 +1,28 @@
using ModernKeePassLib.Keys;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Keys
{
public class KcpPasswordTests
{
const string testPassword = "password";
[Fact]
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.True(MemUtil.ArraysEqual(keyData, expectedHash));
}
}
}

View File

@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
<PackageReference Include="System.Runtime.WindowsRuntime" Version="4.3.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ModernKeePassLib\ModernKeePassLib.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Windows">
<HintPath>..\ModernKeePassLib\Libs\Windows.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
</Reference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,110 @@
using System.Text;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Security;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Security
{
public class ProtectedObjectsTests
{
private readonly Encoding _enc = StrUtil.Utf8;
[Fact]
public void TestAreBinaryObjectsProtected()
{
var pbData = _enc.GetBytes("Test Test Test Test");
var pb = new ProtectedBinary(true, pbData);
Assert.True(pb.IsProtected);
var pbDec = pb.ReadData();
Assert.True(MemUtil.ArraysEqual(pbData, pbDec));
Assert.True(pb.IsProtected);
var pbData2 = _enc.GetBytes("Test Test Test Test");
var pbData3 = _enc.GetBytes("Test Test Test Test Test");
var pb2 = new ProtectedBinary(true, pbData2);
var pb3 = new ProtectedBinary(true, pbData3);
Assert.True(pb.Equals(pb2));
Assert.False(pb.Equals(pb3));
Assert.False(pb2.Equals(pb3));
Assert.Equal(pb.GetHashCode(), pb2.GetHashCode());
Assert.True(pb.Equals((object) pb2));
Assert.False(pb.Equals((object) pb3));
Assert.False(pb2.Equals((object) pb3));
}
[Fact]
public void TestIsEmptyProtectedStringEmpty()
{
var ps = new ProtectedString();
Assert.Equal(0, ps.Length);
Assert.True(ps.IsEmpty);
Assert.Equal(0, ps.ReadString().Length);
}
[Fact]
public void TestAreEqualStringsProtected()
{
var ps = new ProtectedString(true, "Test");
var ps2 = new ProtectedString(true, _enc.GetBytes("Test"));
Assert.False(ps.IsEmpty);
var pbData = ps.ReadUtf8();
var pbData2 = ps2.ReadUtf8();
Assert.True(MemUtil.ArraysEqual(pbData, pbData2));
Assert.Equal(4, pbData.Length);
Assert.Equal(ps.ReadString(), ps2.ReadString());
pbData = ps.ReadUtf8();
pbData2 = ps2.ReadUtf8();
Assert.True(MemUtil.ArraysEqual(pbData, pbData2));
Assert.True(ps.IsProtected);
Assert.True(ps2.IsProtected);
}
[Fact]
public void TestIsRandomStringProtected()
{
var r = CryptoRandom.NewWeakRandom();
var str = string.Empty;
var ps = new ProtectedString();
for (var i = 0; i < 100; ++i)
{
var bProt = ((r.Next() % 4) != 0);
ps = ps.WithProtection(bProt);
var x = r.Next(str.Length + 1);
var c = r.Next(20);
var ch = (char) r.Next(1, 256);
var strIns = new string(ch, c);
str = str.Insert(x, strIns);
ps = ps.Insert(x, strIns);
Assert.Equal(bProt, ps.IsProtected);
Assert.Equal(str, ps.ReadString());
ps = ps.WithProtection(bProt);
x = r.Next(str.Length);
c = r.Next(str.Length - x + 1);
str = str.Remove(x, c);
ps = ps.Remove(x, c);
Assert.Equal(bProt, ps.IsProtected);
Assert.Equal(str, ps.ReadString());
}
}
[Fact]
public void TestAreConcatenatedStringsProtected()
{
var ps = new ProtectedString(false, "ABCD");
var ps2 = new ProtectedString(true, "EFG");
ps += (ps2 + "HI");
Assert.True(ps.Equals(new ProtectedString(true, "ABCDEFGHI"), true));
Assert.True(ps.Equals(new ProtectedString(false, "ABCDEFGHI"), false));
}
}
}

View File

@@ -0,0 +1,72 @@
using System.IO;
using ModernKeePassLib.Serialization;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Serialization
{
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
};
[Fact]
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.True(MemUtil.ArraysEqual(bytes, data));
Assert.Throws<EndOfStreamException>(() => br.ReadByte());
}
}
}
}
[Fact]
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.True(MemUtil.ArraysEqual(buffer, hashStreamData));
}
}
}
}

View File

@@ -0,0 +1,170 @@
using System;
using System.Globalization;
using System.IO;
using System.Text;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Security;
using ModernKeePassLib.Serialization;
using ModernKeePassLib.Collections;
using Xunit;
namespace ModernKeePassLib.Test.Serialization
{
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 = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\r\n" +
"<KeePassFile>\r\n" +
"\t<Meta>\r\n" +
"\t\t<Generator>" + TestLocalizedAppName + "</Generator>\r\n" +
"\t\t<DatabaseName>" + TestDatabaseName + "</DatabaseName>\r\n" +
"\t\t<DatabaseNameChanged>2017-10-23T08:03:55Z</DatabaseNameChanged>\r\n" +
"\t\t<DatabaseDescription>" + TestDatabaseDescription + "</DatabaseDescription>\r\n" +
"\t\t<DatabaseDescriptionChanged>2017-10-23T08:03:55Z</DatabaseDescriptionChanged>\r\n" +
"\t\t<DefaultUserName>" + TestDefaultUserName + "</DefaultUserName>\r\n" +
"\t\t<DefaultUserNameChanged>2017-10-23T08:03:55Z</DefaultUserNameChanged>\r\n" +
"\t\t<MaintenanceHistoryDays>365</MaintenanceHistoryDays>\r\n" +
//"\t\t<Color>" + testColor + "</Color>\r\n" +
"\t\t<Color></Color>\r\n" +
"\t\t<MasterKeyChanged>2017-10-23T08:03:55Z</MasterKeyChanged>\r\n" +
"\t\t<MasterKeyChangeRec>-1</MasterKeyChangeRec>\r\n" +
"\t\t<MasterKeyChangeForce>-1</MasterKeyChangeForce>\r\n" +
"\t\t<MemoryProtection>\r\n" +
"\t\t\t<ProtectTitle>False</ProtectTitle>\r\n" +
"\t\t\t<ProtectUserName>False</ProtectUserName>\r\n" +
"\t\t\t<ProtectPassword>True</ProtectPassword>\r\n" +
"\t\t\t<ProtectURL>False</ProtectURL>\r\n" +
"\t\t\t<ProtectNotes>False</ProtectNotes>\r\n" +
"\t\t</MemoryProtection>\r\n" +
"\t\t<RecycleBinEnabled>True</RecycleBinEnabled>\r\n" +
"\t\t<RecycleBinUUID>AAAAAAAAAAAAAAAAAAAAAA==</RecycleBinUUID>\r\n" +
"\t\t<RecycleBinChanged>2017-10-23T08:03:55Z</RecycleBinChanged>\r\n" +
"\t\t<EntryTemplatesGroup>AAAAAAAAAAAAAAAAAAAAAA==</EntryTemplatesGroup>\r\n" +
"\t\t<EntryTemplatesGroupChanged>2017-10-23T08:03:55Z</EntryTemplatesGroupChanged>\r\n" +
"\t\t<HistoryMaxItems>10</HistoryMaxItems>\r\n" +
"\t\t<HistoryMaxSize>6291456</HistoryMaxSize>\r\n" +
"\t\t<LastSelectedGroup>AAAAAAAAAAAAAAAAAAAAAA==</LastSelectedGroup>\r\n" +
"\t\t<LastTopVisibleGroup>AAAAAAAAAAAAAAAAAAAAAA==</LastTopVisibleGroup>\r\n" +
"\t\t<Binaries />\r\n" +
"\t\t<CustomData />\r\n" +
"\t</Meta>\r\n" +
"\t<Root>\r\n" +
"\t\t<Group>\r\n" +
"\t\t\t<UUID>AAAAAAAAAAAAAAAAAAAAAA==</UUID>\r\n" +
"\t\t\t<Name>" + TestRootGroupName + "</Name>\r\n" +
"\t\t\t<Notes>" + TestRootGroupNotes + "</Notes>\r\n" +
"\t\t\t<IconID>49</IconID>\r\n" +
"\t\t\t<Times>\r\n" +
"\t\t\t\t<CreationTime>2017-10-23T08:03:55Z</CreationTime>\r\n" +
"\t\t\t\t<LastModificationTime>2017-10-23T08:03:55Z</LastModificationTime>\r\n" +
"\t\t\t\t<LastAccessTime>2017-10-23T08:03:55Z</LastAccessTime>\r\n" +
"\t\t\t\t<ExpiryTime>2017-10-23T08:03:55Z</ExpiryTime>\r\n" +
"\t\t\t\t<Expires>False</Expires>\r\n" +
"\t\t\t\t<UsageCount>0</UsageCount>\r\n" +
"\t\t\t\t<LocationChanged>2017-10-23T08:03:55Z</LocationChanged>\r\n" +
"\t\t\t</Times>\r\n" +
"\t\t\t<IsExpanded>True</IsExpanded>\r\n" +
"\t\t\t<DefaultAutoTypeSequence>" + TestRootGroupDefaultAutoTypeSequence + "</DefaultAutoTypeSequence>\r\n" +
"\t\t\t<EnableAutoType>null</EnableAutoType>\r\n" +
"\t\t\t<EnableSearching>null</EnableSearching>\r\n" +
"\t\t\t<LastTopVisibleEntry>AAAAAAAAAAAAAAAAAAAAAA==</LastTopVisibleEntry>\r\n" +
"\t\t</Group>\r\n" +
"\t\t<DeletedObjects />\r\n" +
"\t</Root>\r\n" +
"</KeePassFile>";
const string TestDate = "2017-10-23T08:03:55Z";
[Fact]
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.Equal(PwCompressionAlgorithm.GZip, database.Compression);
//Assert.That (database.CustomData, Is.EqualTo ());
Assert.True(database.CustomIcons.Count == 0);
}
[Fact]
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, CultureInfo.CurrentCulture, DateTimeStyles.AdjustToUniversal);
//var date = DateTime.UtcNow;
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, 0, buffer.Length).Replace("\0", "");
if (typeof(KdbxFile).Namespace.StartsWith("KeePassLib."))
{
// Upstream KeePassLib does not specify line endings for XmlTextWriter,
// so it uses native line endings.
fileContents = fileContents.Replace("\n", "\r\n");
}
Assert.Equal(fileContents, TestDatabase);
}
[Fact]
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<PwEntry>();
database.RootGroup.SearchEntries(sp, listStorage);
Assert.Equal(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.Equal(1U, listStorage.UCount);
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Utility
{
public class GfxUtilTests
{
// 16x16 all white PNG file, base64 encoded
const string testImageData =
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAA" +
"LEwEAmpwYAAAAB3RJTUUH3wMOFgIgmTCUMQAAABl0RVh0Q29tbWVudABDcmVhdG" +
"VkIHdpdGggR0lNUFeBDhcAAAAaSURBVCjPY/z//z8DKYCJgUQwqmFUw9DRAABVb" +
"QMdny4VogAAAABJRU5ErkJggg==";
//[Fact]
//public void TestLoadImage ()
//{
// var testData = Convert.FromBase64String (testImageData);
// var image = GfxUtil.ScaleImage(testData, 16, 16, ScaleTransformFlags.UIIcon);
// //var image = GfxUtil.LoadImage(testData);
// Assert.Equal(image.Width, 16);
// Assert.Equal(image.Height, 16);
//}
}
}

View File

@@ -0,0 +1,88 @@
using System.Text;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Utility;
using Xunit;
namespace ModernKeePassLib.Test.Utility
{
public class MemUtilTests
{
private byte[] _pb = CryptoRandom.Instance.GetRandomBytes((uint)CryptoRandom.NewWeakRandom().Next(0, 0x2FFFF));
[Fact]
public void TestGzip()
{
var pbCompressed = MemUtil.Compress(_pb);
Assert.True(MemUtil.ArraysEqual(MemUtil.Decompress(pbCompressed), _pb));
}
[Fact]
public void TestMemUtil()
{
var enc = StrUtil.Utf8;
_pb = enc.GetBytes("012345678901234567890a");
var pbN = enc.GetBytes("9012");
Assert.Equal(9, MemUtil.IndexOf(_pb, pbN));
pbN = enc.GetBytes("01234567890123");
Assert.Equal(0, MemUtil.IndexOf(_pb, pbN));
pbN = enc.GetBytes("a");
Assert.Equal(21, MemUtil.IndexOf(_pb, pbN));
pbN = enc.GetBytes("0a");
Assert.Equal(20, MemUtil.IndexOf(_pb, pbN));
pbN = enc.GetBytes("1");
Assert.Equal(1, MemUtil.IndexOf(_pb, pbN));
pbN = enc.GetBytes("b");
Assert.True(MemUtil.IndexOf(_pb, pbN) < 0);
pbN = enc.GetBytes("012b");
Assert.True(MemUtil.IndexOf(_pb, pbN) < 0);
}
[Fact]
public void TestBase32()
{
var pbRes = MemUtil.ParseBase32("MY======");
var pbExp = Encoding.UTF8.GetBytes("f");
Assert.True(MemUtil.ArraysEqual(pbRes, pbExp));
pbRes = MemUtil.ParseBase32("MZXQ====");
pbExp = Encoding.UTF8.GetBytes("fo");
Assert.True(MemUtil.ArraysEqual(pbRes, pbExp));
pbRes = MemUtil.ParseBase32("MZXW6===");
pbExp = Encoding.UTF8.GetBytes("foo");
Assert.True(MemUtil.ArraysEqual(pbRes, pbExp));
pbRes = MemUtil.ParseBase32("MZXW6YQ=");
pbExp = Encoding.UTF8.GetBytes("foob");
Assert.True(MemUtil.ArraysEqual(pbRes, pbExp));
pbRes = MemUtil.ParseBase32("MZXW6YTB");
pbExp = Encoding.UTF8.GetBytes("fooba");
Assert.True(MemUtil.ArraysEqual(pbRes, pbExp));
pbRes = MemUtil.ParseBase32("MZXW6YTBOI======");
pbExp = Encoding.UTF8.GetBytes("foobar");
Assert.True(MemUtil.ArraysEqual(pbRes, pbExp));
pbRes = MemUtil.ParseBase32("JNSXSIDQOJXXM2LEMVZCAYTBONSWIIDPNYQG63TFFV2GS3LFEBYGC43TO5XXEZDTFY======");
pbExp = Encoding.UTF8.GetBytes("Key provider based on one-time passwords.");
Assert.True(MemUtil.ArraysEqual(pbRes, pbExp));
}
[Fact]
public void TestMemUtil2()
{
var i = 0 - 0x10203040;
var pbRes = MemUtil.Int32ToBytes(i);
Assert.Equal("C0CFDFEF", MemUtil.ByteArrayToHexString(pbRes));
Assert.Equal(MemUtil.BytesToUInt32(pbRes), (uint)i);
Assert.Equal(MemUtil.BytesToInt32(pbRes), i);
}
}
}