If you are just going to verify/validate the entered user name and password, use the Rfc2898DerivedBytes class (also known as Password Based Key Derivation Function 2 or PBKDF2). This is more secure than using encryption like Triple DES or AES because there is no practical way to go from the result of RFC2898DerivedBytes back to the password. You can only go from a password to the result. See Is it ok to use SHA1 hash of password as a salt when deriving encryption key and IV from password string? for an example and discussion for .Net or String encrypt / decrypt with password c# Metro Style for WinRT/Metro.
If you are storing the password for reuse, such as supplying it to a third party, use the Windows Data Protection API (DPAPI). This uses operating system generated and protected keys and the Triple DES encryption algorithm to encrypt and decrypt information. This means your application does not have to worry about generating and protecting the encryption keys, a major concern when using cryptography.
In C#, use the System.Security.Cryptography.ProtectedData class. For example, to encrypt a piece of data, use ProtectedData.Protect()
:
// Data to protect. Convert a string to a byte[] using Encoding.UTF8.GetBytes().
byte[] plaintext;
// Generate additional entropy (will be used as the Initialization vector)
byte[] entropy = new byte[20];
using(RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(entropy);
}
byte[] ciphertext = ProtectedData.Protect(plaintext, entropy,
DataProtectionScope.CurrentUser);
Store the entropy and ciphertext securely, such as in a file or registry key with permissions set so only the current user can read it. To get access to the original data, use ProtectedData.Unprotect()
:
byte[] plaintext= ProtectedData.Unprotect(ciphertext, entropy,
DataProtectionScope.CurrentUser);
Note that there are additional security considerations. For example, avoid storing secrets like passwords as a string
. Strings are immutable, being they cannot be notified in memory so someone looking at the application's memory or a memory dump may see the password. Use SecureString or a byte[] instead and remember to dispose or zero them as soon as the password is no longer needed.
I have used this before and I think in order to make sure credential persist and in a best secure way is
ConfigurationManager
classSecureString
classCryptography
namespace.This link will be of great help I hope : Click here
I wanted to encrypt and decrypt the string as a readable string.
Here is a very simple quick example in C# Visual Studio 2019 WinForms based on the answer from @Pradip
.
Right click project > properties > settings > Create a username
and password
setting.
Now you can leverage those settings you just created. Here I save the username
and password
but only encrypt the password
in it's respectable value field in the user.config
file.
Example of the encrypted string in the user.config
file.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<secure_password_store.Properties.Settings>
<setting name="username" serializeAs="String">
<value>admin</value>
</setting>
<setting name="password" serializeAs="String">
<value>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAQpgaPYIUq064U3o6xXkQOQAAAAACAAAAAAAQZgAAAAEAACAAAABlQQ8OcONYBr9qUhH7NeKF8bZB6uCJa5uKhk97NdH93AAAAAAOgAAAAAIAACAAAAC7yQicDYV5DiNp0fHXVEDZ7IhOXOrsRUbcY0ziYYTlKSAAAACVDQ+ICHWooDDaUywJeUOV9sRg5c8q6/vizdq8WtPVbkAAAADciZskoSw3g6N9EpX/8FOv+FeExZFxsm03i8vYdDHUVmJvX33K03rqiYF2qzpYCaldQnRxFH9wH2ZEHeSRPeiG</value>
</setting>
</secure_password_store.Properties.Settings>
</userSettings>
</configuration>
Full Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace secure_password_store
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Exit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void Login_Click(object sender, EventArgs e)
{
if (checkBox1.Checked == true)
{
Properties.Settings.Default.username = textBox1.Text;
Properties.Settings.Default.password = EncryptString(ToSecureString(textBox2.Text));
Properties.Settings.Default.Save();
}
else if (checkBox1.Checked == false)
{
Properties.Settings.Default.username = "";
Properties.Settings.Default.password = "";
Properties.Settings.Default.Save();
}
MessageBox.Show("{\"data\": \"some data\"}","Login Message Alert",MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void DecryptString_Click(object sender, EventArgs e)
{
SecureString password = DecryptString(Properties.Settings.Default.password);
string readable = ToInsecureString(password);
textBox4.AppendText(readable + Environment.NewLine);
}
private void Form_Load(object sender, EventArgs e)
{
//textBox1.Text = "UserName";
//textBox2.Text = "Password";
if (Properties.Settings.Default.username != string.Empty)
{
textBox1.Text = Properties.Settings.Default.username;
checkBox1.Checked = true;
SecureString password = DecryptString(Properties.Settings.Default.password);
string readable = ToInsecureString(password);
textBox2.Text = readable;
}
groupBox1.Select();
}
static byte[] entropy = Encoding.Unicode.GetBytes("SaLtY bOy 6970 ePiC");
public static string EncryptString(SecureString input)
{
byte[] encryptedData = ProtectedData.Protect(Encoding.Unicode.GetBytes(ToInsecureString(input)),entropy,DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
public static SecureString DecryptString(string encryptedData)
{
try
{
byte[] decryptedData = ProtectedData.Unprotect(Convert.FromBase64String(encryptedData),entropy,DataProtectionScope.CurrentUser);
return ToSecureString(Encoding.Unicode.GetString(decryptedData));
}
catch
{
return new SecureString();
}
}
public static SecureString ToSecureString(string input)
{
SecureString secure = new SecureString();
foreach (char c in input)
{
secure.AppendChar(c);
}
secure.MakeReadOnly();
return secure;
}
public static string ToInsecureString(SecureString input)
{
string returnValue = string.Empty;
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
try
{
returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
}
return returnValue;
}
private void EncryptString_Click(object sender, EventArgs e)
{
Properties.Settings.Default.password = EncryptString(ToSecureString(textBox2.Text));
textBox3.AppendText(Properties.Settings.Default.password.ToString() + Environment.NewLine);
}
}
}
DPAPI is just for this purpose. Use DPAPI to encrypt the password the first time the user enters is, store it in a secure location (User's registry, User's application data directory, are some choices). Whenever the app is launched, check the location to see if your key exists, if it does use DPAPI to decrypt it and allow access, otherwise deny it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With