Ich werde eine Antwort posten, da einige der vorhandenen Antworten nahe beieinander liegen, aber eine der folgenden haben:
- Ein kleinerer Zeichenraum als gewünscht, damit entweder das Brute-Forcing einfacher ist oder das Kennwort für dieselbe Entropie länger sein muss
- ein RNG , das nicht als kryptografisch sicher gilt
- eine Voraussetzung für eine Bibliothek von Drittanbietern, und ich dachte, es könnte interessant sein, zu zeigen, was nötig ist, um es selbst zu tun
Diese Antwort umgeht das count/strlen
Problem, da die Sicherheit des generierten Passworts, zumindest IMHO, über Ihre Anreise hinausgeht. Ich gehe auch von PHP> 5.3.0 aus.
Lassen Sie uns das Problem in die Bestandteile aufteilen, die sind:
- Verwenden Sie eine sichere Zufallsquelle, um zufällige Daten zu erhalten
- Verwenden Sie diese Daten und stellen Sie sie als druckbare Zeichenfolge dar
Für den ersten Teil bietet PHP> 5.3.0 die Funktion openssl_random_pseudo_bytes
. Beachten Sie, dass die meisten Systeme zwar einen kryptografisch starken Algorithmus verwenden, Sie dies jedoch überprüfen müssen, damit ein Wrapper verwendet wird:
/**
* @param int $length
*/
function strong_random_bytes($length)
{
$strong = false; // Flag for whether a strong algorithm was used
$bytes = openssl_random_pseudo_bytes($length, $strong);
if ( ! $strong)
{
// System did not use a cryptographically strong algorithm
throw new Exception('Strong algorithm not available for PRNG.');
}
return $bytes;
}
Für den zweiten Teil verwenden wir, base64_encode
da es eine Byte-Zeichenfolge benötigt und eine Reihe von Zeichen erzeugt, deren Alphabet dem in der ursprünglichen Frage angegebenen sehr nahe kommt. Wenn wir nicht mit nichts ausmachte +
, /
und =
Zeichen in der letzten Zeichenfolge erscheinen und wir ein Ergebnis zumindest wollen $n
Zeichen lang, könnten wir einfach nutzen:
base64_encode(strong_random_bytes(intval(ceil($n * 3 / 4))));
Der 3/4
Faktor beruht auf der Tatsache, dass die Base64-Codierung zu einer Zeichenfolge führt, deren Länge mindestens ein Drittel größer ist als die Byte-Zeichenfolge. Das Ergebnis ist genau, $n
wenn es ein Vielfaches von 4 und ansonsten bis zu 3 Zeichen länger ist. Da die zusätzlichen Zeichen überwiegend das Auffüllzeichen sind =
, können wir es auf die gewünschte Länge kürzen , wenn wir aus irgendeinem Grund die Einschränkung hatten, dass das Kennwort eine exakte Länge hat. Dies liegt insbesondere daran, dass für ein bestimmtes $n
Kennwort alle Kennwörter mit der gleichen Anzahl enden würden, sodass ein Angreifer, der Zugriff auf ein Ergebniskennwort hatte, bis zu 2 Zeichen weniger erraten müsste.
Wenn wir für zusätzliche Gutschriften die genaue Spezifikation wie in der Frage des OP erfüllen wollten, müssten wir ein bisschen mehr Arbeit leisten. Ich werde hier auf den Ansatz der Basiskonvertierung verzichten und mich für einen schnellen und schmutzigen entscheiden. Beide müssen aufgrund des 62-Eintrags langen Alphabets ohnehin mehr Zufälligkeit erzeugen, als im Ergebnis verwendet wird.
Für die zusätzlichen Zeichen im Ergebnis können wir sie einfach aus der resultierenden Zeichenfolge verwerfen. Wenn wir mit 8 Bytes in unserer Byte-Zeichenfolge beginnen, sind bis zu 25% der base64-Zeichen diese "unerwünschten" Zeichen, sodass das einfache Verwerfen dieser Zeichen zu einer Zeichenfolge führt, die nicht kürzer als das gewünschte OP ist. Dann können wir es einfach abschneiden, um die genaue Länge zu erhalten:
$dirty_pass = base64_encode(strong_random_bytes(8)));
$pass = substr(str_replace(['/', '+', '='], ['', '', ''], $dirty_pass, 0, 8);
Wenn Sie längere Kennwörter generieren, macht das Auffüllzeichen =
einen immer kleineren Anteil des Zwischenergebnisses aus, sodass Sie einen schlankeren Ansatz implementieren können, wenn das Entleeren des für das PRNG verwendeten Entropiepools ein Problem darstellt.