Ukládání do SecureString má jednu velkou výhodu – pokud se pokusíte použít stejné soubory na jiném PC nebo účtu, Windows vám je nepřijme a budete se muset znovu přihlásit. A k heslu se taky nikdo nedostane, pokud zrovna ho nebudete vypisovat někde v aplikaci, nejhůře v plain textu. A protože jsem si pořád myslel že chyba je někde ve třídě které pracují s SecureString, hledal jsem další způsoby jak s ním pracovat. Nakonec jsem vytvořil tyto 2 třídy – třída Unsafe jak název napovídá nemusí být pro uživatele věrohodná, takovou assembly musíte jako unsafe označit, jinak vám ji kompilátor nezkompiluje. Proto doporučuji použít třídu SecureStringHelper, která dělá úplně tutéž práci, jen v kontextu managed kódu. A teď k oběma třídám:
Unsafe:
using System;
using System.Runtime.InteropServices;
using System.Security;
public static class Unsafe
{
public static SecureString ToSecureString(this string value)
{
unsafe
{
fixed (char* value3 = value)
{
SecureString ss = new System.Security.SecureString(value3, value.Length);
ss.MakeReadOnly();
return ss;
}
}
}
public static string ToInsecureString(SecureString securePassword)
{
IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
}SecureStringHelper:
using System;
using System.Security;
public class SecureStringHelper
{
public static SecureString ToSecureString(string input)
{
SecureString secure = new SecureString();
foreach (char c in input)
{
secure.AppendChar(c);
}
secure.MakeReadOnly();
return secure;
}
public static string ToInsecureString(SecureString input)
{
string returnValue = string.Empty;
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
try
{
returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
}
return returnValue;
}
}