Kurze Antwort
warum kann ich nicht einfach sagen:
SecureString password = new SecureString("password");
Denn jetzt hast du password
in Erinnerung; ohne die Möglichkeit, es zu löschen - genau das ist der Punkt von SecureString .
Lange Antwort
Der Grund, warum SecureString existiert, ist, dass Sie ZeroMemory nicht zum Löschen vertraulicher Daten verwenden können, wenn Sie damit fertig sind. Es ist vorhanden, um ein Problem zu lösen, das aufgrund der CLR besteht.
In einer regulären nativen Anwendung würden Sie Folgendes aufrufen SecureZeroMemory
:
Füllt einen Speicherblock mit Nullen.
Hinweis : SecureZeroMemory ist identisch mit ZeroMemory
, außer dass der Compiler es nicht entfernt.
Das Problem ist, dass Sie nichtZeroMemory
oder SecureZeroMemory
in .NET anrufen können . Und in .NET sind Zeichenfolgen unveränderlich. Sie können den Inhalt der Zeichenfolge nicht einmal wie in anderen Sprachen überschreiben :
//Wipe out the password
for (int i=0; i<password.Length; i++)
password[i] = \0;
Also was kannst du tun? Wie bieten wir in .NET die Möglichkeit, ein Passwort oder eine Kreditkartennummer aus dem Speicher zu löschen, wenn wir damit fertig sind?
Der einzige Weg , es kann getan werden wäre die Zeichenfolge in einigen zu platzieren nativen Speicherblock, in dem Sie können dann rufen ZeroMemory
. Ein natives Speicherobjekt wie:
- ein BSTR
- ein HGLOBAL
- Nicht verwalteter CoTaskMem-Speicher
SecureString gibt die verlorene Fähigkeit zurück
In .NET können Strings nicht gelöscht werden, wenn Sie damit fertig sind:
- sie sind unveränderlich; Sie können ihren Inhalt nicht überschreiben
- du kannst nicht
Dispose
von ihnen
- Ihre Bereinigung ist dem Müllsammler ausgeliefert
SecureString ist eine Möglichkeit, die Sicherheit von Strings zu umgehen und deren Bereinigung bei Bedarf zu gewährleisten.
Sie haben die Frage gestellt:
warum kann ich nicht einfach sagen:
SecureString password = new SecureString("password");
Denn jetzt hast du password
in Erinnerung; ohne eine Möglichkeit, es abzuwischen. Es bleibt dort hängen, bis die CLR beschließt, diesen Speicher wiederzuverwenden. Sie haben uns wieder dorthin gebracht, wo wir angefangen haben. Eine laufende Anwendung mit einem Kennwort, das wir nicht entfernen können und bei der ein Speicherauszug (oder Prozessmonitor) das Kennwort sehen kann.
SecureString verwendet die Datenschutz-API, um die im Speicher verschlüsselte Zeichenfolge zu speichern. Auf diese Weise ist die Zeichenfolge in Swap-Dateien, Absturzabbildern oder sogar im Fenster für lokale Variablen nicht vorhanden, wenn ein Kollege Ihre Anforderungen überprüft.
Wie lese ich das Passwort?
Dann ist die Frage: Wie interagiere ich mit der Zeichenfolge? Sie wollen absolut keine Methode wie:
String connectionString = secureConnectionString.ToString()
denn jetzt bist du wieder da, wo du angefangen hast - ein Passwort, das du nicht loswerden kannst. Sie wollen zwingen Entwickler die empfindliche Saite richtig zu handhaben - so dass es kann aus dem Gedächtnis gewischt werden.
Aus diesem Grund bietet .NET drei praktische Hilfsfunktionen, um einen SecureString in einem nicht verwalteten Speicher zu speichern:
Sie konvertieren die Zeichenfolge in einen nicht verwalteten Speicher-Blob, behandeln ihn und löschen ihn dann erneut.
Einige APIs akzeptieren SecureStrings . Zum Beispiel in ADO.net 4.5 die SqlConnection.Credential nimmt einen Satz SqlCredential :
SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();
Sie können das Kennwort auch innerhalb einer Verbindungszeichenfolge ändern:
SqlConnection.ChangePassword(connectionString, cred, newPassword);
Und es gibt viele Stellen in .NET, an denen sie aus Kompatibilitätsgründen weiterhin eine einfache Zeichenfolge akzeptieren und diese dann schnell umdrehen und in einen SecureString einfügen.
Wie füge ich Text in den SecureString ein?
Dies lässt immer noch das Problem:
Wie bekomme ich überhaupt ein Passwort in den SecureString?
Dies ist die Herausforderung, aber es geht darum, dass Sie über Sicherheit nachdenken.
Manchmal ist die Funktionalität bereits für Sie bereitgestellt. Beispielsweise kann das WPF PasswordBox- Steuerelement das eingegebene Kennwort direkt als SecureString zurückgeben :
Ruft das aktuell von der PasswordBox gehaltene Kennwort als SecureString ab .
Dies ist hilfreich, da Sie überall dort, wo Sie eine Rohzeichenfolge weitergegeben haben, jetzt das Typsystem haben, das sich darüber beschwert, dass SecureString nicht mit Zeichenfolge kompatibel ist. Sie möchten so lange wie möglich arbeiten, bevor Sie Ihren SecureString wieder in eine normale Zeichenfolge konvertieren müssen.
Das Konvertieren eines SecureString ist einfach genug:
- SecureStringToBSTR
- PtrToStringBSTR
wie in:
private static string CreateString(SecureString secureString)
{
IntPtr intPtr = IntPtr.Zero;
if (secureString == null || secureString.Length == 0)
{
return string.Empty;
}
string result;
try
{
intPtr = Marshal.SecureStringToBSTR(secureString);
result = Marshal.PtrToStringBSTR(intPtr);
}
finally
{
if (intPtr != IntPtr.Zero)
{
Marshal.ZeroFreeBSTR(intPtr);
}
}
return result;
}
Sie wollen einfach nicht, dass du es tust.
Aber wie bekomme ich einen String in einen SecureString? Nun, was Sie tun müssen, ist, überhaupt kein Passwort mehr in einem String zu haben. Sie mussten es in etwas anderem haben. Sogar ein Char[]
Array wäre hilfreich.
Dann können Sie jedes Zeichen anhängen und den Klartext löschen, wenn Sie fertig sind:
for (int i=0; i < PasswordArray.Length; i++)
{
password.AppendChar(PasswordArray[i]);
PasswordArray[i] = (Char)0;
}
Sie müssen Ihr Passwort in einem Speicher speichern, den Sie löschen können. Laden Sie es von dort in den SecureString.
tl; dr: SecureString ist vorhanden, um das Äquivalent von ZeroMemory bereitzustellen .
Einige Leute sehen keinen Sinn darin , das Kennwort des Benutzers aus dem Speicher zu löschen, wenn ein Gerät gesperrt ist , oder Tastatureingaben aus dem Speicher zu löschen, nachdem sie authentifiziert wurden . Diese Personen verwenden SecureString nicht.
SecureString
Neuentwicklung mehr: github.com/dotnet/platform-compat/blob/master/docs/DE0001.md