diff --git a/mRemoteNGTests/Security/KeyDerivation/Pkcs5S2KeyGeneratorTests.cs b/mRemoteNGTests/Security/KeyDerivation/Pkcs5S2KeyGeneratorTests.cs new file mode 100644 index 000000000..c5985b07c --- /dev/null +++ b/mRemoteNGTests/Security/KeyDerivation/Pkcs5S2KeyGeneratorTests.cs @@ -0,0 +1,91 @@ +using System; +using mRemoteNG.Security.KeyDerivation; +using NUnit.Framework; + + +namespace mRemoteNGTests.Security.KeyDerivation +{ + public class Pkcs5S2KeyGeneratorTests + { + [Test] + public void DefaultConstructorThrowsNoException() + { + // ReSharper disable once ObjectCreationAsStatement + Assert.DoesNotThrow(() => new Pkcs5S2KeyGenerator()); + } + + [Test] + public void CreatingGeneratorWithLowIterationCountThrowsError() + { + // ReSharper disable once ObjectCreationAsStatement + Assert.Throws(() => new Pkcs5S2KeyGenerator(256, 999)); + } + + [Test] + public void CreatingGeneratorWithNegativeKeyBitSizeThrowsError() + { + // ReSharper disable once ObjectCreationAsStatement + Assert.Throws(() => new Pkcs5S2KeyGenerator(-1)); + } + + [Test] + public void IdenticalParametersProduceIdenticalKeys() + { + var keyDerivationFunction = new Pkcs5S2KeyGenerator(); + var key1 = keyDerivationFunction.DeriveKey("", new byte[0]); + var key2 = keyDerivationFunction.DeriveKey("", new byte[0]); + Assert.That(key1, Is.EquivalentTo(key2)); + } + + [Test] + public void DifferingIterationsProduceDifferingKeys() + { + var keyDerivationFunction1 = new Pkcs5S2KeyGenerator(256, 1001); + var keyDerivationFunction2 = new Pkcs5S2KeyGenerator(256, 1002); + var key1 = keyDerivationFunction1.DeriveKey("", new byte[0]); + var key2 = keyDerivationFunction2.DeriveKey("", new byte[0]); + Assert.That(key1, Is.Not.EquivalentTo(key2)); + } + + [Test] + public void DifferingKeysizeProduceDifferingKeys() + { + var keyDerivationFunction1 = new Pkcs5S2KeyGenerator(); + var keyDerivationFunction2 = new Pkcs5S2KeyGenerator(512); + var key1 = keyDerivationFunction1.DeriveKey("", new byte[0]); + var key2 = keyDerivationFunction2.DeriveKey("", new byte[0]); + Assert.That(key1, Is.Not.EquivalentTo(key2)); + } + + [Test] + public void DifferingPasswordsProduceDifferingKeys() + { + var keyDerivationFunction = new Pkcs5S2KeyGenerator(); + var key1 = keyDerivationFunction.DeriveKey("a", new byte[0]); + var key2 = keyDerivationFunction.DeriveKey("b", new byte[0]); + Assert.That(key1, Is.Not.EquivalentTo(key2)); + } + + [Test] + public void DifferingSaltsProduceDifferingKeys() + { + var keyDerivationFunction = new Pkcs5S2KeyGenerator(); + var key1 = keyDerivationFunction.DeriveKey("", new byte[0]); + var key2 = keyDerivationFunction.DeriveKey("", new byte[] {1}); + Assert.That(key1, Is.Not.EquivalentTo(key2)); + } + + [TestCase(0)] + [TestCase(1)] + [TestCase(8)] + [TestCase(9)] + [TestCase(256)] + [TestCase(333)] + public void KeyLengthIsKeyBitSizeDividedBy8(int keyBitSize) + { + var keyDerivationFunction = new Pkcs5S2KeyGenerator(keyBitSize); + var key = keyDerivationFunction.DeriveKey("", new byte[0]); + Assert.That(key.Length, Is.EqualTo(keyBitSize / 8)); + } + } +} \ No newline at end of file diff --git a/mRemoteNGTests/mRemoteNGTests.csproj b/mRemoteNGTests/mRemoteNGTests.csproj index 36651ded5..905babcda 100644 --- a/mRemoteNGTests/mRemoteNGTests.csproj +++ b/mRemoteNGTests/mRemoteNGTests.csproj @@ -117,6 +117,7 @@ + diff --git a/mRemoteV1/Security/KeyDerivation/Pkcs5S2KeyGenerator.cs b/mRemoteV1/Security/KeyDerivation/Pkcs5S2KeyGenerator.cs index 2bc3c907b..8d01c88b8 100644 --- a/mRemoteV1/Security/KeyDerivation/Pkcs5S2KeyGenerator.cs +++ b/mRemoteV1/Security/KeyDerivation/Pkcs5S2KeyGenerator.cs @@ -1,4 +1,5 @@ -using Org.BouncyCastle.Crypto; +using System; +using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; @@ -12,6 +13,10 @@ namespace mRemoteNG.Security.KeyDerivation public Pkcs5S2KeyGenerator(int keyBitSize = 256, int iterations = 1000) { + if (iterations < 1000) + throw new ArgumentOutOfRangeException($"Minimum value of {nameof(iterations)} is 1000"); + if (keyBitSize < 0) + throw new ArgumentOutOfRangeException($"{nameof(keyBitSize)} must be positive"); _keyBitSize = keyBitSize; _iterations = iterations; }