Sometimes you need to keep sensitive information in a Windows Forms application settings file. The settings file is plain text by default. In this case, you'd better encrypt this sensitive information, like a password, to protect from someone capturing the file (user.config, app.config depending on your choice) and seeing the content of the settings file and trying to abuse it.
Encrypting settings is very easy. Al you need is:
Encrypting settings is very easy. Al you need is:
- A settings class derives from ApplicationSettingsBase
- An encryption utility class
- A couple of lines to get, set and save the settings
| encryptingwindowsformssettings.zip |
A settings class derives from ApplicationSettingsBase
using System;
using System.Configuration;
namespace EncryptingWindowsFormsSettings
{
internal class AppSettings : ApplicationSettingsBase
{
// Shared secreet is used for encryption
// You can change this according to your preference
private const string SharedSecret = "sSDffdf46FFs";
// this attribute specifies that an application settings group or
// property contains distinct values for each user of an application
[UserScopedSetting]
public string Password
{
get
{
// this part is necessary
// for the first time when there is still nothing to
// read in the settings file. In other words, the
// "Password" is null or empty.
try
{
// Crypto is the utiliy class that holds the encryption logic
// You can use your own encryption utility class for more control
return Crypto.DecryptStringAES(((string)this["Password"]), SharedSecret);
}
catch (FormatException)
{
// simply return nothing in case of exception
return ((string)this["Password"]);
}
}
set
{
// When you save the settings, the password will be encrypted
this["Password"] = Crypto.EncryptStringAES(value, SharedSecret);
}
}
}
}
using System.Configuration;
namespace EncryptingWindowsFormsSettings
{
internal class AppSettings : ApplicationSettingsBase
{
// Shared secreet is used for encryption
// You can change this according to your preference
private const string SharedSecret = "sSDffdf46FFs";
// this attribute specifies that an application settings group or
// property contains distinct values for each user of an application
[UserScopedSetting]
public string Password
{
get
{
// this part is necessary
// for the first time when there is still nothing to
// read in the settings file. In other words, the
// "Password" is null or empty.
try
{
// Crypto is the utiliy class that holds the encryption logic
// You can use your own encryption utility class for more control
return Crypto.DecryptStringAES(((string)this["Password"]), SharedSecret);
}
catch (FormatException)
{
// simply return nothing in case of exception
return ((string)this["Password"]);
}
}
set
{
// When you save the settings, the password will be encrypted
this["Password"] = Crypto.EncryptStringAES(value, SharedSecret);
}
}
}
}
An encryption utility class
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace EncryptingWindowsFormsSettings
{
// Encrypt/Decrypt string in .NET
// http://stackoverflow.com/questions/202011/encrypt-decrypt-string-in-net
public static class Crypto
{
private static readonly byte[] Salt = Encoding.ASCII.GetBytes("dE4ffrTy7/!");
/// <summary>
/// Encrypt the given string using AES. The string can be decrypted using
/// DecryptStringAES(). The sharedSecret parameters must match.
/// </summary>
/// <param name="plainText">The text to encrypt.</param>
/// <param name="sharedSecret">A password used to generate a key for encryption.</param>
public static string EncryptStringAES(string plainText, string sharedSecret)
{
if (string.IsNullOrEmpty(plainText))
throw new ArgumentNullException("plainText");
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
string outStr; // Encrypted string to return
RijndaelManaged aesAlg = null; // RijndaelManaged object used to encrypt the data.
try
{
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, Salt);
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
}
outStr = Convert.ToBase64String(msEncrypt.ToArray());
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
// Return the encrypted bytes from the memory stream.
return outStr;
}
/// <summary>
/// Decrypt the given string. Assumes the string was encrypted using
/// EncryptStringAES(), using an identical sharedSecret.
/// </summary>
/// <param name="cipherText">The text to decrypt.</param>
/// <param name="sharedSecret">A password used to generate a key for decryption.</param>
public static string DecryptStringAES(string cipherText, string sharedSecret)
{
if (string.IsNullOrEmpty(cipherText))
throw new ArgumentNullException("cipherText");
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
// Declare the RijndaelManaged object
// used to decrypt the data.
RijndaelManaged aesAlg = null;
// Declare the string used to hold
// the decrypted text.
string plaintext;
try
{
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, Salt);
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
byte[] bytes = Convert.FromBase64String(cipherText);
using (MemoryStream msDecrypt = new MemoryStream(bytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
return plaintext;
}
}
}
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace EncryptingWindowsFormsSettings
{
// Encrypt/Decrypt string in .NET
// http://stackoverflow.com/questions/202011/encrypt-decrypt-string-in-net
public static class Crypto
{
private static readonly byte[] Salt = Encoding.ASCII.GetBytes("dE4ffrTy7/!");
/// <summary>
/// Encrypt the given string using AES. The string can be decrypted using
/// DecryptStringAES(). The sharedSecret parameters must match.
/// </summary>
/// <param name="plainText">The text to encrypt.</param>
/// <param name="sharedSecret">A password used to generate a key for encryption.</param>
public static string EncryptStringAES(string plainText, string sharedSecret)
{
if (string.IsNullOrEmpty(plainText))
throw new ArgumentNullException("plainText");
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
string outStr; // Encrypted string to return
RijndaelManaged aesAlg = null; // RijndaelManaged object used to encrypt the data.
try
{
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, Salt);
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
}
outStr = Convert.ToBase64String(msEncrypt.ToArray());
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
// Return the encrypted bytes from the memory stream.
return outStr;
}
/// <summary>
/// Decrypt the given string. Assumes the string was encrypted using
/// EncryptStringAES(), using an identical sharedSecret.
/// </summary>
/// <param name="cipherText">The text to decrypt.</param>
/// <param name="sharedSecret">A password used to generate a key for decryption.</param>
public static string DecryptStringAES(string cipherText, string sharedSecret)
{
if (string.IsNullOrEmpty(cipherText))
throw new ArgumentNullException("cipherText");
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
// Declare the RijndaelManaged object
// used to decrypt the data.
RijndaelManaged aesAlg = null;
// Declare the string used to hold
// the decrypted text.
string plaintext;
try
{
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, Salt);
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
byte[] bytes = Convert.FromBase64String(cipherText);
using (MemoryStream msDecrypt = new MemoryStream(bytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
return plaintext;
}
}
}
A couple of lines to get, set and save the settings
using System;
using System.Windows.Forms;
namespace EncryptingWindowsFormsSettings
{
public partial class Form1 : Form
{
private AppSettings _appSettings;
public Form1()
{
InitializeComponent();
Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
// get an instance of the AppSettings object
_appSettings = new AppSettings();
// bind the 'Text' property of textBoxPassword with
// the 'Password' property of _appSettings
textBoxPassword.DataBindings.Add(new Binding("Text", _appSettings, "Password"));
}
private void ButtonCloseClick(object sender, EventArgs e)
{
_appSettings.Save();
}
}
}
using System.Windows.Forms;
namespace EncryptingWindowsFormsSettings
{
public partial class Form1 : Form
{
private AppSettings _appSettings;
public Form1()
{
InitializeComponent();
Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
// get an instance of the AppSettings object
_appSettings = new AppSettings();
// bind the 'Text' property of textBoxPassword with
// the 'Password' property of _appSettings
textBoxPassword.DataBindings.Add(new Binding("Text", _appSettings, "Password"));
}
private void ButtonCloseClick(object sender, EventArgs e)
{
_appSettings.Save();
}
}
}
RSS Feed