Konvertieren Sie einen String in SecureString

Antworten:

137

Das tust du nicht. Der gesamte Grund für die Verwendung des SecureString-Objekts besteht darin, das Erstellen eines Zeichenfolgenobjekts zu vermeiden (das in den Speicher geladen und dort bis zur Speicherbereinigung im Klartext gespeichert wird). Sie können einem SecureString jedoch Zeichen hinzufügen, indem Sie sie anhängen.

var s = new SecureString();
s.AppendChar('d');
s.AppendChar('u');
s.AppendChar('m');
s.AppendChar('b');
s.AppendChar('p');
s.AppendChar('a');
s.AppendChar('s');
s.AppendChar('s');
s.AppendChar('w');
s.AppendChar('d');
John Dagg
quelle
13
"Die Kombination ist 12345... so etwas hat ein Idiot auf seinem Gepäck!"
Kolob Canyon
8
Alles was ich sehe ist*****
Ian Boyd
AppendCharwird erst zur Laufzeit ausgeführt, sodass diese Zeichen immer noch aus der IL gelesen werden können, richtig? Vielleicht hilft auch eine Verschleierung während der Kompilierung, wenn Sie Kennwörter fest codieren.
Samis
5
Das ist ein lahmes Argument. Woher bekommst du ein Passwort? Aus einem Formular oder über eine Befehlszeile. Bis sie eine Methode zum Lesen einer sicheren Zeichenfolge direkt aus einem Gerät oder Befehlszeilenargumenten erstellen, müssen wir eine Zeichenfolge in einen SecureString konvertieren.
Quarkly
1
@DonaldAirey Sie erhalten ein Passwort von einem Geheimdienstmanager. Im Allgemeinen handelt es sich bei den Geheimnissen, über die wir hier sprechen, nicht um Benutzerkennwörter, sondern um Dinge, die möglicherweise zu einer Eskalation von Berechtigungen oder zu Datenlecks führen. Das bedeutet, dass die Kennwörter für andere Dienste bestimmt sind und nicht über Befehlszeilen oder im Clear-over-Netzwerkkanal weitergegeben werden sollten.
Barry Kelly
159

Es gibt auch eine andere Möglichkeit, zwischen SecureStringund zu konvertieren String.

1. String zu SecureString

SecureString theSecureString = new NetworkCredential("", "myPass").SecurePassword;

2. SecureString to String

string theString = new NetworkCredential("", theSecureString).Password;

Hier ist der Link

Hossein Narimani Rad
quelle
3
Dies ist bei weitem die beste Lösung für den häufigsten Anwendungsfall!
Dan Bechard
16
Es macht keinen Sinn, a zu verwenden, SecureStringwenn Ihr Code ein stringObjekt mit dem Wert erstellt, den Sie sichern möchten. Das Ziel von SecureStringbesteht darin, zu vermeiden, dass sich die Zeichenfolge im verwalteten Speicher befindet, damit ein Angreifer, der diesen Speicher untersucht, den Wert erkennen kann, den Sie ausblenden möchten. Da der NetworkCredentialKonstruktor Sie eine Zeichenfolge fordern erfordert, die nicht die Art und Weise ist zu gehen ... Sicher, ist der Code eine einfache Möglichkeit , zu und von einem Secure zu konvertieren, aber es macht den Code so sicher wie mit einem einfachen Verwendungstring
Gian Paolo
14
@GianPaolo Während dies theoretisch korrekt ist, müssen wir es in der Praxis immer noch verwenden, SecureStringwenn wir mit einigen Bibliotheken arbeiten. Und seien wir ehrlich, wenn jemand aktiv den Speicher Ihrer Anwendung scannt, haben Sie bereits verloren. Selbst wenn Sie SecureString richtig verwendet haben, was ich noch nie gesehen habe, müssen andere wertvolle Daten extrahiert werden.
Jonathan Allen
1
@ JonathanAllen: Sie haben wahrscheinlich Recht, aber nur, weil wir die Kultur haben, Sicherheit als nachträglichen Gedanken zu behandeln. Wenn Sie eine Rezeptwebsite erstellen, wird Nordkorea wahrscheinlich nicht versuchen, den Speicher Ihres Programms zu scannen. Wenn Sie Bankensoftware schreiben, ist die Bedrohung viel realer.
Eric J.
58

Die folgende Methode hilft beim Konvertieren von Zeichenfolgen in sichere Zeichenfolgen

private SecureString ConvertToSecureString(string password)
{
    if (password == null)
        throw new ArgumentNullException("password");

    var securePassword = new SecureString();

    foreach (char c in password)
        securePassword.AppendChar(c);

    securePassword.MakeReadOnly();
    return securePassword;
}
M2012
quelle
26
+1, aber beachten Sie, dass die Übergabe des Kennworts als Zeichenfolgenparameter eine unverschlüsselte Zeichenfolgeninstanz im verwalteten Speicher erstellt und den Zweck von 'SecureString' in erster Linie zunichte macht. Ich möchte nur darauf hinweisen, dass zukünftige Leute vorbeikommen und diesen Code verwenden.
Cody
19
@Cody Das stimmt, und ein guter Punkt, aber vielen von uns ist es egal, ob der SecureString sicher ist oder nicht, und er wird nur verwendet, weil einige Microsoft-APIs ihn als Parameter benötigen.
Dan Bechard
3
@Cody Es stellt sich heraus, dass selbst die SecureString-Klasse die Zeichenfolge nicht verschlüsselt halten kann. Aus diesem Grund erwägen MS, den Typ github.com/dotnet/platform-compat/blob/master/docs/DE0001.md zu veralten .
Martin Brown
19

Sie können dies folgen:

string password = "test";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();
Skorpion
quelle
11

Hier ist ein billiger Linq-Trick.

            SecureString sec = new SecureString();
            string pwd = "abc123"; /* Not Secure! */
            pwd.ToCharArray().ToList().ForEach(sec.AppendChar);
            /* and now : seal the deal */
            sec.MakeReadOnly();
granadaCoder
quelle
32
Diese Antwort ist eine Übung zu sehen, wie viele temporäre Kopien des Klartextes in einer Aufnahme erzeugt werden können
Mike Caron
1
Wie @ John-Dagg vorgeschlagen hat, besteht die Idee darin, KEINE Zeichenfolge mit Ihrem Passwort festzulegen, da in diesem Fall kein Vorteil mehr besteht, einen Sicherheitsring zu verwenden. In Ihrem Fall, in dem Sie das Passwort im Klartext eingegeben haben, sichern Sie nichts, indem Sie später einen Sicherheitsring verwenden. Ich hoffe, Sie verstehen, dass der Sicherheitsring dazu gedacht war, Ihre Zeichenfolge vor Personen zu schützen, die sich die Demontage oder einen Debugger ansehen. Sehen Sie also, was sich in der IL / im Speicher befindet.
user734028
8

Ich werde das da rauswerfen. Warum?

Sie können nicht einfach alle Ihre Zeichenfolgen in sichere Zeichenfolgen ändern, und plötzlich ist Ihre Anwendung "sicher". Die sichere Zeichenfolge dient dazu, die Zeichenfolge so lange wie möglich verschlüsselt und nur für einen sehr kurzen Zeitraum zu entschlüsseln, wodurch der Speicher gelöscht wird, nachdem eine Operation ausgeführt wurde.

Ich würde riskieren zu sagen, dass Sie möglicherweise einige Probleme auf Designebene haben, bevor Sie sich Gedanken über die Sicherung Ihrer Anwendungszeichenfolgen machen. Geben Sie uns weitere Informationen darüber, was Sie versuchen, und wir können Ihnen möglicherweise besser helfen.

Spence
quelle
1
Ich möchte es nur verwenden, um das Passwort für ProcessStartInfo festzulegen und meine Exe als anderer Benutzer auszuführen. Das hat bei mir funktioniert ...
Developer404
4
Meine Anwendung wird durch Ausführen auf einem sicheren System gesichert. Es könnte mich nicht weniger interessieren, ob diese bestimmte Zeichenfolge im Speicher verschlüsselt wird. Es gibt weitaus wichtigere Informationen zu diesem System, über die Sie sich Sorgen machen müssen, falls es jemals kompromittiert werden sollte. SecureString wird einfach von einer Microsoft-API benötigt, die mein Programm verwenden muss. Es wird vorausgesetzt, dass der Entwickler seinen eigenen Anwendungsfall berücksichtigt und feststellt, ob das Konvertieren von Strings in SecureStrings im Kontext eine gültige Operation ist.
Dan Bechard
Diese Methode verhindert also nicht, dass jemand das Passwort sieht, wenn er einen Dekompiler wie DotPeek verwendet? Gibt es in diesem Fall eine Möglichkeit, Zeichenfolgen auszublenden?
M.Parent
Abhängig von der Bedrohung, die Sie besiegen möchten, gibt es einige Methoden. Wenn Sie die Benutzerinformationen vor anderen Personen als dem lokalen Administrator schützen möchten, können Sie mithilfe der DPAPI-Methoden unter Windows eine Datei verschlüsseln und dort ein Geheimnis speichern, sie in eine sichere Zeichenfolge einlesen und dann wegwerfen. Wenn es sich um ein Unternehmensgeheimnis handelt, lautet die kurze Antwort, ob Ihre Anwendung es entschlüsseln kann, ebenso wie der Benutzer.
Spence
6
unsafe 
{
    fixed(char* psz = password)
        return new SecureString(psz, password.Length);
}
hypersw
quelle
5

Keine ausgefallene Linq, nicht alle Zeichen von Hand hinzufügen, einfach und schlicht:

var str = "foo";
var sc = new SecureString();
foreach(char c in str) sc.appendChar(c);
garglblarg
quelle
Noch schicker, keine Notwendigkeit, eine Variable zu definieren
bigworld12
Hier ist ein var sc = new SecureString(); foreach(char c in "foo") sc.appendChar(c);
Einzeiler
4

Ich bin mit Spence (+1) einverstanden, aber wenn Sie dies zum Lernen oder Testen von Pourposes tun, können Sie ein foreach in der Zeichenfolge verwenden und jedes Zeichen mit der AppendChar-Methode an den Sicherheitsring anhängen.

Jonathan
quelle
3

Ich möchte nur alle Leute darauf hinweisen, die sagen: "Das ist nicht der Punkt von SecureString", dass viele der Leute, die diese Frage stellen, sich in einer Bewerbung befinden, in der sie, aus welchem ​​Grund auch immer, gerechtfertigt oder nicht, nicht besonders besorgt sind Eine temporäre Kopie des Kennworts befindet sich als GC-fähige Zeichenfolge auf dem Heap. Sie müssen jedoch eine API verwenden, die nurSecureString Objekte akzeptiert . Sie haben also eine App, die Sie nicht interessiertUnabhängig davon, ob sich das Kennwort auf dem Heap befindet, ist es möglicherweise nur für den internen Gebrauch bestimmt und das Kennwort ist nur vorhanden, da es von den zugrunde liegenden Netzwerkprotokollen benötigt wird. Sie können feststellen, dass diese Zeichenfolge, in der das Kennwort gespeichert ist, nicht zum Einrichten einer Remote-PowerShell verwendet werden kann Runspace - aber es gibt keinen einfachen, unkomplizierten Einzeiler, um das zu erstellen, SecureStringwas Sie benötigen. Es ist eine kleine Unannehmlichkeit - aber wahrscheinlich lohnt sich , um sicherzustellen , dass die Anwendungen , die wirklich tun müssen , SecureStringum den Einsatz nicht dazu verleiten , die Autoren tun System.Stringoder System.Char[]Vermittler. :-)

Jonathan Gilbert
quelle
2

Wenn Sie die Konvertierung von a stringin a SecureStringin eine LINQAnweisung komprimieren möchten, können Sie dies wie folgt ausdrücken:

var plain  = "The quick brown fox jumps over the lazy dog";
var secure = plain
             .ToCharArray()
             .Aggregate( new SecureString()
                       , (s, c) => { s.AppendChar(c); return s; }
                       , (s)    => { s.MakeReadOnly(); return s; }
                       );

Beachten Sie jedoch, dass die Verwendung LINQdie Sicherheit dieser Lösung nicht verbessert. Es leidet unter dem gleichen Fehler wie jede Konvertierung von stringnach SecureString. Solange das Original stringim Speicher bleibt, sind die Daten anfällig.

Abgesehen davon kann die obige Aussage die Erstellung der SecureString, ihre Initialisierung mit Daten zusammenhalten und sie schließlich vor Änderungen schützen.

cel scharf
quelle
2

Die folgenden 2 Erweiterungen sollten den Trick machen:

  1. Für ein charArray

    public static SecureString ToSecureString(this char[] _self)
    {
        SecureString knox = new SecureString();
        foreach (char c in _self)
        {
            knox.AppendChar(c);
        }
        return knox;
    }
  2. Und für string

    public static SecureString ToSecureString(this string _self)
    {
        SecureString knox = new SecureString();
        char[] chars = _self.ToCharArray();
        foreach (char c in chars)
        {
            knox.AppendChar(c);
        }
        return knox;
    }

Vielen Dank an John Dagg für die AppendCharEmpfehlung.

Peet
quelle
0

Sie können dieses einfache Skript verwenden

private SecureString SecureStringConverter(string pass)
{
    SecureString ret = new SecureString();

    foreach (char chr in pass.ToCharArray())
        ret.AppendChar(chr);

    return ret;
}
Nadir
quelle
1
Diese Antwort wurde vor 15 Monaten veröffentlicht . Es war wirklich nicht nötig, es erneut zu posten.
GSerg