1250 Stimmen

Sicherer Hash und Salt für PHP-Passwörter

Derzeit wird behauptet, dass MD5 teilweise unsicher ist. In Anbetracht dessen würde ich gerne wissen, welchen Mechanismus ich für den Passwortschutz verwenden soll.

Diese Frage, Ist das "doppelte Hashing" eines Passworts weniger sicher als das einmalige Hashing? legt nahe, dass mehrfaches Hashing eine gute Idee sein kann, während Wie kann man einen Passwortschutz für einzelne Dateien einrichten? empfiehlt die Verwendung von Salz.

Ich verwende PHP. Ich möchte ein sicheres und schnelles Passwort-Verschlüsselungssystem. Das millionenfache Hashing eines Passworts ist zwar sicherer, aber auch langsamer. Wie lässt sich ein gutes Gleichgewicht zwischen Geschwindigkeit und Sicherheit erreichen? Außerdem möchte ich, dass das Ergebnis eine konstante Anzahl von Zeichen hat.

  1. Der Hashing-Mechanismus muss in PHP verfügbar sein
  2. Es muss sicher sein
  3. Es kann Salz verwendet werden (sind in diesem Fall alle Salze gleich gut? Gibt es eine Möglichkeit, gute Salze zu erzeugen?)

Sollte ich außerdem zwei Felder in der Datenbank speichern (z. B. eines mit MD5 und ein anderes mit SHA)? Wäre es dadurch sicherer oder unsicherer?

Falls ich mich nicht klar genug ausgedrückt habe, möchte ich wissen, welche Hashing-Funktion(en) zu verwenden sind und wie man einen guten Salt auswählt, um einen sicheren und schnellen Passwortschutzmechanismus zu haben.

Verwandte Fragen, die meine Frage nicht ganz abdecken:

Was ist der Unterschied zwischen SHA und MD5 in PHP?
Einfache Passwortverschlüsselung
Sichere Methoden zur Speicherung von Schlüsseln und Passwörtern für asp.net
Wie würden Sie gesalzene Passwörter in Tomcat 5.5 implementieren?

14 Stimmen

openwall.com/phpass ist auch eine sehr gute Bibliothek

60 Stimmen

Md5 ist jetzt völlig unsicher

3 Stimmen

@NSAwesomeGuy Das hängt davon ab, wofür Sie es verwenden. Es ist trivial, ungesalzene MD5-Passwörter mit Rainbow-Match oder Brute-Force zu knacken, aber mit anständigem Salting ist es immer noch äußerst unpraktisch, eine Rainbow-Tabelle zum schnellen Knacken von Passwortsätzen zu erstellen, und Brute-Force ist ein No-Hoper.

8voto

Jason OOO Punkte 3517

Ich habe hier das perfekte Thema zu diesem Thema gefunden: https://crackstation.net/hashing-security.htm Ich wollte, dass Sie davon profitieren, hier ist auch der Quellcode, der auch einen Schutz gegen zeitbasierte Angriffe bietet.

<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTES", 24);
define("PBKDF2_HASH_BYTES", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" . 
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTES,
            true
        ));
}

function validate_password($password, $good_hash)
{
    $params = explode(":", $good_hash);
    if(count($params) < HASH_SECTIONS)
       return false; 
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0; 
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
?>

1 Stimmen

Sie geben uns eine Lösung ohne Nutzung keine Nutzung

7voto

rmeador Punkte 25087

Ich verwende in der Regel SHA1 und Salt mit der Benutzer-ID (oder einer anderen benutzerspezifischen Information), und manchmal verwende ich zusätzlich ein konstantes Salt (so dass ich zwei Teile des Salt habe).

SHA1 gilt inzwischen auch als etwas gefährdet, allerdings in einem weitaus geringeren Maße als MD5. Durch die Verwendung eines Salzes (irgendeines Salzes) verhindern Sie die Verwendung eines generischen Regenbogentisch um Ihre Hashes anzugreifen (einige Leute haben sogar Erfolg damit gehabt, Google als eine Art Regenbogentabelle zu verwenden, indem sie nach dem Hash gesucht haben). Es ist denkbar, dass ein Angreifer eine Regenbogentabelle mit Ihrem Salt generiert, deshalb sollten Sie ein benutzerspezifisches Salt hinzufügen. Auf diese Weise muss der Angreifer eine Regenbogentabelle für jeden einzelnen Datensatz in Ihrem System erstellen, nicht nur eine für Ihr gesamtes System! Mit dieser Art von Salting ist sogar MD5 anständig sicher.

2 Stimmen

Konstantes Salz ist keine gute Idee... wahrscheinlich kein fataler Fehler, aber es schwächt das System unnötig.

0 Stimmen

MD5 und SHA1 sind schnell, daher ist dies ein schlechter Wert.

5voto

Henrik Paul Punkte 65301

SHA1 und ein Salz sollten ausreichen (abhängig natürlich davon, ob Sie etwas für Fort Knox oder ein Anmeldesystem für Ihre Einkaufsliste) für die absehbare Zukunft. Wenn SHA1 für Sie nicht gut genug ist, verwenden Sie SHA256 .

Die Idee eines Salzes ist es, die Hashing-Ergebnisse sozusagen aus dem Gleichgewicht zu bringen. Es ist zum Beispiel bekannt, dass der MD5-Hash einer leeren Zeichenkette d41d8cd98f00b204e9800998ecf8427e . Wenn also jemand, der ein gutes Gedächtnis hat, diesen Hash sieht, weiß er, dass es sich um den Hash einer leeren Zeichenfolge handelt. Wenn die Zeichenfolge jedoch gesalzen ist (z. B. mit der Zeichenfolge " MY_PERSONAL_SALT "), der Hash für den "leeren String" (d.h. " MY_PERSONAL_SALT ") wird aeac2612626724592271634fb14d3ea6 Daher ist es nicht offensichtlich, dass sie zurückverfolgt werden können. Was ich damit sagen will, ist, dass es besser ist, die jede Salz, als es nicht zu tun. Daher ist es nicht allzu wichtig, zu wissen que Salz zu verwenden.

Es gibt tatsächlich Websites, die genau dies tun - kann man einen (md5)-Hash eingeben, und er spuckt einen bekannten Klartext aus, der diesen speziellen Hash erzeugt. Wenn Sie Zugang zu einer Datenbank hätten, die einfache md5-Hashes speichert, wäre es für Sie trivial, den Hash für den Administrator eines solchen Dienstes einzugeben und sich anzumelden. Wären die Kennwörter jedoch gesalzen, würde ein solcher Dienst unwirksam werden.

Auch das Double-Hashing wird allgemein als schlechte Methode angesehen, da es den Ergebnisraum verkleinert. Alle gängigen Hashes sind von fester Länge. Sie können also nur eine begrenzte Anzahl von Werten dieser festen Länge haben, und die Ergebnisse werden weniger vielfältig. Diese könnte als eine weitere Form des Salzens angesehen werden, aber ich würde es nicht empfehlen.

0 Stimmen

Die Zielseite sollte keine allzu sensiblen Daten enthalten (es handelt sich nicht um eine Bank), aber ich würde sie trotzdem lieber gesichert haben.

1 Stimmen

Doppeltes Hashing reduziert den Ergebnisraum nicht. Iteratives Hashing ist ein gängiges Mittel gegen Wörterbuch- und Brute-Force-Angriffe (es verlangsamt diese viel mehr als die Passwortprüfung).

2 Stimmen

@frankodwyer: Ja, es ist schlimm. sha1(sha1($foo)) reduziert den Ausgaberaum effektiv, da jede Kollision der inneren Funktion automatisch zu einer Kollision der äußeren wird. Die Verschlechterung ist zwar linear, aber dennoch ein Problem. Bei den iterativen Hashing-Methoden werden in jeder Runde Daten zurückgespielt, wie z. B. $hash = sha1(sha1($salt . $password) . $salt) . Aber das ist immer noch nicht gut... Bleiben Sie bei PBKDF2 oder Bcrypt...

-7voto

shalvasoft Punkte 89

Ok in der Fitsy brauchen wir Salz Salz muss eindeutig sein Erzeugen wir es also

   /**
     * Generating string
     * @param $size
     * @return string
     */
    function Uniwur_string($size){
        $text = md5(uniqid(rand(), TRUE));
        RETURN substr($text, 0, $size);
    }

Außerdem brauchen wir den Hash Ich verwende sha512 es ist das beste und es ist in php

   /**
     * Hashing string
     * @param $string
     * @return string
     */
    function hash($string){
        return hash('sha512', $string);
    }

Jetzt können wir diese Funktionen verwenden, um ein sicheres Passwort zu erzeugen

// generating unique password
$password = Uniwur_string(20); // or you can add manual password
// generating 32 character salt
$salt = Uniwur_string(32);
// now we can manipulate this informations

// hashin salt for safe
$hash_salt = hash($salt);
// hashing password
$hash_psw = hash($password.$hash_salt);

Jetzt müssen wir den Wert unserer Variablen $hash_psw und $salt in der Datenbank speichern

und für die Autorisierung werden wir dieselben Schritte anwenden...

es ist der beste Weg, um die Passwörter unserer Kunden zu schützen...

P.s. für die letzten 2 Schritte können Sie Ihren eigenen Algorithmus verwenden... aber seien Sie sicher, dass Sie dieses Hash-Passwort in der Zukunft generieren können wenn Sie einen Benutzer autorisieren müssen...

4 Stimmen

In dieser Frage ging es um Hashes für Passwörter. 1 Ausführung von sha512 (selbst wenn es gesalzen ist) wird allgemein als nicht gut genug für den Passwortschutz angesehen. (Außerdem ist der RNG nicht kryptografisch sicher, so dass seine Verwendung für die Passwortgenerierung riskant ist).

4 Stimmen

Sie haben keine Ahnung, was Sie da tun. Lesen Sie die wichtigsten Antworten in diesem Beitrag und Sie werden sehen, warum Ihr Code nicht nur unsicher ist, sondern auch keinen Sinn ergibt.

0 Stimmen

Ok. mein Code ist nicht sicher. also lassen Sie mich wissen, warum Sie in Ihren Algorithmen nur sha256 verwenden??? Ich weiß, dass sha512 der beste ist, warum verwenden Sie ihn nicht?

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