passwords password - Wie benutzt man bcrypt zum Hashing von Passwörtern in PHP?





generator example (9)


Edit: 2013.01.15 - Wenn Ihr Server es unterstützt, verwenden Sie stattdessen die Lösung von martinstoeckli.

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

function blowfishCrypt($password,$cost)
{
    $chars='./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt=sprintf('$2y$%02d$',$cost);
//For PHP < PHP 5.3.7 use this instead
//    $salt=sprintf('$2a$%02d$',$cost);
    //Create a 22 character salt -edit- 2013.01.15 - replaced rand with 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); //This creates the hash
$hash=blowfishCrypt('password',12); //This creates a more secure hash
if(crypt('password',$hash)==$hash){ /*ok*/ } //This checks a password

Ich weiß, es sollte offensichtlich sein, aber bitte benutze kein Passwort als Passwort.

Hin und wieder höre ich den Hinweis "Benutze bcrypt zum Speichern von Passwörtern in PHP, bcrypt-Regeln".

Aber was ist bcrypt ? PHP bietet keine solchen Funktionen, Wikipedia plappert über ein Dienstprogramm zur Dateiverschlüsselung und Web-Suchen zeigen nur einige Implementierungen von Blowfish in verschiedenen Sprachen. Jetzt ist Blowfish auch in PHP über mcrypt , aber wie hilft das beim Speichern von Passwörtern? Blowfish ist eine allgemeine Chiffre, es funktioniert auf zwei Arten. Wenn es verschlüsselt werden könnte, kann es entschlüsselt werden. Passwörter benötigen eine Einweg-Hashing-Funktion.

Was ist die Erklärung?




bcrypt ist ein Hashing-Algorithmus, der mit der Hardware skalierbar ist (über eine konfigurierbare Anzahl von Runden). Seine Langsamkeit und mehrere Runden stellen sicher, dass ein Angreifer massive Mittel und Hardware bereitstellen muss, um Ihre Kennwörter knacken zu können. Fügen Sie zu den per-Passwort- salts ( bcrypt REQUIRES salts) und Sie können sicher sein, dass ein Angriff ohne entweder lächerliche Menge an Geldmitteln oder Hardware praktisch undurchführbar ist.

bcrypt verwendet den Eksblowfish- Algorithmus zum Hashing von Kennwörtern. Während die Verschlüsselungsphase von Eksblowfish und Blowfish genau gleich ist, stellt die wichtige Planungsphase von Eksblowfish sicher, dass jeder nachfolgende Status sowohl von "salt" als auch von "key" (Benutzerkennwort) abhängt und kein Zustand ohne das Wissen beider vorausberechnet werden kann. Aufgrund dieses wichtigen Unterschieds ist bcrypt ein Einweg-Hashing-Algorithmus. Sie können das Klartext-Passwort nicht abrufen, ohne bereits das Salz, die Runden und den Schlüssel (Passwort) zu kennen. [ Source ]

Wie benutze ich bcrypt:

Mit PHP> = 5.5-DEV

Password Hashing Funktionen wurden nun direkt in PHP> = 5.5 eingebaut . Sie können nun mit password_hash() einen bcrypt Hash eines beliebigen Passworts erstellen:

<?php
// Usage 1:
echo password_hash('rasmuslerdorf', PASSWORD_DEFAULT)."\n";
// $2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// For example:
// $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

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

Um ein vom Benutzer angegebenes Passwort gegen einen vorhandenen Hash zu verifizieren, können Sie password_verify() als solches verwenden:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

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

Es gibt eine Kompatibilitätsbibliothek auf GitHub die basierend auf dem Quellcode der oben genannten Funktionen, die ursprünglich in C geschrieben wurden, erstellt wurde und dieselbe Funktionalität bietet. Sobald die Kompatibilitätsbibliothek installiert ist, ist die Verwendung die gleiche wie oben (abzüglich der Schreibweise des Kurzformats, wenn Sie sich noch im Zweig 5.3.x befinden).

Verwenden von PHP <5.3.7 (DEPRECATED)

Sie können die crypt() -Funktion verwenden, um bcrypt-Hashes von Eingabezeichenfolgen zu generieren. Diese Klasse kann automatisch Salze generieren und bestehende Hashes gegen eine Eingabe verifizieren. Wenn Sie eine Version von PHP höher oder gleich 5.3.7 verwenden, wird dringend empfohlen, die integrierte Funktion oder die compat-Bibliothek zu verwenden . Diese Alternative ist nur für historische Zwecke vorgesehen.

class Bcrypt{
  private $rounds;

  public function __construct($rounds = 12) {
    if (CRYPT_BLOWFISH != 1) {
      throw new Exception("bcrypt not supported in this installation. See 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 is slow on 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){
    // The following is code from the 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 .




Für OAuth 2- Kennwörter:

$bcrypt = new \Zend\Crypt\Password\Bcrypt;
$bcrypt->create("youpasswordhere", 10)



Sie erhalten eine Menge an Informationen in Genug mit den Rainbow Tables: Was Sie über sichere Passwort-Schemata oder Portable PHP Password Hashing Framework wissen müssen .

Das Ziel ist es, das Passwort mit etwas Langsamem zu hashen, damit jemand, der Ihre Passwort-Datenbank bekommt, stirbt, wenn Sie versuchen, es brutal zu erzwingen (eine Verzögerung von 10 ms, um ein Passwort zu überprüfen, ist nichts für Sie, viel für jemanden, der es brutal erzwingen will). Bcrypt ist langsam und kann mit einem Parameter verwendet werden, um auszuwählen, wie langsam es ist.




Aktuelles Denken: Hashes sollten möglichst langsam und nicht so schnell wie möglich sein. Dies unterdrückt Rainbow-Table- Angriffe.

Auch verwandt, aber vorsorglich: Ein Angreifer sollte niemals uneingeschränkten Zugriff auf Ihren Anmeldebildschirm haben. Um dies zu verhindern: Richten Sie eine IP-Adressen-Verfolgungstabelle ein, die jeden Treffer zusammen mit dem URI aufzeichnet. Wenn mehr als 5 Anmeldeversuche von derselben IP-Adresse in einem Zeitraum von fünf Minuten kommen, blockieren Sie mit einer Erläuterung. Ein sekundärer Ansatz besteht darin, ein zweistufiges Passwortschema zu verwenden, wie dies Banken tun. Eine Sperre für Fehler im zweiten Durchgang erhöht die Sicherheit.

Zusammenfassung: Verlangsamen Sie den Angreifer, indem Sie zeitraubende Hash-Funktionen verwenden. Blockieren Sie auch zu viele Zugriffe auf Ihr Login und fügen Sie eine zweite Passwort-Ebene hinzu.




Eine Alternative ist die Verwendung von Scrypt, das Colin Percival in seiner Arbeit überlegen ist. Es gibt eine scrypt PHP Erweiterung in PECL . Im Idealfall würde dieser Algorithmus in PHP umgewandelt werden, so dass er für die Funktionen password_ * spezifiziert werden könnte (idealerweise als "PASSWORD_SCRYPT"), aber das ist noch nicht da.




Version 5.5 von PHP wird integrierte Unterstützung für BCrypt, die Funktionen password_hash() und password_verify() . Eigentlich sind dies nur Wrapper um die Funktion crypt() und sollen es einfacher machen, sie richtig zu benutzen. Es sorgt für die Erzeugung eines sicheren Zufallssalzes und liefert gute Standardwerte.

Der einfachste Weg, diese Funktionen zu verwenden, ist:

$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

Dieser Code hasht das Passwort mit BCrypt (Algorithmus 2y ), generiert ein zufälliges Salz aus der Zufallsquelle des Betriebssystems und verwendet den Standardkostenparameter (im Moment ist dies 10). Die zweite Zeile prüft, ob das eingegebene Passwort mit einem bereits gespeicherten Hash-Wert übereinstimmt.

Wenn Sie den Kostenparameter ändern möchten, können Sie dies tun, indem Sie den Kostenparameter um 1 erhöhen, die benötigte Zeit für die Berechnung des Hashwerts verdoppelt:

$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 11));

Im Gegensatz zum Parameter "cost" ist es besser, den Parameter "salt" wegzulassen, da die Funktion bereits versucht, ein kryptographisch sicheres Salz zu erzeugen.

Für PHP Version 5.3.7 und höher gibt es ein Kompatibilitäts-Paket , von demselben Autor, der die Funktion password_hash() hat. Für PHP-Versionen vor 5.3.7 gibt es keine Unterstützung für crypt() mit 2y , dem unicode-sicheren BCrypt-Algorithmus. Man könnte es stattdessen durch 2a ersetzen, was die beste Alternative für frühere PHP-Versionen ist.




Sie können einen Einweg-Hash mit bcrypt erstellen, indem Sie die crypt() -Funktion von PHP verwenden und ein entsprechendes Blowfish-Salz übergeben. Die wichtigste der ganzen Gleichung ist, dass A) der Algorithmus nicht kompromittiert wurde und B) Sie jedes Passwort richtig salzen . Verwenden Sie kein anwendungsweites Salz; Das öffnet Ihre gesamte Anwendung, um von einem einzigen Satz Rainbow-Tabellen aus anzugreifen.

PHP - Crypt-Funktion




Die beste Idee, um Ihre Daten in der Datenbank zu verschlüsseln / entschlüsseln, selbst wenn Sie Zugriff auf den Code haben, ist die Verwendung von zwei verschiedenen user-pass ein privates Passwort ( user-pass ) für jeden Benutzer und einen privaten Code für alle Benutzer ( system-pass ).

Szenario

  1. user-pass wird mit MD5 in der Datenbank gespeichert und wird verwendet, um jeden Benutzer für die Anmeldung am System zu validieren. Dieser Benutzerpass ist für jeden Benutzer unterschiedlich.
  2. Jeder Benutzereintrag in der Datenbank hat in md5 einen system-pass für die Verschlüsselung / Entschlüsselung der Daten. Dieser Systempass ist für jeden Benutzer gleich.
  3. Jedes Mal, wenn ein Benutzer aus dem System entfernt wird, müssen alle Daten, die unter dem alten Systempass verschlüsselt sind, erneut unter einem neuen Systempass verschlüsselt werden, um Sicherheitsprobleme zu vermeiden.




php passwords cryptography password-protection bcrypt