diff --git a/mRemoteNGTests/NUnitExtensions/SecureTextBoxTester.cs b/mRemoteNGTests/NUnitExtensions/SecureTextBoxTester.cs
new file mode 100644
index 000000000..93e6cf9cb
--- /dev/null
+++ b/mRemoteNGTests/NUnitExtensions/SecureTextBoxTester.cs
@@ -0,0 +1,28 @@
+using System.Windows.Forms;
+using mRemoteNG.UI.Controls;
+using NUnit.Extensions.Forms;
+
+
+namespace mRemoteNGTests.NUnitExtensions
+{
+ public class SecureTextBoxTester : ControlTester
+ {
+ public SecureTextBoxTester(string name, string formName) : base(name, formName)
+ {
+ }
+
+ public SecureTextBoxTester(string name, Form form) : base(name, form)
+ {
+ }
+
+ public SecureTextBoxTester(string name) : base(name)
+ {
+ }
+
+ public SecureTextBoxTester(ControlTester tester, int index) : base(tester, index)
+ {
+ }
+
+ public SecureTextBox Properties => (SecureTextBox) Control;
+ }
+}
\ No newline at end of file
diff --git a/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.Designer.cs b/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.Designer.cs
new file mode 100644
index 000000000..abe3ec476
--- /dev/null
+++ b/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.Designer.cs
@@ -0,0 +1,61 @@
+using mRemoteNG.UI.Controls;
+
+namespace mRemoteNGTests.UI.Controls
+{
+ partial class SecureTextBoxTestForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.secureTextBox1 = new mRemoteNG.UI.Controls.SecureTextBox();
+ this.SuspendLayout();
+ //
+ // secureTextBox1
+ //
+ this.secureTextBox1.Location = new System.Drawing.Point(12, 12);
+ this.secureTextBox1.Name = "secureTextBox1";
+ this.secureTextBox1.ShortcutsEnabled = false;
+ this.secureTextBox1.Size = new System.Drawing.Size(232, 20);
+ this.secureTextBox1.TabIndex = 0;
+ //
+ // SecureTextBoxTestForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(256, 45);
+ this.Controls.Add(this.secureTextBox1);
+ this.Name = "SecureTextBoxTestForm";
+ this.Text = "SecureTextBoxTestForm";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ internal SecureTextBox secureTextBox1;
+ }
+}
\ No newline at end of file
diff --git a/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.cs b/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.cs
new file mode 100644
index 000000000..38fbcad0c
--- /dev/null
+++ b/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.cs
@@ -0,0 +1,13 @@
+using System.Windows.Forms;
+
+namespace mRemoteNGTests.UI.Controls
+{
+ public partial class SecureTextBoxTestForm : Form
+ {
+ public SecureTextBoxTestForm()
+ {
+ Application.EnableVisualStyles();
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.resx b/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.resx
new file mode 100644
index 000000000..1af7de150
--- /dev/null
+++ b/mRemoteNGTests/UI/Controls/SecureTextBoxTestForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/mRemoteNGTests/UI/Controls/SecureTextBoxTests.cs b/mRemoteNGTests/UI/Controls/SecureTextBoxTests.cs
new file mode 100644
index 000000000..4ae5a32d9
--- /dev/null
+++ b/mRemoteNGTests/UI/Controls/SecureTextBoxTests.cs
@@ -0,0 +1,35 @@
+using mRemoteNG.Security;
+using mRemoteNGTests.NUnitExtensions;
+using NUnit.Framework;
+
+namespace mRemoteNGTests.UI.Controls
+{
+ public class SecureTextBoxTests
+ {
+ private SecureTextBoxTestForm _testForm;
+
+ [SetUp]
+ public void Setup()
+ {
+ _testForm = new SecureTextBoxTestForm();
+ _testForm.Show();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ _testForm.Close();
+ while (_testForm.Disposing) { }
+ _testForm = null;
+ }
+
+ [Test]
+ public void TextboxInputGetsAddedToSecureString()
+ {
+ var textBox = new SecureTextBoxTester(_testForm.secureTextBox1.Name);
+ const string textToSend = "abc123";
+ textBox.Properties.Text = textToSend;
+ Assert.That(textBox.Properties.SecureString.ConvertToUnsecureString(), Is.EqualTo(textToSend));
+ }
+ }
+}
\ No newline at end of file
diff --git a/mRemoteNGTests/mRemoteNGTests.csproj b/mRemoteNGTests/mRemoteNGTests.csproj
index 85967e4b5..8fd5610af 100644
--- a/mRemoteNGTests/mRemoteNGTests.csproj
+++ b/mRemoteNGTests/mRemoteNGTests.csproj
@@ -133,6 +133,7 @@
+
@@ -166,6 +167,13 @@
+
+ Form
+
+
+ SecureTextBoxTestForm.cs
+
+
Form
@@ -191,6 +199,9 @@
ResXFileCodeGenerator
Resources.Designer.cs
+
+ SecureTextBoxTestForm.cs
+
TestForm.cs
diff --git a/mRemoteV1/UI/Controls/SecureTextBox.Designer.cs b/mRemoteV1/UI/Controls/SecureTextBox.Designer.cs
new file mode 100644
index 000000000..67bdcf789
--- /dev/null
+++ b/mRemoteV1/UI/Controls/SecureTextBox.Designer.cs
@@ -0,0 +1,36 @@
+namespace mRemoteNG.UI.Controls
+{
+ partial class SecureTextBox
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+ }
+}
diff --git a/mRemoteV1/UI/Controls/SecureTextBox.cs b/mRemoteV1/UI/Controls/SecureTextBox.cs
new file mode 100644
index 000000000..10ec694d7
--- /dev/null
+++ b/mRemoteV1/UI/Controls/SecureTextBox.cs
@@ -0,0 +1,23 @@
+using System.Security;
+using System.Windows.Forms;
+using mRemoteNG.Security;
+
+
+namespace mRemoteNG.UI.Controls
+{
+ public partial class SecureTextBox : TextBox
+ {
+ public SecureString SecureString { get; private set; } = new SecureString();
+
+ public SecureTextBox()
+ {
+ InitializeComponent();
+ TextChanged += SecureTextBox_TextChanged;
+ }
+
+ private void SecureTextBox_TextChanged(object sender, System.EventArgs e)
+ {
+ SecureString = Text.ConvertToSecureString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/mRemoteV1/mRemoteV1.csproj b/mRemoteV1/mRemoteV1.csproj
index 7e728a995..6d2b1ac3c 100644
--- a/mRemoteV1/mRemoteV1.csproj
+++ b/mRemoteV1/mRemoteV1.csproj
@@ -269,6 +269,12 @@
Component
+
+ Component
+
+
+ SecureTextBox.cs
+
Component