Vergleich von hashed Passwörtern

  • Hallo Leute

    ich baue mir gerade eine Oberfläche für meinen Mailserver,

    um die Passwörter der Konten bequem über den Browser ändern zu können.

    Natürlich muss der Nutzer berechtigt sein, deshalb frage ich das alte PW vor

    der Änderung ab. Hierbei komme ich nicht weiter, da der Vergleich mit PHP(7.0)

    nicht klappt.

    $pw_alt kommt aus dem Formular

    $data['password'] aus der DB


    Code
    function testpwd($pwd){
            $password = $pwd;
            $salt = substr(sha1(rand()), 0, 16);
            $hashedPassword = "{SHA512-CRYPT}" . crypt($password, "$6$$salt");
            return $hashedPassword;
    }
    
    $antwort_alt= testpwd($pw_alt);
    echo var_dump(hash_equals($antwort_alt, $data['password']));    ///ergibt false
    echo var_dump(password_verify($pw_alt, $data['password']));  /// ergibt false

    vergleiche ich den neuen hash mit dovecot erhalte ich ein "verified".


    Code
    doveadm pw -t '{SHA512-CRYPT}$6$9e9e1a6158cb06cd$ctPwJ3sgyl/gGBf.77P//rpMJrii2SkyLEU/fQxVi8Yj4xmKi3tZDLmX/TmfMkdKlvY6XGBLoDlmmaeV48Gaf0' -p 'passwort12345'                                                                          
    {SHA512-CRYPT}$6$9e9e1a6158cb06cd$ctPwJ3sgyl/gGBf.77P//rpMJrii2SkyLEU/fQxVi8Yj4xmKi3tZDLmX/TmfMkdKlvY6XGBLoDlmmaeV48Gaf0 (verified)

    Google bringt mich leider auch nicht weiter

    Gibt es noch andere Wege/Möglichkeiten in PHP?



    Danke Im Voraus

    michi

    It's me, only me, pure michi 🦆

    RS 1000 SAS G8 | Cyber Quack

    VPS: 50 G7 |B Ostern 2017|200 | Karneval | piko

    WH: SmallEi | Adv17 Family |4000 SE|1000 SE

  • Hallo Michi,


    in testpwd erzeugst Du jedes mal einen neuen zufälligen salt. Dadurch kommt auch bei gleichem "alten" Passwort immer ein anderer Hash heraus.

    Du musst den gleichen salt verwenden, wie beim gespeicherten PW.

    Passend zu password_verify , kümmert sich password_hash automatisch darum

  • Hallo Andi,

    Oha da hatte ich das genau andersrum verstanden

    dass der jedesmal neu generiert werden muss.


    Danke

    It's me, only me, pure michi 🦆

    RS 1000 SAS G8 | Cyber Quack

    VPS: 50 G7 |B Ostern 2017|200 | Karneval | piko

    WH: SmallEi | Adv17 Family |4000 SE|1000 SE

  • Der Salt wird dann generiert, wenn du ein Passwort in die Datenbank schreibst.

    In der Datenbank steht dann ungefähr

    $[Hashfunktion-Id]]$[Salt]$[Hash von Passwort+Salt

    Wenn du das Passwort testen willst nimmst du den Salt aus der DB, kombinierst den mit dem gegebenen Passwort, hashst das ganze und vergleichst mit dem bekannten Hash.


    Wenn der User sein Passwort ändert, kannst du dann natürlich auch einen neuen Salt generieren und mit abspeichern.

    Current Servers

    morpheus: Root-Server M SSD v6a2
    apoc: VPS 50 G7
    link: Storage-Server S 1000 G7

  • Hi ,

    danke für euer Feedback

    ich habs jetzt so gelöst , dass ich den Salt separat in der DB abspeichere.

    Die Funktion hab ich dahingehend erweitert dass ich einen 2ten Wert mit übergebe.

    Ist ein Salt in der db vorhanden, wird er mit übergeben. Sollte kein Eintrag vorhanden sein,

    wird ein neuer Salt generiert und an die db weitergeleitet. Somit kann ich damit auch neue

    Passwörter generieren.Die ersten pwds wurden noch über dovecot erstellt und daher hatte

    ich dafür keinen salt. Diese Passwörter wurden ersetzt und somit bin ich da wo ich hin wollte.

    Verglichen wird über hash_equals() und das klappt alles gut.


    Danke an alle

    michi

    It's me, only me, pure michi 🦆

    RS 1000 SAS G8 | Cyber Quack

    VPS: 50 G7 |B Ostern 2017|200 | Karneval | piko

    WH: SmallEi | Adv17 Family |4000 SE|1000 SE

  • Ich will jetzt nicht pedantisch sein, aber für den Fall, dass jemand über eine Suche hier her kommt würde ich gerne ein paar Anmerkungen schreiben.


    Wenn man keinen besonderen Grund hat (z.B. Lerneffekt oder Interoperabilität mit anderen Sprachen) ist es fast immer eine gute Idee die eingebauten Funktionen einer Sprache zu verwenden.


    Hier also password_hash und password_verify


    Man kann bei einer Passwort-Hashing Funktion viel falsch machen, und bei den eingebauten Funktionen haben sich schon viele Entwickler mit dem Problem auseinandergesetzt.

    Und man profitiert automatisch von Verbesserungen die in neuen PHP-Releases implementiert werden.


    @Gunah Du hast Dich wahrscheinlich vertippt. Wegen der Timing Attacken sollte man die (von michi verwendete) hash_equals Funktion verwenden, und nicht strcmp.

    PHP strcmp verwendet die libc memcmp Implemetierung (siehe github und gehe zu ZEND_FUNCTION(strcmp)). Zumindest in der glibc ist diese aber genau für diese Timing Attacken anfällig (siehe Gnu-glibc-git)


    hash_equals macht einen, Timing Attacke sicheren, String Vergleich (Hat genau genommen gar nichts mit einem Hash zu tun. Es werden einfach 2 Strings verglichen).


    password_verify hingegen verifiziert ob ein Passwort-String dem speziell formatierten Hash-String, der von password_hash zurückgegeben wurde, entspricht.

    In diesem Hash-String ist unter anderem der Salt enthalten, so dass password_verify mit diesen Informationen und dem Passwort wieder einen Hash berechnen, und mit dem übergebenen Hash vergleichen kann.


    michi Viel Spaß und Erfolg mit Deinem Projekt!


    Jetzt wünsch ich Euch allen frohe Ostern und ein schönes Wochenende,

    Andi

  • @Andi22 ja korrekt, wenn ein PW mit "md5/hash" generiert wurde, klappt es nicht direkt mit "hash_equals" sprich es müssen alle PWs "umgewandelt" werden.

    mit strcmp und anderen Abfragen, kann man das ganze schon gut härten.


    Hier findet man Beispiele, zum nachstellen der Timing Attack

    https://www.cryptologie.net/ar…e-password-hashes-in-php/


    meines erachtens sollte man direkt auf password_hash und password_verify gehen, wird ab 5.4 unterstützt. vielleicht nicht direkt auf Argon (da erst ab 7.2).

  • @Andi22 ja korrekt, wenn ein PW mit "md5/hash" generiert wurde, klappt es nicht direkt mit "hash_equals" sprich es müssen alle PWs "umgewandelt" werden.

    mit strcmp und anderen Abfragen, kann man das ganze schon gut härten.

    Kannst Du das nähers erläutern ?

    Warum soll man "hash_equals" nicht verwenden können ? Funktional entspricht es (strcmp(string1,string2) === 0) (siehe php-git)


    Zitat

    meines erachtens sollte man direkt auf password_hash und password_verify gehen, wird ab 5.4 unterstützt. vielleicht nicht direkt auf Argon (da erst ab 7.2).

    Genau das wollte ich damit sagen. Volle Zustimmung.