Hallo,
mal unabhängig von dem MD5/SHA1-Thema. Generell muss ich doch bei dem Verfahren serverseitig einen Schlüssel ausliefern, mit dem clientseitig dass Passwort (per JavaScript) verschlüsselt werden kann. Sehe ich das richtig?
Es geht nicht um eine Verschlüsselung, sondern um das Bilden eines Hashes. Eine Art "Einwegverschlüsselung".
So, jetzt die eigentliche Frage: Im JS ist das Verschlüsselungsverfahren ja ermittelbar und der Schlüssel wird übertragen und kann dann ja auch abgefangen werden (men in the middle heißt das, oder?).
Nein, es geht hier nur um die Speicherung der Passwörter - die eben nicht selbst gesopeichert werden sollen, sondern deren Hash gespeichert werden soll. Damit ein Angreifer eben nicht eine nette Liste mit Nutzernamen, Mailadressen und Passwörtern herunterladen kann. Im Falle einer einfachen Methode wie md5 oder sha1 gibt es aber inzwischen Angriffe die - um es ganz(sic!) grob(sic! sic! sic!) zu sagen - darauf beruhen, dass md5('hallo') immer gleich ist, also riesige Datensammlungen, welche es ermöglichen aus dem geklautem hash das oder ein anderes funktionierendes Passwort [1] zu ermitteln.
Aus dem Grund werden die Passwörter vor dem hashen gesalzen ("salted"). Das bedeutet, jedes Passwort bekommt einen String hinzugefügt und dann wird "gehashed". Damit steigt der Aufwand, weil selbst wenn der Salt (String) bekannt ist müssen die Rainbow-Tables [1] neu gebaut werden. Der Salt muss aber bekannt sein, also verwendet man für jedes Passwort einen eigenen zufälligen Salt und speichert den Salt und das Passwort in geeigneter Weise zusammen ab. Dann müssen für jedes zu knackende Passwort die Rainbow-Tabellen angeglichen werden - was den Rechenaufwand eines Angreifers zur Ermittlung der Passwörter wieder hochtreibt. Zusätzlich kann man das hashen mehrfach durchführen.
Die von molily unter dem gegen mich gerichteten - und nicht gerechtfertigtem - Vorwurf der "Ahnungslosigkeit" genannten Funktionen phpass, password_hash und hash_pbkdf2 tun letztendlich genau das (oder erlauben sogar die Übergabe eines statischen salt - was nicht zur Erhöhung der Sicherheit beiträgt) und verwenden dabei auch (nicht aber zwangsläufig, wie z.B. ein Blick in die Dokumentation auf die Ausgaben von hash_algos() ergibt) auch andere, stärkere hash-algorithmen als md5/sha1.
Für die Übertragung gibt es ssl/https. Das ist aber noch mal ein anderes Thema. Merke Dir aber, dass die verschlüsselte Übertragung ggf. nutzlos wäre, wenn die Daten dann im Klartext gespeichert werden. Ebenso macht die Speicherung nur eingeschränkt Sinn, wenn die Daten dann im Klartext von der NSA oder anderen Angreifern abgegriffen werden.
So: Verfahren bekannt, Schlüssel abgefangen, wo liegt also die Sicherheit?
Freilich kannst Du versuchen, z.B. mit JS (auf dem Client) und PHP (Server) sowas wie die übliche asymmetrische ssl-Verschlüsselung zu implementieren, bei der nicht öffentliche Schlüssel ausgetauscht werden. Grob gesagt geht das so: der Sender VERschlüsselt mit einem Schlüssel, der aus seinem geheimen und dem öffentlichem Schlüssel des Empfängers gebaut wird - der Empfänger ENTschlüsselt mit einem Schlüssel, der seinem geheimen Schlüssel und dem öffentlichen Schlüssel des Senders gebaut wird. Deshalb asymmetrisch. Um die Sicherheit zu verbessern gäbe dann noch diffi-hellmann zum Wechsel der Schlüssel e.t.c. - das wieder, weil z.B. wenn genug Klartext bekannt ist auf die verwendeten Schlüssel geschlossen werden kann. "diffi-hellmann" sorgt dafür, dass die Schlüssel sich verändern.
[1] gigantische Rainbow-Tables helfen inzwischen dabei, extrem viel Rechenzeit zu sparen.