For a C# console app, I need to persist a password in the application settings but when I create a setting of type System.Security.SecureString
the setting itself is removed from the plain-text config file. Since I can't see the raw value anymore I can't validate whether or not the data is still encrypted when saved.
Is SecureString
the best approach or should I use ProtectedData
to simply encrypt the string?
--EDIT--
Here is the test code that I used to validate that a SecureString
can be persisted.
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.Security.SecureString Password
{
get
{
return ((global::System.Security.SecureString)(this["Password"]));
}
set { this["Password"] = value; }
}
static void Main(string[] args)
{
PersistPassword("A-Test-Password");
Console.WriteLine(ReadPassword());
Console.ReadLine();
}
static void PersistPassword(string Password)
{
SecureString ss = new SecureString();
Password.ToCharArray().ToList().ForEach(ss.AppendChar);
Settings.Default.Password = ss;
}
static string ReadPassword()
{
SecureString ss = Settings.Default.Password;
IntPtr ptr = Marshal.SecureStringToCoTaskMemUnicode(ss);
return Marshal.PtrToStringUni(ptr);
}
You cannot persist data that is encrypted with SecureString. The key is held in memory, and only lasts as long as your program is alive. SecureString is a wrapper around the native CryptProtectMemory function.
If you need you need the encrypted data to be persistable (for longer than your program exists), you need the Data Protection API (DPAPI), and it's CryptProtectData function - which is exposed to C# users through the ProtectedData class.
SecureString has the advantage of being ephemeral; useful for:
while they are being used by your program - and then deleted.
The DPAPI is better for long-term storage. But beware the protection levels, and you choose the one that is appropriate for what you need:
If you need encryption that can survive transport to different sites or different domains: CryptProtectData is not for you.