diff --git a/mRemoteNGTests/Security/LegacyRijndaelCryptographyProviderTests.cs b/mRemoteNGTests/Security/LegacyRijndaelCryptographyProviderTests.cs
new file mode 100644
index 000000000..2d34f871f
--- /dev/null
+++ b/mRemoteNGTests/Security/LegacyRijndaelCryptographyProviderTests.cs
@@ -0,0 +1,58 @@
+using System.Security;
+using mRemoteNG.Security;
+using NUnit.Framework;
+
+
+namespace mRemoteNGTests.Security
+{
+ [TestFixture()]
+ public class LegacyRijndaelCryptographyProviderTests
+ {
+ private ICryptographyProvider _rijndaelCryptographyProvider;
+ private SecureString _encryptionKey;
+ private string _plainText;
+
+ [SetUp]
+ public void SetUp()
+ {
+ _rijndaelCryptographyProvider = new LegacyRijndaelCryptographyProvider();
+ _encryptionKey = "mR3m".ConvertToSecureString();
+ _plainText = "MySecret!";
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _rijndaelCryptographyProvider = null;
+ }
+
+ [Test]
+ public void GetBlockSizeReturnsProperValueForRijndael()
+ {
+ Assert.That(_rijndaelCryptographyProvider.BlockSizeInBytes, Is.EqualTo(16));
+ }
+
+ [Test]
+ public void EncryptionOutputsBase64String()
+ {
+ var cipherText = _rijndaelCryptographyProvider.Encrypt(_plainText, _encryptionKey);
+ Assert.That(cipherText.IsBase64String, Is.True);
+ }
+
+ [Test]
+ public void DecryptedTextIsEqualToOriginalPlainText()
+ {
+ var cipherText = _rijndaelCryptographyProvider.Encrypt(_plainText, _encryptionKey);
+ var decryptedCipherText = _rijndaelCryptographyProvider.Decrypt(cipherText, _encryptionKey);
+ Assert.That(decryptedCipherText, Is.EqualTo(_plainText));
+ }
+
+ [Test]
+ public void EncryptingTheSameValueReturnsNewCipherTextEachTime()
+ {
+ var cipherText1 = _rijndaelCryptographyProvider.Encrypt(_plainText, _encryptionKey);
+ var cipherText2 = _rijndaelCryptographyProvider.Encrypt(_plainText, _encryptionKey);
+ Assert.That(cipherText1, Is.Not.EqualTo(cipherText2));
+ }
+ }
+}
\ No newline at end of file
diff --git a/mRemoteNGTests/mRemoteNGTests.csproj b/mRemoteNGTests/mRemoteNGTests.csproj
index acb911769..1d7a1b822 100644
--- a/mRemoteNGTests/mRemoteNGTests.csproj
+++ b/mRemoteNGTests/mRemoteNGTests.csproj
@@ -107,6 +107,7 @@
+
Form
diff --git a/mRemoteV1/App/Info/GeneralAppInfo.cs b/mRemoteV1/App/Info/GeneralAppInfo.cs
index e4aa01a05..538f74e0f 100644
--- a/mRemoteV1/App/Info/GeneralAppInfo.cs
+++ b/mRemoteV1/App/Info/GeneralAppInfo.cs
@@ -2,8 +2,10 @@ using System.Collections.Generic;
using System;
using System.IO;
using System.Reflection;
+using System.Security;
using System.Threading;
using System.Windows.Forms;
+using mRemoteNG.Security;
using static System.Environment;
@@ -19,7 +21,7 @@ namespace mRemoteNG.App.Info
public static readonly string ProdName = Application.ProductName;
public static readonly string copyright = ((AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyCopyrightAttribute), false)).Copyright;
public static readonly string HomePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
- public static readonly string EncryptionKey = "mR3m";
+ public static readonly SecureString EncryptionKey = "mR3m".ConvertToSecureString();
public static string ReportingFilePath = "";
public static readonly string PuttyPath = HomePath + "\\PuTTYNG.exe";
public static string UserAgent
diff --git a/mRemoteV1/Config/Connections/ConnectionsLoader.cs b/mRemoteV1/Config/Connections/ConnectionsLoader.cs
index e2645f653..406cfd924 100644
--- a/mRemoteV1/Config/Connections/ConnectionsLoader.cs
+++ b/mRemoteV1/Config/Connections/ConnectionsLoader.cs
@@ -8,8 +8,10 @@ using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
+using System.Security;
using System.Windows.Forms;
using System.Xml;
+using mRemoteNG.App.Info;
using mRemoteNG.Tree;
using mRemoteNG.Connection;
using mRemoteNG.Container;
@@ -26,7 +28,7 @@ namespace mRemoteNG.Config.Connections
#region Private Properties
private XmlDocument xDom;
private double confVersion;
- private string pW = "mR3m";
+ private SecureString pW = GeneralAppInfo.EncryptionKey;
private SqlConnection sqlCon;
private SqlCommand sqlQuery;
private SqlDataReader sqlRd;
@@ -1252,7 +1254,7 @@ namespace mRemoteNG.Config.Connections
{
pW = Tools.MiscTools.PasswordDialog(passwordName, false);
- if (string.IsNullOrEmpty(pW))
+ if (pW.Length == 0)
{
return false;
}
@@ -1264,7 +1266,7 @@ namespace mRemoteNG.Config.Connections
{
pW = Tools.MiscTools.PasswordDialog(passwordName, false);
- if (string.IsNullOrEmpty(pW))
+ if (pW.Length == 0)
{
return false;
}
@@ -1273,7 +1275,7 @@ namespace mRemoteNG.Config.Connections
if (rootInfo != null)
{
rootInfo.Password = true;
- rootInfo.PasswordString = pW;
+ rootInfo.PasswordString = pW.ConvertToUnsecureString();
}
}
diff --git a/mRemoteV1/Config/Connections/ConnectionsSaver.cs b/mRemoteV1/Config/Connections/ConnectionsSaver.cs
index 5c5b509e8..eb97b9924 100644
--- a/mRemoteV1/Config/Connections/ConnectionsSaver.cs
+++ b/mRemoteV1/Config/Connections/ConnectionsSaver.cs
@@ -3,6 +3,7 @@ using System.Data.SqlClient;
using System.Drawing;
using System.Globalization;
using System.IO;
+using System.Security;
using System.Text;
using System.Windows.Forms;
using System.Xml;
@@ -37,7 +38,7 @@ namespace mRemoteNG.Config.Connections
#region Private Properties
private XmlTextWriter _xmlTextWriter;
- private string _password = "mR3m";
+ private SecureString _password = GeneralAppInfo.EncryptionKey;
private SqlConnection _sqlConnection;
private SqlCommand _sqlQuery;
@@ -192,7 +193,7 @@ namespace mRemoteNG.Config.Connections
{
if (((RootNodeInfo) tN.Tag).Password)
{
- _password = Convert.ToString(((RootNodeInfo) tN.Tag).PasswordString);
+ _password = Convert.ToString(((RootNodeInfo) tN.Tag).PasswordString).ConvertToSecureString();
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", _password);
}
else
@@ -593,7 +594,7 @@ namespace mRemoteNG.Config.Connections
{
if (((RootNodeInfo) treeNode.Tag).Password)
{
- _password = Convert.ToString(((RootNodeInfo) treeNode.Tag).PasswordString);
+ _password = Convert.ToString(((RootNodeInfo) treeNode.Tag).PasswordString).ConvertToSecureString();
_xmlTextWriter.WriteAttributeString("Protected", "", cryptographyProvider.Encrypt("ThisIsProtected", _password));
}
else
diff --git a/mRemoteV1/Security/LegacyRijndaelCryptographyProvider.cs b/mRemoteV1/Security/LegacyRijndaelCryptographyProvider.cs
index 6814fadd5..e865fbd4f 100644
--- a/mRemoteV1/Security/LegacyRijndaelCryptographyProvider.cs
+++ b/mRemoteV1/Security/LegacyRijndaelCryptographyProvider.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.Security;
using System.Security.Cryptography;
using System.Text;
using mRemoteNG.App;
@@ -8,21 +9,30 @@ using mRemoteNG.Messages;
namespace mRemoteNG.Security
{
- public class LegacyRijndaelCryptographyProvider
+ public class LegacyRijndaelCryptographyProvider : ICryptographyProvider
{
- public string Encrypt(string strToEncrypt, string strSecret)
+ public int BlockSizeInBytes { get; }
+
+ public string CipherEngine { get; }
+
+ public LegacyRijndaelCryptographyProvider()
+ {
+ CipherEngine = "Rijndael";
+ BlockSizeInBytes = 16;
+ }
+
+
+ public string Encrypt(string strToEncrypt, SecureString strSecret)
{
- if (strToEncrypt == "" || strSecret == "")
- {
+ if (strToEncrypt == "" || strSecret.Length == 0)
return strToEncrypt;
- }
try
{
var rd = new RijndaelManaged();
var md5 = new MD5CryptoServiceProvider();
- var key = md5.ComputeHash(Encoding.UTF8.GetBytes(strSecret));
+ var key = md5.ComputeHash(Encoding.UTF8.GetBytes(strSecret.ConvertToUnsecureString()));
md5.Clear();
rd.Key = key;
@@ -53,9 +63,9 @@ namespace mRemoteNG.Security
return strToEncrypt;
}
- public string Decrypt(string ciphertextBase64, string password)
+ public string Decrypt(string ciphertextBase64, SecureString password)
{
- if (string.IsNullOrEmpty(ciphertextBase64) || string.IsNullOrEmpty(password))
+ if (string.IsNullOrEmpty(ciphertextBase64) || password.Length == 0)
return ciphertextBase64;
try
@@ -65,7 +75,7 @@ namespace mRemoteNG.Security
using (var rijndaelManaged = new RijndaelManaged())
using (var md5 = new MD5CryptoServiceProvider())
{
- var key = md5.ComputeHash(Encoding.UTF8.GetBytes(password));
+ var key = md5.ComputeHash(Encoding.UTF8.GetBytes(password.ConvertToUnsecureString()));
rijndaelManaged.Key = key;
var ciphertext = Convert.FromBase64String(ciphertextBase64);
@@ -73,9 +83,8 @@ namespace mRemoteNG.Security
using (var cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateDecryptor(), CryptoStreamMode.Read))
using (var streamReader = new StreamReader(cryptoStream, Encoding.UTF8, true))
{
- const int ivLength = 16;
- var iv = new byte[ivLength - 1 + 1];
- memoryStream.Read(iv, 0, ivLength);
+ var iv = new byte[BlockSizeInBytes];
+ memoryStream.Read(iv, 0, BlockSizeInBytes);
rijndaelManaged.IV = iv;
plaintext = streamReader.ReadToEnd();
rijndaelManaged.Clear();
diff --git a/mRemoteV1/Tools/MiscTools.cs b/mRemoteV1/Tools/MiscTools.cs
index 08f44b3f5..f8b9a487c 100644
--- a/mRemoteV1/Tools/MiscTools.cs
+++ b/mRemoteV1/Tools/MiscTools.cs
@@ -5,10 +5,12 @@ using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
+using System.Security;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Forms;
using mRemoteNG.Messages;
+using mRemoteNG.Security;
using mRemoteNG.UI.Window;
using static System.String;
@@ -58,11 +60,11 @@ namespace mRemoteNG.Tools
- public static string PasswordDialog(string passwordName = null, bool verify = true)
+ public static SecureString PasswordDialog(string passwordName = null, bool verify = true)
{
PasswordForm passwordForm = new PasswordForm(passwordName, verify);
- return passwordForm.ShowDialog() == DialogResult.OK ? passwordForm.Password : "";
+ return passwordForm.ShowDialog() == DialogResult.OK ? passwordForm.Password.ConvertToSecureString() : "".ConvertToSecureString();
}
diff --git a/mRemoteV1/UI/Window/ConfigWindow.cs b/mRemoteV1/UI/Window/ConfigWindow.cs
index 5f1ba9bfc..800cf2ea1 100644
--- a/mRemoteV1/UI/Window/ConfigWindow.cs
+++ b/mRemoteV1/UI/Window/ConfigWindow.cs
@@ -12,6 +12,7 @@ using System.Drawing;
using System.IO;
using System.Net.NetworkInformation;
using System.Windows.Forms;
+using mRemoteNG.Security;
using mRemoteNG.UI.Controls.FilteredPropertyGrid;
using WeifenLuo.WinFormsUI.Docking;
@@ -775,10 +776,10 @@ namespace mRemoteNG.UI.Window
passwordName = Path.GetFileName(Runtime.GetStartupConnectionFileName());
var password = MiscTools.PasswordDialog(passwordName);
- if (string.IsNullOrEmpty(password))
+ if (password.Length == 0)
rootInfo.Password = false;
else
- rootInfo.PasswordString = password;
+ rootInfo.PasswordString = password.ConvertToUnsecureString();
}
break;
case "Name":