kostenloser Webspace werbefrei: lima-city


Qt Passwort mit Passwort Hash aus Datenbank vergleichen

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    uebungen-till

    uebungen-till hat kostenlosen Webspace.

    Hallo,
    ich hoffe, dass ihr mir mit meinem Problem helfen könnt.

    Ich habe bereits mit dem Qt-Creator ein Login erstellt und möchte die Daten aus dem Formular mit Daten aus einer MySQL Datenbank vergleichen.

    Das auslesen der Daten funktioniert und ich möchte wissen, wie ich das eingegebene Passwort mit dem gehaschten Passwort aus der Datenbank vergleichen kann.

    Hier ist der Code vom Login:

    #include "login.h"
    #include "ui_login.h"
    #include "QtSql/QtSql"
    #include "string"
    
    login::login(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::login)
    {
        ui->setupUi(this);
    
        //--Verbindung zur Datenbank
            QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
            QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
            db.setHostName("uebungen-till.lima-db.de");
            db.setDatabaseName("db_356572_5");
            db.setUserName("USER356572");
            db.setPassword("top-secret"); // zensiert
            bool ok = db.open();
    
        //--Prüfung der Verbindung
            if(ok){
                ui->textEdit->setText("Verbindung hergestellt");
            } else {
                ui->textEdit->setText("Verbindung fehlgeschlagen");
            }
    }
    
    login::~login()
    {
        delete ui;
    }
    
    void login::on_pushButton_clicked()
    {
    //--Daten aus Formular
        QString username = ui->username->text();
        QString passwort = ui->passwort->text();
    
    //--SQL Abfrage
        QSqlQuery string("SELECT * FROM user WHERE `username` = '" + username + "'");
        while (string.next()) {
            QString pass = string.value(6).toString();
    
    //------Passwort ueberpruefen
            //Passwort aus dem Formular (passwort) soll mit dem gehashtem Passwort aus der Datenbank (pass) verglichen werden
        }
    }


    Ich danke schon mal im voraus für eure Hilfe.

    Beitrag zuletzt geändert: 14.6.2017 17:28:24 von hackyourlife
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. uebungen-till schrieb:
    Das auslesen der Daten funktioniert und ich möchte wissen, wie ich das eingegebene Passwort mit dem gehaschten Passwort aus der Datenbank vergleichen kann.

    Normalerweise hasht man das eingegebene Passwort mit der gleichen Funktion und vergleicht die beiden Hashs.

    Wenn ich deinen Code richtig verstehe, musst du also QString passwort mit QString pass abgleichen und QString passwort davor mit der gleichen Funktion, die in der Registrierung der User verwendet wird hashen.

    Ich kann leider C++ nicht so gut, aber ein einfaches if (passwort == pass) sollte das doch machen?!

    Wenn du nicht weiterkommst, wäre es für uns evtl. hilfreich, den Code der Registrierung zu sehen (wegen der dort verwendeten Hash-Funktion).
  4. Autor dieses Themas

    uebungen-till

    uebungen-till hat kostenlosen Webspace.

    Die Registrierung wurde mit PHP gemacht.

    Zum hashen in PHP habe ich das benutzt:
    password_hash($password, PASSWORD_DEFAULT);

    Beitrag zuletzt geändert: 15.6.2017 13:28:33 von uebungen-till
  5. webfreclan schrieb:
    Normalerweise hasht man das eingegebene Passwort mit der gleichen Funktion und vergleicht die beiden Hashs.

    Auch wenn das viele Leute so machen: Es trägt zu erfolgreichen Passwort-Leaks bei und ist einfach fahrlässig.

    uebungen-till schrieb:
    Die Registrierung wurde mit PHP gemacht.
    Zum hashen in PHP habe ich das benutzt:
    password_hash($password, PASSWORD_DEFAULT);

    Um möglichst kompatibel zu bleiben würde ich einfach im Sourcecode von PHP nachschauen wie die Funktion password_verify programmiert wurde und die dann entsprechend übernehmen oder nachbauen.

    Prinzipiell ist es aber eh keine gute Idee mit einer Client-Applikation direkt auf die Datenbank zuzugreifen. Zumal der DB-Nutzer bei Lima eh immer auch Schreibzugriff hat. Damit könnte man also problemlos auch einfach die Daten ändern.
    Baue da lieber eine entsprechende Schnittstelle und prüfe die Zugangsdaten auf Serverseite. Ebenso solltest du die entsprechenden DB-Operationen wie Lesen oder gar Schreiben serverseitig nach Authentifizierung ausführen.
  6. muellerlukas schrieb:
    Auch wenn das viele Leute so machen: Es trägt zu erfolgreichen Passwort-Leaks bei und ist einfach fahrlässig.

    Warum? Ich schreibe ja nicht, dass keine Salts, etc verwendet werden, sondern nur, dass man die gleiche Funktion verwendet. Außerdem meine ich damit ja nicht die reine Hash-Funktion ...

    Optimalerweise baut man sich dafür eine eigene Funktion, welche für jedes Passwort einen neuen Salt generiert und verwendet keine weit verbreitete Lösungen, die mögliche Ziele für Hacker sein könnten und bald wieder veraltet sind ...
  7. webfreclan schrieb:
    muellerlukas schrieb:
    Auch wenn das viele Leute so machen: Es trägt zu erfolgreichen Passwort-Leaks bei und ist einfach fahrlässig.

    Warum? Ich schreibe ja nicht, dass keine Salts, etc verwendet werden, sondern nur, dass man die gleiche Funktion verwendet. Außerdem meine ich damit ja nicht die reine Hash-Funktion ...

    Weil du von "hashen" redest und kurz darauf schreibst
    ein einfaches if (passwort == pass) sollte das doch machen?!
    .
    Was eben nur machbar ist wenn es ein Hash ohne Salt ist. Mit Salt müsste man vorher entsprechend den Salt auslesen und damit das Passwort hashen um zu vergleichen zu können.

    Optimalerweise baut man sich dafür eine eigene Funktion

    Nein, nicht wirklich. Grade beim Thema Verschlüsselungs- oder Hashalgorithmus sollte man nicht unbedingt selbst was zusammen bauen.
    welche für jedes Passwort einen neuen Salt generiert

    Genau das tut password_hash.

    und verwendet keine weit verbreitete Lösungen, die mögliche Ziele für Hacker sein könnten und bald wieder veraltet sind ...

    Ein selbstgeschriebener Algorithmus ist also sicherer weil er nicht so verbreitet ist? Sowas naives habe ich schon lange nicht mehr gelesen.
    Übrigens ist SHA2 immer noch als "sicher" anzusehen. Jeder Hashalgorithmus wird früher oder später "veraltet".
  8. Optimalerweise baut man sich dafür eine eigene Funktion, welche für jedes Passwort einen neuen Salt generiert und verwendet keine weit verbreitete Lösungen, die mögliche Ziele für Hacker sein könnten und bald wieder veraltet sind ...
    Security by obsucrity ist also wieder "in"? Ist das nicht im wesentlichen ein wenig widersprüchlich zu Kerckhoffs' Prinzip?
  9. uebungen-till schrieb:
    Zum hashen in PHP habe ich das benutzt:
    password_hash($password, PASSWORD_DEFAULT);
    Ok, dann schau dir mal die Funktion
    crypt()
    an. Diese gibt es zum einen als PHP-Funktion (siehe Manual). Dort steht z.B. folgendes:
    password_hash() ist ein einfacher crypt()-Wrapper und kompatibel zu bestehenden Passwort-Hashes.

    Tatsächlich kann man mit
    crypt()
    die Passworthashs überprüfen, die mit
    password_hash()
    erstellt wurden. Dazu übergibt man zuerst das Passwort und als zweites die Angaben über Algorithmus und Salt (also den entsprechenden Teil des Hashs) und vergleicht das Ergebnis mit dem vorgegebenen Hash.

    Die
    crypt()
    -Funktion gibt es auch für C++, zumindest bei Linux ist das so. (siehe Manpage)
    Falls du Windows einsetzt, musst du schauen ob es eine äquivalente Bibliothek für Windows gibt.

    Ich hab mich jetzt kurz gefasst und alles nur grob beschrieben, für Rückfragen bin ich da.
  10. Autor dieses Themas

    uebungen-till

    uebungen-till hat kostenlosen Webspace.

    fuerderer schrieb:
    Tatsächlich kann man mit
    crypt()
    die Passworthashs überprüfen, die mit
    password_hash()
    erstellt wurden. Dazu übergibt man zuerst das Passwort und als zweites die Angaben über Algorithmus und Salt (also den entsprechenden Teil des Hashs) und vergleicht das Ergebnis mit dem vorgegebenen Hash.


    Könntest du das evtl. an einem Beispiel erklären?
  11. Klar, mach ich.

    Zunächst einmal erzeuge ich einen Passworthash:
    $passwort = "passwort123";
    $hash = password_hash($passwort, PASSWORD_DEFAULT);
    echo $hash;
    Ergebnis (z.B.)
    $2y$10$4mijsKmr44Tt5OlakgacueA6w.K.8K8l12Up1PVPl4b052hWpFk.C
    Hier kommt bei jedem Aufruf der Funktion
    password_hash()
    ein anderes Ergebnis heraus, deshalb bekommst du nicht genau den gleichen Wert, falls du das wiederholst.


    Jetzt erkläre ich kurz die Bestandteile des Hashs:
    $2y$10$
    Angaben über den Algorithmus (und hier z.B. noch die verwendete Zahl der Runden)
    4mijsKmr44Tt5Olakgacue
    Der Salt (hier 22 Zeichen, das gilt aber nicht für jeden Algorithmus)
    A6w.K.8K8l12Up1PVPl4b052hWpFk.C
    Der eigentliche Hashwert


    Ich musste feststellen, dass du den Salt nicht zuverlässig vom Hashwert abtrennen kannst, da die Trennung eben abhängig vom Algorithmus wäre. Es gibt aber eine einfachere Lösung, denn man kann auch den ganzen Hashwert übergeben und der Algorithmus nimmt sich dann seinen Salt.

    Hier also die Überprüfung eines Passworts:
    $passwort = "passwort123";
    $hash = "$2y$10$4mijsKmr44Tt5OlakgacueA6w.K.8K8l12Up1PVPl4b052hWpFk.C";
    $kontrollhash = crypt($passwort, $hash);
    echo $kontrollhash."\n";
    var_dump($hash == $kontrollhash); // Vorsicht mit dem Vergleichsoperator!
    Ergebnis:
    $2y$10$4mijsKmr44Tt5OlakgacueA6w.K.8K8l12Up1PVPl4b052hWpFk.C
    bool(true)


    Wenn das Passwort nicht stimmt, kommt ein anderer Hashwert heraus:
    $passwort = "passwort124";
    Fürht zu:
    $2y$10$4mijsKmr44Tt5Olakgacuea5V4gj1Gu.U3C0B0XKti0sY57dubtzW
    bool(false)


    Ich schrieb noch: Vorsicht mit dem Vergleichsoperator!
    PHP empfiehlt, beim Vergleich solcher Hashwerte eine Funktion zu verwenden, die nicht für Timing-Attacken anfällig ist und bietet zu diesem Zweck die Funktion
    hash_equals()
    . Für C++ gilt dies prinzipiell auch. Wenn du das beachten möchtest, kann ich auch hierzu noch Beispielcode liefern.
  12. Autor dieses Themas

    uebungen-till

    uebungen-till hat kostenlosen Webspace.

    Ein Beispielcode für C++ wäre nicht schlecht.


    Ich hätte noch eine Frage:
    muellerlukas schrieb:
    Prinzipiell ist es aber eh keine gute Idee mit einer Client-Applikation direkt auf die Datenbank zuzugreifen. Zumal der DB-Nutzer bei Lima eh immer auch Schreibzugriff hat. Damit könnte man also problemlos auch einfach die Daten ändern.
    Baue da lieber eine entsprechende Schnittstelle und prüfe die Zugangsdaten auf Serverseite. Ebenso solltest du die entsprechenden DB-Operationen wie Lesen oder gar Schreiben serverseitig nach Authentifizierung ausführen.

    Wie könnte ich das mit der serverseitigen Authentifizierung machen?
    Ein Beispielcode dafür wäre auch nicht schlecht.
  13. Also, hier noch ein Beispiel für einen timing-safe Stringvergleich in C++:
    bool hash_equals(const char *a, const char *b) {
      bool equals = true;
      while (true) {
        equals &= (*a == *b);
        if (!(*a && *b)) {
          return equals;
        }
        a++;
        b++;
      }
    }
    Am besten, man kompiliert das ohne Optimierung, damit der Compiler nicht noch irgendwelchen Mist macht.


    uebungen-till schrieb:
    Wie könnte ich das mit der serverseitigen Authentifizierung machen?
    Dazu brauchst du serverseitig ein Programm, das den Hashwert aus der Datenbank liest, ein vom Nutzer übergebenes Passwort damit überprüft und dann dem Client antwortet ob die Anmeldung erfolgreich war. Außerdem muss das Programm alle Serverzugriffe überwachen (was auch immer die Nutzer genau machen können) und dabei sicherstellen, dass nur angemeldete Nutzer zugreifen können.
    Ist deine MySql Datenbank bei Lima-City? Dann wirst du wohl PHP für die Authentifizierung verwenden. Hast du einen eigenen Server, kannst du auch andere Möglichkeiten in Betracht ziehen.

    Ein Beispielprogramm wäre jetzt komplex, etwas Vorarbeit solltest du schon leisten. Wenn es an einem bestimmten Punkt klemmt, dann helfe ich gerne wieder.
  14. Autor dieses Themas

    uebungen-till

    uebungen-till hat kostenlosen Webspace.

    fuerderer schrieb:
    Dazu brauchst du serverseitig ein Programm, das den Hashwert aus der Datenbank liest, ein vom Nutzer übergebenes Passwort damit überprüft und dann dem Client antwortet ob die Anmeldung erfolgreich war.

    Das könnte ich mit PHP machen.
    Ich würde dann auch gleich alle anderen benötigten Daten auslesen und in eine .txt Datei schreiben, welche dann mit Qt ausgelesen wird.

    Hättest du evtl ein Beispiel, wie ich mit Qt das PHP-Script aufrufe?
  15. Ein Beispiel gibt es hier: http://doc.qt.io/qt-5/qtnetwork-http-example.html
    In der "http/httpwindow.cpp" steht wohl der Code zum eigentlichen Download. Ich hab das aber nur überflogen, scheint auf den ersten Blick relativ viel zu sein.

    Grob zum Verständnis: Das C++ Programm ruft eine .php-Datei vom Webserver auf und damit startet dieses PHP-Skript auf dem Server automatisch. Und wenn PHP Ausgaben macht (z.b. mit echo), dann empfängt C++ diese Ausgaben und macht damit irgendwas, das Beispielskript speichert es in eine Datei.

    Was ich damit sagen möchte: Serverseitig brauchst du keine Textdatei zu erzeugen. Was zum C++ Programm übertragen werden soll, gibst du einfach mit echo aus.
  16. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!