Reputation: 929
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);
}
Upvotes: 0
Views: 1189
Reputation: 256991
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.
Upvotes: 1
Reputation: 14687
As states in MSDN,
The value of an instance of SecureString is automatically protected using a mechanism supported by the underlying platform when the instance is initialized or when the value is modified.
If you want to provide the mechanism to keep it readonly once the password in store in securestring then you can invoke the method MarkAsReadonly()
on it.
For persistence purpose you can also Hash the SecureString
and create a salt for it. You can retreive the salt for later use e.g. comparison pupose. Check out this code snippet which is using the salt over Securestring
.
Upvotes: 1