1322 Stimmen

Wie verwenden Sie bcrypt zum Hashen von Passwörtern in PHP?

Ab und zu höre ich den Rat "Verwenden Sie bcrypt zum Speichern von Passwörtern in PHP, bcrypt regiert".

Aber was ist bcrypt? PHP bietet keine solchen Funktionen an, Wikipedia redet von einem Datei-Verschlüsselungsprogramm und die Websuche zeigt nur einige Implementierungen von Blowfish in verschiedenen Sprachen. Nun ist Blowfish auch in PHP über mcrypt verfügbar, aber wie hilft das beim Speichern von Passwörtern? Blowfish ist ein Allzweck-Chiffre, sie funktioniert in beide Richtungen. Wenn etwas verschlüsselt werden kann, kann es auch entschlüsselt werden. Passwörter benötigen jedoch eine Einweg-Hashfunktion.

Was ist die Erklärung?

1106voto

Andrew Moore Punkte 90339

bcrypt ist ein Hashing-Algorithmus, der mit Hardware skalierbar ist (über eine konfigurierbare Anzahl von Runden). Die Langsamkeit und die mehrfachen Runden stellen sicher, dass ein Angreifer massive Mittel und Hardware einsetzen muss, um Ihre Passwörter knacken zu können. Fügen Sie dazu pro Passwort Salze hinzu (bcrypt VERLANGT Salze) und Sie können sicher sein, dass ein Angriff praktisch unmöglich ist, es sei denn, es gibt entweder absurde Geldmittel oder Hardware.

bcrypt verwendet den Eksblowfish-Algorithmus zum Hashen von Passwörtern. Während die Verschlüsselungsphase von Eksblowfish und Blowfish genau gleich sind, sorgt die Schlüsselplanungsphase von Eksblowfish dafür, dass ein späterer Zustand sowohl vom Salz als auch vom Schlüssel (Benutzerpasswort) abhängt und kein Zustand ohne Kenntnis von beidem vorberechnet werden kann. Aufgrund dieses Schlüsselunterschieds ist bcrypt einseitiger Hash-Algorithmus. Sie können das Klartextpasswort nicht abrufen, ohne bereits das Salz, die Runden und den Schlüssel (Passwort) zu kennen. [Quelle]

Wie man bcrypt verwendet:

Mit PHP >= 5.5-DEV

Passwort-Hashing-Funktionen sind jetzt direkt in PHP >= 5.5 integriert. Sie können jetzt password_hash() verwenden, um einen bcrypt-Hash eines beliebigen Passworts zu erstellen:

 11
];
echo password_hash('rasmuslerdorf', PASSWORD_BCRYPT, $options)."\n";
// $2y$11$6DP.V0nO7YI3iSki4qog6OQI5eiO6Jnjsqg7vdnb.JgGIsxniOn4C

Um ein vom Benutzer bereitgestelltes Passwort gegen einen vorhandenen Hash zu überprüfen, können Sie password_verify() wie folgt verwenden:

``

Mit PHP >= 5.3.7, < 5.5-DEV (auch RedHat PHP >= 5.3.3)

Es gibt eine Kompatibilitätsbibliothek auf GitHub, die auf dem Quellcode der oben genannten Funktionen basiert, die ursprünglich in C geschrieben wurden und dieselbe Funktionalität bietet. Sobald die Kompatibilitätsbibliothek installiert ist, ist die Verwendung dieselbe wie oben (abzüglich der Kurzarray-Schreibweise, wenn Sie immer noch auf dem 5.3.x-Zweig sind).

Mit PHP < 5.3.7 (VERALTET)

Sie können die Funktion crypt() verwenden, um bcrypt-Hashes von Eingabestrings zu generieren. Diese Klasse kann automatisch Salze generieren und vorhandene Hashes gegen eine Eingabe überprüfen. Wenn Sie eine PHP-Version höher oder gleich 5.3.7 verwenden, wird dringend empfohlen, die integrierte Funktion oder die Kompatibilitätsbibliothek zu verwenden. Dieses Alternative wird nur aus historischen Gründen bereitgestellt.

class Bcrypt{
  private $rounds;

  public function __construct($rounds = 12) {
    if (CRYPT_BLOWFISH != 1) {
      throw new Exception("bcrypt in dieser Installation nicht unterstützt. Siehe http://php.net/crypt");
    }

    $this->rounds = $rounds;
  }

  public function hash($input){
    $hash = crypt($input, $this->getSalt());

    if (strlen($hash) > 13)
      return $hash;

    return false;
  }

  public function verify($input, $existingHash){
    $hash = crypt($input, $existingHash);

    return $hash === $existingHash;
  }

  private function getSalt(){
    $salt = sprintf('$2a$%02d$', $this->rounds);

    $bytes = $this->getRandomBytes(16);

    $salt .= $this->encodeBytes($bytes);

    return $salt;
  }

  private $randomState;
  private function getRandomBytes($count){
    $bytes = '';

    if (function_exists('openssl_random_pseudo_bytes') &&
        (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL ist langsam unter Windows
      $bytes = openssl_random_pseudo_bytes($count);
    }

    if ($bytes === '' && is_readable('/dev/urandom') &&
       ($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
      $bytes = fread($hRand, $count);
      fclose($hRand);
    }

    if (strlen($bytes) < $count) {
      $bytes = '';

      if ($this->randomState === null) {
        $this->randomState = microtime();
        if (function_exists('getmypid')) {
          $this->randomState .= getmypid();
        }
      }

      for ($i = 0; $i < $count; $i += 16) {
        $this->randomState = md5(microtime() . $this->randomState);

        if (PHP_VERSION >= '5') {
          $bytes .= md5($this->randomState, true);
        } else {
          $bytes .= pack('H*', md5($this->randomState));
        }
      }

      $bytes = substr($bytes, 0, $count);
    }

    return $bytes;
  }

  private function encodeBytes($input){
    // Der folgende Code stammt aus dem PHP Password Hashing Framework
    $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    $output = '';
    $i = 0;
    do {
      $c1 = ord($input[$i++]);
      $output .= $itoa64[$c1 >> 2];
      $c1 = ($c1 & 0x03) << 4;
      if ($i >= 16) {
        $output .= $itoa64[$c1];
        break;
      }

      $c2 = ord($input[$i++]);
      $c1 |= $c2 >> 4;
      $output .= $itoa64[$c1];
      $c1 = ($c2 & 0x0f) << 2;

      $c2 = ord($input[$i++]);
      $c1 |= $c2 >> 6;
      $output .= $itoa64[$c1];
      $output .= $itoa64[$c2 & 0x3f];
    } while (true);

    return $output;
  }
}

Sie können diesen Code wie folgt verwenden:

$bcrypt = new Bcrypt(15);

$hash = $bcrypt->hash('password');
$isGood = $bcrypt->verify('password', $hash);

Alternativ können Sie auch das Portable PHP Hashing Framework verwenden.

``

309voto

ircmaxell Punkte 159431

Also, du willst bcrypt verwenden? Super! Aber wie in anderen Bereichen der Kryptographie, solltest du es nicht selbst machen. Wenn du dich um Dinge wie das Verwalten von Schlüsseln, das Speichern von Salzen oder das Generieren von Zufallszahlen kümmern musst, machst du etwas falsch.

Der Grund ist einfach: Es ist so einfach, bcrypt zu vermasseln. Tatsächlich wirst du feststellen, dass fast jeder Code auf dieser Seite mindestens eines dieser gängigen Probleme hat.

Akzeptiere es, Kryptographie ist schwer.

Überlasse es den Experten. Überlasse es den Leuten, deren Aufgabe es ist, diese Bibliotheken zu pflegen. Wenn du eine Entscheidung treffen musst, machst du etwas falsch.

Verwende stattdessen einfach eine Bibliothek. Es gibt mehrere, je nach deinen Anforderungen.

Bibliotheken

Hier ist eine Aufschlüsselung einiger der am häufigsten verwendeten APIs.

PHP 5.5 API - (Verfügbar für 5.3.7+)

In PHP 5.5 wird eine neue API zur Passworthashierung eingeführt. Es gibt auch eine kompatibilitätsbibliothek, die von mir für 5.3.7+ gepflegt wird. Dies bietet den Vorteil einer durch Kollegen überprüften und einfachen Implementierung.

function register($benutzername, $passwort) {
    $hash = password_hash($passwort, PASSWORD_BCRYPT);
    speichern($benutzername, $hash);
}

function login($benutzername, $passwort) {
    $hash = ladeHashNachBenutzername($benutzername);
    if (password_verify($passwort, $hash)) {
        // Einloggen
    } else {
        // Fehler
    }
}

Es ist wirklich darauf ausgerichtet, extrem einfach zu sein.

Quellen:

48voto

Arkh Punkte 8340

Sie erhalten viele Informationen in Genug mit den regenbogenfarbenen Tabellen: Was Sie über sichere Passwortschemata wissen müssen oder Tragbares PHP-Passwort-Hashing-Framework.

Das Ziel ist es, das Passwort mit etwas Langsamem zu hashen, damit jemand, der Ihre Passwortdatenbank erhält, beim Brute-Forcen überschleicht (eine Verzögerung von 10 ms für die Überprüfung eines Passworts ist für Sie nichts, aber für jemanden, der versucht, es zu Brute-Forcen, ist es viel). Bcrypt ist langsam und kann mit einem Parameter verwendet werden, um auszuwählen, wie langsam es ist.

37voto

coreyward Punkte 72986

Sie können mit bcrypt einen Einweg-Hash erstellen, indem Sie die crypt()-Funktion von PHP verwenden und einen geeigneten Blowfish-Salt übergeben. Das Wichtigste an der gesamten Gleichung ist, dass A) der Algorithmus nicht kompromittiert wurde und B) Sie jedes Passwort ordnungsgemäß salzen. Verwenden Sie keinen anwendungsweiten Salz; das öffnet Ihre gesamte Anwendung für Angriffe aus einer einzigen Rainbow-Tabellensammlung.

PHP - Crypt Funktion

34voto

Jon Hulka Punkte 1219

Bearbeitung: 2013.01.15 - Wenn Ihr Server es unterstützt, verwenden Sie stattdessen martinstoecklis Lösung.


Jeder will es komplizierter machen, als es ist. Die crypt() -Funktion erledigt den größten Teil der Arbeit.

function blowfishCrypt($password,$cost)
{
    $chars='./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt=sprintf('$2y$%02d$',$cost);
//Für PHP < PHP 5.3.7 verwenden Sie stattdessen dies
//    $salt=sprintf('$2a$%02d$',$cost);
    //Erstellt ein 22 Zeichen langes Salz -Bearbeitung- 2013.01.15 - ersetzte rand durch mt_rand
    mt_srand();
    for($i=0;$i<22;$i++) $salt.=$chars[mt_rand(0,63)];
    return crypt($password,$salt);
}

Beispiel:

$hash=blowfishCrypt('password',10); //Das erstellt den Hash
$hash=blowfishCrypt('password',12); //Das erstellt einen sichereren Hash
if(crypt('password',$hash)==$hash){ /*ok*/ } //Dies prüft ein Passwort

Es sollte offensichtlich sein, aber bitte verwenden Sie nicht 'password' als Ihr Passwort.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X