Often we’ll come across situations where we need to put a password into our application. For example securing a connection string or login details for a services.
This post is more a dissection of the post Encrypting Passwords in a .NET app.config File than anything new, but interestingly through up a bunch of things to look at.
String & SecureString
Let’s start by looking at String storage. Ultimately strings are stored in memory in clear text and the disposal of them is determined by the garbage collection, hence their lifespan is non-deterministic so we could dump the strings using WinDbg or similar tools in clear text.
SecureString is part of the System.Security assembly and supplies a mechanism for encrypting a string in memory and also, when no longer required, can be disposed of.
The following code shows how we might use a SecureString.
public static class Secure
{
private static byte[] ENTROPY = System.Text.Encoding.Unicode.GetBytes("Salt Is Not A Password");
public static string Encrypt(SecureString input)
{
return Encrypt(ToInsecureString(input));
}
public static string Encrypt(string input)
{
var encryptedData = System.Security.Cryptography.ProtectedData.Protect(
System.Text.Encoding.Unicode.GetBytes(input),
ENTROPY,
System.Security.Cryptography.DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
public static SecureString DecryptToSecureString(string encryptedData)
{
var result = DecryptToString(encryptedData);
return result != null ? ToSecureString(result) : new SecureString();
}
public static string DecryptToString(string encryptedData)
{
try
{
var decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
Convert.FromBase64String(encryptedData),
ENTROPY,
System.Security.Cryptography.DataProtectionScope.CurrentUser);
return System.Text.Encoding.Unicode.GetString(decryptedData);
}
catch
{
return null;
}
}
public static SecureString ToSecureString(string input)
{
var secure = new SecureString();
foreach (var c in input)
{
secure.AppendChar(c);
}
secure.MakeReadOnly();
return secure;
}
public static string ToInsecureString(SecureString input)
{
string returnValue;
var ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
try
{
returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
}
return returnValue;
}
}
References
Encrypting Passwords in a .NET app.config File
SecureString Class