# [PHP/Meinung] Rubiks salted hash



## Ap0ll0XT (25. August 2015)

Ich habe da mal eine Frage. Ich habe für mein RIA-Framework eine Funktion zum hashen eines Passwortes inklusive Salt geschrieben. Mein Ziel war es, Bruteforce, Rainbowtable und Kollissionsangriffe so gut wie möglich zu erschweren. Nun würde ich mich freuen, wenn da ein paar mehr drüber schauen können, ob es damit Probleme gibt oder ob man den Code so nehmen kann. Viele Augen sehen mehr als nur 4 (ich trage Brille  ).

Zum Code:

```
function rubiksSaltedHash($password,$regstamp) {
        $hashed_stamp = substr(preg_replace("![^0-9]!","",hash("sha256",$regstamp)),0,12);
        $hashes = array("md5","sha1","sha256","sha384","ripemd128","ripemd160","ripemd256","ripemd320","snefru","gost");
        $salt_len = (int) $hashed_stamp[11] > 0 ? (int) $hashed_stamp[11] : 9;
        $pw_prehash = $hashes[(int) $hashed_stamp[10]];
        $signarray[0] = array("a","c","e","g","h","j","l","n","p","r");
        $signarray[1] = array("b","d","f","i","k","m","o","q","s","t");
        $signarray[2] = array("1","3","5","7","9","#","*","-",".",",");
        $signarray[3] = array("2","3","6","8","0",":","_","=","/","!");
        $conv_timestamp = str_split(substr((string) $hashed_stamp,0,$salt_len));
        $salt = "";
        foreach($conv_timestamp as $num) {
            $salt .= $signarray[0][(int) $num];
            $salt .= $signarray[1][(int) $num];
            $salt .= $signarray[2][(int) $num];
            $salt .= $signarray[3][(int) $num];
            $signarray[0] = array_reverse($signarray[0]);
            $signarray[1] = array_reverse($signarray[1]);
            $signarray[2] = array_reverse($signarray[2]);
            $signarray[3] = array_reverse($signarray[3]);
            $signarray = array_reverse($signarray);
        }
        $spl_salt = str_split($salt);
        $pass = array_reverse(str_split(hash($hashes[(int) $hashed_stamp[10]],$password)));
        $new_password = "";
        if(count($pass) > count($spl_salt)) {
            foreach($pass as $num => $char) {
                $new_password .= $char;
                if(isset($spl_salt[$num])) {
                    $new_password .= $spl_salt[$num];
                }
            }
        } else {
            foreach($spl_salt as $num => $char) {
                $new_password .= $char;
                if(isset($pass[$num])) {
                    $new_password .= $pass[$num];
                }
            }
        }
        return hash("sha512",$new_password);
    }
```
Eine Demo zum testen: DEMO: Rubiks Salted SHA512 Hash

Screenshot von der Demo (wer nicht auf den Link klicken will - Demo mit PHP Desktop):



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Ist das so brauchbar oder eher nicht. Wenn nicht, warum?


----------



## Festplatte (25. August 2015)

Von der Erstellung einer eigenen Funktion für's Passwort-Hashing rate ich dringend ab. Du hast dir mit deiner Funktion vermutlich viel Mühe gegeben und das ist schön. Ich bezweifle allerdings, dass du ein Sicherheitsexperte bist und viel Erfahrung im Bereich der Passwort-Verschlüsselung hast - als Anfänger in diesem Bereich lässt sich einfach zu viel falsch machen, gerade bei solch sensiblen Daten wie Passwörtern. PHP stellt dir z. B. password_hash zur Verfügung, welche das übergebene Passwort standardmäßig mit Blowfish verschlüsselt. Blowfisch ist ein Blockverschlüsselungsalgorithmus der extra zum Verschlüsseln von Passwörten kreiert wurde und für deinen Einsatzzweck optimal sein wird. Um das Passwort mit dem Eingegebenen zu vergleichen, wird password_verify verwendet. Um so Sachen wie Salting, etc. musst du dich hiermit nicht mehr kümmern, das wird alles automatisch von der Funktion übernommen.

Lesestoff:

cryptography - Why shouldn't we roll our own? - Information Security Stack Exchange

How do you use bcrypt for hashing passwords in PHP? - Stack Overflow

php - How can I store my users' passwords safely? - Stack Overflow


----------



## DKK007 (25. August 2015)

Allerdings ist Blowfish ja ein symmetrisches Verschlüsselungsverfahren. Ich würde da schon nen richtiges Hashverfahren verwenden. Allerdings sollten auch gleich nur aktuell sichere (SHA-256 oder gleich SHA-512) verwendet werden. MD5 kann als gebrochen angesehen werden.


----------



## Ap0ll0XT (25. August 2015)

Danke für die ersten Rückmeldungen. Die password_hash Funktion war mir bis jetzt noch unbekannt. Dürfte aber daran gelegen haben, das ich schon mehrere Jahre aus PHP raus war.



DKK007 schrieb:


> Allerdings ist Blowfish ja ein symmetrisches Verschlüsselungsverfahren. Ich würde da schon nen richtiges Hashverfahren verwenden. Allerdings sollten auch gleich nur aktuell sichere (SHA-256 oder gleich SHA-512) verwendet werden. MD5 kann als gebrochen angesehen werden.



Das habe ich auch gedacht, als ich Blowfish gelesen habe. Mir ist es auch nur als Verschlüsselung und nicht als Hash bekannt. Die im $hashes Array integrierten Algos sind nur zum Prehash und wurden deswegen unterschiedlich gewählt, um eine dynamisch lange Zeichenkette zu erzeugen, ohne das Passwort im Klartext in den mit sha512 zu hashenden String zu speichern.

Mein erster Entwurf erzeugte mit sha1 aus dem Passwort einen 40 stelligen hash und der Salt war immer 42 stellig. Das waren zusammen 82 stellen. Das war mir für Bruteforce zu leicht.

*EDIT:* Ich sehe gerade, das password_hash erst ab PHP 5.5.0 verfügbar ist. Mein Code könnte daher zur Not als Fallbacklösung herhalten.

*EDIT2:* Es scheint sich bei password_hash tatsächlich um einen Hash zu handeln. Allerdings kommt es mir doch sehr abstrakt vor, das die benötigten Parameter für verify direkt mit im Hash sind. Aber wenn das am ende die benötigte Sicherheit bringt.


----------



## Icephoen1x (26. August 2015)

Warum so kompliziert? Wenn du schon den timestamp nimmst kannste den auch direkt hashen, da dein code open source ist macht das keinen unterschied ob du da jetzt draus irgendeinen zwischenwert berechnest oder nicht. Wenn jemand wirklich dein passwort knacken wollte kann er sich einfach deinen open source code anschauen und vorher halt einmal schnell den salt berechnen.  Da kannst du dir einfacher ein salt machen indem du den timestamp einfach hashest oder so.
Außerdem, falls array reverse das macht was ich denke, hast du bei jedem zweiten durchlauf deiner schleife wieder die gleichen arrays wie am anfang. Das ist etwa das gleiche als würdest du bei deinem rubiks cube nur eine seite immer hin und her drehen. (Ganz davon abgesehen das der rubiks cube vergleich ehh hinkt da bei einem rubiks ja alle seiten gleichzeitig verändert werden)
Also ich würde da eher auf altbewährtes zurückgreifen, da einfacher und genau so sicher.


----------

