我最近发现了 SecureString,它似乎适合一个完美的应用程序,我想在应用程序开始时基本上初始化一个静态秘密字符串,然后将其设为只读并在应用程序的整个生命周期中使用它(作为一个哈希)。
我无法理解如何使用 SecureString 类。据我所知,您可以设置 SecureString,但无法比较值或以任何方式检索值。
如果这个类是只写的,它的目的是什么?
我最近发现了 SecureString,它似乎适合一个完美的应用程序,我想在应用程序开始时基本上初始化一个静态秘密字符串,然后将其设为只读并在应用程序的整个生命周期中使用它(作为一个哈希)。
我无法理解如何使用 SecureString 类。据我所知,您可以设置 SecureString,但无法比较值或以任何方式检索值。
如果这个类是只写的,它的目的是什么?
不,它不是只写的:您可以使用Marshal类String
从.NET 中检索常规 .NET :SecureString
IntPtr ptr = Marshal.SecureStringToBSTR(secureString);
string str = Marshal.PtrToStringBSTR(ptr);
Marshal.ZeroFreeBSTR(ptr);
return str;
请注意,这会分配非托管内存,因此您需要确保释放它(使用Marshal.ZeroFreeBSTR
)以避免泄漏。不言而喻,一旦将其转换为 .NET 字符串,您将失去 SecureString 的好处(字符串将保留在内存中,直到它被 GC'ed,它可能被分页到磁盘等)。
SecureString 类的目的是您可以在应保护用户数据(例如,密码或信用卡号)隐私的 API 中使用它(例如,如果您的应用程序崩溃并且小型转储被保存到磁盘)。.NET Framework 中的少数类(例如PasswordBox.SecurePassword)采用 SecureString 对象以避免暴露此数据。
这里有两种方式,一种将其转换为安全字符串和从安全字符串转换的方法。当然,将它存储在安全字符串中的全部目的是首先防止它出现在内存中。
#region SecureString Manipulation
/// <summary>
/// Convert a Securestring to a regular string (not considered best practice, but make sure it's not in memory if you can help it)
/// </summary>
/// <param name="securePassword">Password stored in a secure string</param>
/// <returns>regular string of securestring password</returns>
public static string ConvertToUnsecureString(this System.Security.SecureString securePassword)
{
if (securePassword == null)
throw new ArgumentNullException("securePassword");
IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
/// <summary>
/// Pass a text password to this function to return a SecureString (doesn't store the password in memory)
/// </summary>
/// <param name="password">Text version of a password</param>
/// <returns>SecureString of a password (not readable by memory)</returns>
public static SecureString ConvertToSecureString(this string password)
{
if (password == null)
throw new ArgumentNullException("password");
var secure = new SecureString();
foreach (var c in password.ToCharArray())
secure.AppendChar(c);
return secure;
}
#endregion