From da44bba3fe232c6cba9e8dcf31e0c44ae2e40afe Mon Sep 17 00:00:00 2001 From: David Sparer Date: Tue, 24 Jan 2017 13:35:03 -0700 Subject: [PATCH] created a builder class for creating a crypto provider from an xml element --- .../Security/XmlCryptoProviderBuilderTests.cs | 66 +++++++++++++++++++ mRemoteNGTests/mRemoteNGTests.csproj | 1 + .../Security/CryptographyProviderFactory.cs | 7 ++ .../Security/XmlCryptoProviderBuilder.cs | 39 +++++++++++ mRemoteV1/mRemoteV1.csproj | 1 + 5 files changed, 114 insertions(+) create mode 100644 mRemoteNGTests/Security/XmlCryptoProviderBuilderTests.cs create mode 100644 mRemoteV1/Security/XmlCryptoProviderBuilder.cs diff --git a/mRemoteNGTests/Security/XmlCryptoProviderBuilderTests.cs b/mRemoteNGTests/Security/XmlCryptoProviderBuilderTests.cs new file mode 100644 index 000000000..01c2f60ef --- /dev/null +++ b/mRemoteNGTests/Security/XmlCryptoProviderBuilderTests.cs @@ -0,0 +1,66 @@ +using System; +using System.Xml.Linq; +using mRemoteNG.Security; +using mRemoteNG.Security.SymmetricEncryption; +using NUnit.Framework; + + +namespace mRemoteNGTests.Security +{ + public class XmlCryptoProviderBuilderTests + { + [Test] + public void BuildsCorrectEncryptionEngine() + { + var element = BuildValidElement(); + var builder = new XmlCryptoProviderBuilder(element); + var cryptoProvider = builder.Build(); + Assert.That(cryptoProvider.CipherEngine, Is.EqualTo(BlockCipherEngines.Serpent)); + } + + [Test] + public void BuildsCorrectCipherMode() + { + var element = BuildValidElement(); + var builder = new XmlCryptoProviderBuilder(element); + var cryptoProvider = builder.Build(); + Assert.That(cryptoProvider.CipherMode, Is.EqualTo(BlockCipherModes.EAX)); + } + + [Test] + public void BuildsCorrectKdfIterations() + { + var element = BuildValidElement(); + var builder = new XmlCryptoProviderBuilder(element); + var cryptoProvider = builder.Build(); + Assert.That(cryptoProvider.KeyDerivationIterations, Is.EqualTo(1234)); + } + + [Test] + public void CantPassNullIntoConstructor() + { + Assert.Throws(() => + { + // ReSharper disable once ObjectCreationAsStatement + new XmlCryptoProviderBuilder(null); + }); + } + + [Test] + public void ReturnsOldProviderTypeIfXmlIsntValid() + { + var badElement = new XElement("BadElement"); + var builder = new XmlCryptoProviderBuilder(badElement); + var cryptoProvider = builder.Build(); + Assert.That(cryptoProvider, Is.TypeOf()); + } + + private static XElement BuildValidElement() + { + return new XElement("TestElement", + new XAttribute("EncryptionEngine", "Serpent"), + new XAttribute("BlockCipherMode", "EAX"), + new XAttribute("KdfIterations", "1234")); + } + } +} \ No newline at end of file diff --git a/mRemoteNGTests/mRemoteNGTests.csproj b/mRemoteNGTests/mRemoteNGTests.csproj index 957a6c866..8ad585e1b 100644 --- a/mRemoteNGTests/mRemoteNGTests.csproj +++ b/mRemoteNGTests/mRemoteNGTests.csproj @@ -137,6 +137,7 @@ + diff --git a/mRemoteV1/Security/CryptographyProviderFactory.cs b/mRemoteV1/Security/CryptographyProviderFactory.cs index e2a43e1fa..ef360bc8e 100644 --- a/mRemoteV1/Security/CryptographyProviderFactory.cs +++ b/mRemoteV1/Security/CryptographyProviderFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Xml.Linq; using mRemoteNG.Security.SymmetricEncryption; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; @@ -20,6 +21,12 @@ namespace mRemoteNG.Security return new LegacyRijndaelCryptographyProvider(); } + public static ICryptographyProvider BuildFromXml(XElement element) + { + var builder = new XmlCryptoProviderBuilder(element); + return builder.Build(); + } + private IBlockCipher ChooseBlockCipherEngine(BlockCipherEngines engine) { switch (engine) diff --git a/mRemoteV1/Security/XmlCryptoProviderBuilder.cs b/mRemoteV1/Security/XmlCryptoProviderBuilder.cs new file mode 100644 index 000000000..f57727133 --- /dev/null +++ b/mRemoteV1/Security/XmlCryptoProviderBuilder.cs @@ -0,0 +1,39 @@ +using System; +using System.Xml.Linq; + + +namespace mRemoteNG.Security +{ + public class XmlCryptoProviderBuilder + { + private readonly XElement _element; + + public XmlCryptoProviderBuilder(XElement element) + { + if (element == null) + throw new ArgumentNullException(nameof(element)); + + _element = element; + } + + public ICryptographyProvider Build() + { + ICryptographyProvider cryptoProvider; + try + { + var engine = (BlockCipherEngines)Enum.Parse(typeof(BlockCipherEngines), _element?.Attribute("EncryptionEngine")?.Value ?? ""); + var mode = (BlockCipherModes)Enum.Parse(typeof(BlockCipherModes), _element?.Attribute("BlockCipherMode")?.Value ?? ""); + cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(engine, mode); + + var keyDerivationIterations = int.Parse(_element?.Attribute("KdfIterations")?.Value ?? ""); + cryptoProvider.KeyDerivationIterations = keyDerivationIterations; + } + catch (Exception) + { + return new CryptographyProviderFactory().CreateLegacyRijndaelCryptographyProvider(); + } + + return cryptoProvider; + } + } +} \ No newline at end of file diff --git a/mRemoteV1/mRemoteV1.csproj b/mRemoteV1/mRemoteV1.csproj index fe788473f..70c5db7ea 100644 --- a/mRemoteV1/mRemoteV1.csproj +++ b/mRemoteV1/mRemoteV1.csproj @@ -220,6 +220,7 @@ +