2017-02-19 1 views
0

Java bietet die URLEncoder Klasse für URL-codierende Strings. Aber it is considered insecure to store passwords as Strings. Ist dieser Code zum Senden eines Passworts über POST über einen HttpsURLConnection Ausgabestrom wr sicher genug?Sicheres URL-Encoding eines Passworts

try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) { 
    // Write some post params 
    for (char c : pass) { 
     wr.writeBytes(URLEncoder.encode(String.valueOf(c), "UTF-8")); 
    } 
    // Write some more 
} 

Auf der einen Seite verwendet es Strings. Auf der anderen Seite sind diese Strings 1 Zeichen lang und konzeptionell gleich nach der Codierung. Es scheint mir auch, dass dies bei Multi-Byte-Zeichen fehlschlagen könnte. Wäre ein Angreifer in der Lage, diese 1-Zeichen-Strings im Speicher zu finden und das ursprüngliche Passwort zu rekonstruieren? Gibt es einen besseren Weg, dies zu tun?

+0

Ich verstehe Ihren Standpunkt nicht: Sie sprechen nicht darüber, wie man ein Passwort im Speicher darstellt. * Du sprichst von * Senden * von Passwörtern. Das ist * nicht * das gleiche ?! – GhostCat

+0

@GhostCat Ich spreche darüber, wie man ein Passwort überträgt, ohne es in einem unsicheren Format im Speicher zu speichern. –

+0

@GhostCat Insbesondere frage ich mich, ob es sicher ist, die einzelnen Zeichen meines Passworts als Strings zu speichern. Könnte ein Angreifer diese Strings lokalisieren und das Passwort rekonstruieren? –

Antwort

2

Es stimmt, dass Sie Strings für Passwörter nicht zuverlässig verwerfen können, da Sie die String Inhalte nicht manuell löschen können (außer durch Reflektion) und der Inhalt für eine unbekannte Zeit im Speicher bleibt. Daher wird oft empfohlen, char[] für eine Passworteingabe zu verwenden, gefolgt von einer manuellen Nullstellung der genannten char[].

Allerdings ist der Angriff in keiner Weise einfach zu montieren, da es Zugriff auf den Speicher erfordert, Glück mit Timing. Es ist unwahrscheinlich, dass das Passwort für sehr lange Zeit im Speicher verbleibt, da der GC seine Arbeit verrichtet und der Speicher wiederverwendet wird. In den meisten Fällen kann dieser Angriffsvektor im Vergleich zu anderen, einfacheren Angriffen undurchführbar sein.

0

Ein OutputStream hat keine Methode writeBytes; aber es bietet eine Schreib (Byte []) -Methode, die verwendet werden könnte, um alle Zeichen des Passworts mit einen Aufruf schreiben.

Und darüber hinaus: die ganze Idee der Verwendung von HTTPS ist, dass die Verbindung selbst ist sicher verschlüsselt; Es sollte also wirklich egal sein, ob Sie solche Inhalte mit Single-Byte- oder Multi-Byte-Bursts übertragen.

Dann: Denken Sie daran, dass alle diese Klassen Abstraktionen sind, die aufeinander geschichtet sind. HTTPS verwendet TCP; und TCP-Pakete haben eine bestimmte Größe; in diesem Sinne gibt es keine einzelnen Bytes, die sowieso über das Netzwerk gehen.

Und in Bezug auf den zweiten Teil Ihrer Frage: Sie sind ein Array von Char-Werte iterieren. Es kommt also wirklich darauf an wie das Char-Array erstellt wurde; aber normalerweise müssen Sie sich keine Sorgen machen (siehe here zu diesem Thema).

+0

Lesen Sie den verknüpften Beitrag. Es geht darum, Passwörter als Strings zu speichern, nicht über die Sicherheit im Transit. Ich benutze 'DataOutputStream'. Ich füge das zu meiner Frage hinzu. –

+0

Das Zeichenfeld wurde aus z.B. 'JPasswordField.getPassword()'. –

+0

@BrianMcCutchon Mit anderen Worten: Sie können darauf vertrauen, dass dieses Char-Array das Passwort darstellt; weil Sie sich auf eine gut getestete vertrauenswürdige Bibliothekskomponente verlassen, um sie von Ihnen zu erhalten. Mit anderen Worten: Sie müssen sich keine Sorgen machen, dass die einzelnen Zeichen in diesem Array nicht mit utf8 dargestellt werden. – GhostCat