2009-03-12 6 views
36

Ich bin auf der Suche nach einer wiederverwendbaren Funktion, die einen zufälligen Schlüssel mit druckbaren ACSII Zeichen der gewählten Länge (irgendwo von 2 bis 1000 +) generieren wird. Ich denke, druckbare ASCII-Zeichen wären 33-126. Der Schlüssel muss nicht vollständig eindeutig sein, nur einmalig, wenn er genau in der Millisekunde generiert wird (also uniqid() wird nicht funktionieren).Was ist der beste Weg, um einen zufälligen Schlüssel in PHP zu generieren?

Ich denke, eine Kombination von chr() und mt_rand() könnte funktionieren.

Ist dies der richtige Weg oder ist etwas anderes die beste Methode?

Bearbeiten:uniqid() wird auch nicht funktionieren, weil es keinen Längenparameter hat, es ist nur was auch immer PHP Ihnen gibt.

Meine Idee: Das ist, was ich kam mit:

function GenerateKey($length = 16) { 
    $key = ''; 

    for($i = 0; $i < $length; $i ++) { 
     $key .= chr(mt_rand(33, 126)); 
    } 

    return $key; 
} 

Gibt es Probleme mit diesem?

Andere Edit: Die meisten anderen Fragen befassen sich mit der Passwort-Generierung. Ich möchte eine größere Vielfalt an Charakteren und ich interessiere mich nicht für 1 vs l. Ich möchte, dass die maximale Anzahl möglicher Schlüssel möglich ist.

Hinweis: Der generierte Schlüssel muss nicht unbedingt kryptographisch sicher sein.

+0

Zufallszahlengeneratoren im Allgemeinen nicht _guarantee_ Einzigartigkeit, auch wenn "Genau zur selben Millisekunde erzeugt." Um die Eindeutigkeit zu gewährleisten, müssen Sie in der Lage sein, eine Kollision zu erkennen. – danorton

+0

Große Warnung vor der Sicherheit hinzugefügt, sonst müsste ich jede Antwort ablehnen. Seien Sie gewarnt, dass einige der Funktionen in den Antworten binär, andere zurück Hex, andere Base64 etc. etc. –

Antwort

54

Update (12/2015): Für PHP 7.0, Sie random_int() statt mt_rand wie es bietet „kryptografisch sichere Werte“

persönlich verwenden sollte, Ich mag sha1(microtime(true).mt_rand(10000,90000)) verwenden, aber Sie suchen mehr eine anpassbare Ansatz, diese Funktion so versuchen (die eine Änderung an Ihrem Antrag this answer ist):

function rand_char($length) { 
    $random = ''; 
    for ($i = 0; $i < $length; $i++) { 
    $random .= chr(mt_rand(33, 126)); 
    } 
    return $random; 
} 

Dennoch wird dies wahrscheinlich als uniqid deutlich langsamer sein(), md5() oder sHA1().

Bearbeiten: Sieht so aus, als ob Sie zuerst, sorry. : D

Edit 2: ich mit PHP 5 und eAccelerator einen netten kleinen Test auf meinem Debian-Maschine zu tun beschlossen (entschuldigen Sie den langen Code):

function rand_char($length) { 
    $random = ''; 
    for ($i = 0; $i < $length; $i++) { 
    $random .= chr(mt_rand(33, 126)); 
    } 
    return $random; 
} 

function rand_sha1($length) { 
    $max = ceil($length/40); 
    $random = ''; 
    for ($i = 0; $i < $max; $i ++) { 
    $random .= sha1(microtime(true).mt_rand(10000,90000)); 
    } 
    return substr($random, 0, $length); 
} 

function rand_md5($length) { 
    $max = ceil($length/32); 
    $random = ''; 
    for ($i = 0; $i < $max; $i ++) { 
    $random .= md5(microtime(true).mt_rand(10000,90000)); 
    } 
    return substr($random, 0, $length); 
} 

$a = microtime(true); 
for ($x = 0; $x < 1000; $x++) 
    $temp = rand_char(1000); 

echo "Rand:\t".(microtime(true) - $a)."\n"; 

$a = microtime(true); 
for ($x = 0; $x < 1000; $x++) 
    $temp = rand_sha1(1000); 

echo "SHA-1:\t".(microtime(true) - $a)."\n"; 

$a = microtime(true); 
for ($x = 0; $x < 1000; $x++) 
    $temp = rand_md5(1000); 

echo "MD5:\t".(microtime(true) - $a)."\n"; 

Ergebnisse:

Rand: 2.09621596336 
SHA-1: 0.611464977264 
MD5: 0.618473052979 

Also mein Vorschlag, wenn du Geschwindigkeit (aber nicht vollen Zeichensatz) willst, ist MD5, SHA-1, oder Uniqid (was ich noch nicht getestet habe ..)

+1

Beat ya nur um ein paar Sekunden. –

+3

Beat ya nur um ein paar Monate;) – lpfavreau

+0

+1 für die saubere Antwort und Änderung an den ursprünglichen Code, dieser ist besser mit mt_rand() – lpfavreau

0

Ist that question von Interesse für Sie?

Ich bin mir nicht sicher, warum uniqid() funktioniert nicht für Sie und in dem Fall benötigen Sie eine eindeutige Nummer in der gleichen Millisekunde, aber nicht unbedingt anders; Was erzeugst du so schnell, dass du in der gleichen Millisekunde eine Kollision haben könntest? Ich frage mich, wie viel Zeit braucht uniqid() nur, um seine Nummer zu generieren. Wenn Sie möchten, verwenden Sie den Präfix-Parameter der uniqid() Funktion mit ein paar zufälligen Buchstaben und Sie sollten sicher sein.

Wenn es zum Generieren von Datei ist, möchten Sie vielleicht tmpfile() oder tempname() betrachten.

In jedem Fall können Sie je nachdem, was Sie erreichen möchten, einfach eine Schleife ausführen und überprüfen, ob die eindeutige ID bereits vergeben ist (in einem Array mit file_exists usw.) und nur eine weitere generieren .


Auch, wie ich bin nicht sicher, ich verstehe Ihre Frage genau, würde ich Sie auf diese anderen Fragen zeigen, die ziemlich ähnlich klingen, während ich den Unterschied von Ihnen erhalten:

Die erste wird von Interesse sein, wenn Sie eine eindeutige ID zu tun suchen, der für Menschen lesbaren ist. Der zweite könnte nützlich sein, wenn Sie mit Zufallszahlen und md5/sha1 spielen möchten. Obwohl ich wiederum denke, uniqid() könnte schon sein, was Sie suchen.

7

kannst du noch dran halten se uniqid(), mach einfach eine zusätzliche Verarbeitung, um den Wert auf die Anzahl der benötigten Zeichen zu erweitern.

Zum Beispiel zu erweitern es 32 Zeichen, könnten Sie tun

$id = md5(uniqid()); 

es zu 64 Zeichen zu erweitern, fügen Sie einfach den md5 des md5, wie so

$first = md5(uniqid()); 
$id = $first . md5($first); 

Dann trucate wie notwendig, wenn Sie weniger als einige vielfache von 32 brauchen.

Es ist möglich, dass Sie in Kollisionen laufen konnten, aber es ist ziemlich unwahrscheinlich. Wenn Sie paranoid sind, verwenden Sie einfach die gleiche Idee, aber tuckern Sie uniqid() durch eine symmetrische Chiffre wie AES, anstatt es zu hashing.

27

Keine der Antworten hier ist ausreichend, wenn Sie Kryptographie-Stärke Zufälligkeit (gibt es einen entschlossenen Angreifer versucht zu raten, was Ihre zufälligen Schlüssel sind?). Das Verhindern der Zeit ist nicht sicher, ein Angreifer kann seine Suche erheblich beschleunigen, indem er rät, wann der Server den Schlüssel generiert hat, und es ist einfach, alle Millisekunden in einem bestimmten Jahr zu durchsuchen, sogar auf einem handelsüblichen Laptop (es ist 35) Bit Suchraum). Auch der Vorschlag, die Ergebnisse von uniqid() oder einer anderen schwachen Zufallsquelle über eine Hash-Funktion zu "erweitern", ist gefährlich - dies macht die Suche eines Angreifers nicht schwieriger, sobald sie herausfinden, dass Sie dies getan haben.

Wenn Sie wirklich Krypto-Level-Sicherheit benötigen, sollten Sie lesen von/dev/random, der folgende Code sollte in jedem POSIX-kompatiblen System (alles andere als Windows) für Sie arbeiten:

#Generate a random key from /dev/random 
function get_key($bit_length = 128){ 
    $fp = @fopen('/dev/random','rb'); 
    if ($fp !== FALSE) { 
     $key = substr(base64_encode(@fread($fp,($bit_length + 7)/8)), 0, (($bit_length + 5)/6) - 2); 
     @fclose($fp); 
     return $key; 
    } 
    return null; 
} 

Wenn Sie brauche etwas mehr Geschwindigkeit, kannst du stattdessen von 'dev/urandom' lesen.

+4

Ich wollte nur wissen - Ich hatte ein Skript, das extra 50s zum Laden benötigte, und es stellte sich heraus, dass die Verwendung von/dev/random anstelle von/dev/urandom die Ursache war. In meiner lokalen Testumgebung ist dies nie passiert. – whichdan

+4

'/ dev/urandom' sollte der Standard sein, die Verwendung von'/dev/random/'wird den Zufallsentropie-Pool zu früh zerstören (auf Systemen ohne dedizierten Zufallszahlengenerator, der mit'/dev/random' verknüpft ist). Eigentlich wäre es eine gute Möglichkeit für einen Angreifer, eine DoS-Attacke auszuführen, aber ich denke nicht, dass die Funktion überhaupt verfügbar sein sollte, sie ist nur für Anwendungen/Bibliotheken mit ihrem eigenen PRNG nützlich. –

3

Warum openssl_random_pseudo_bytes nicht verwenden http://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php

+0

Diese Antwort wäre effektiver, wenn Sie ein Beispiel zeigen, wie es helfen würde. – ethrbunny

+0

Ich verwende erfolgreich das obige wie folgt $ sessionkey = bin2hex (openssl_random_pseudo_bytes (1024)); Dies erzeugt einen kryptographisch sicheren Zufallsschlüssel ... Dies ist eine Antwort auf .. 'die beste Art, einen zufälligen Schlüssel zu erzeugen' ... Es ist ein sehr guter Weg, wie .. a) es verwendet eine einfache schnelle Funktion ... es ist crypo sicher, es ist offensichtlich zufällig .. und Sie können Schlüssel von beliebiger Länge generieren ... –

0

$ key = md5 (micro() rand().);

Microtime selbst ist nicht sicher, da es nur 1/1000 Chance, erraten werden lässt.

Rand von selbst ist auch nicht sehr sicher, aber Hashing ihre Verkettung sie zusammen ergibt eine ziemlich solide Randomisierung.

+0

"Rand an sich ist auch nicht sehr sicher, aber Hashing ihre Verkettung sie zusammen ergibt eine ziemlich solide Randomisierung." Nee. Sie haben einen vorhersagbaren Wert mit einer Obergrenze von 32 Bit Entropie von 'rand()'. Wenn wir annehmen, dass 'microtime()' 10 Bits Entropie enthält, ergibt das ungefähr 42 Bits. Geburtstagskollisionen nach jeweils 2 Millionen Samples, aber 'rand()' ist vorhersehbar. Bessere Lösung: Verwenden Sie ein CSPRNG zum Generieren von Schlüsseln. –

1

Meine vorherige Antwort nahm einen Hash von uniqid() kombiniert mit einem aus Systemvariablen abgeleiteten Salz, aber das erzeugt keinen zufälligen Schlüssel, nur einer, der sehr wahrscheinlich einzigartig ist. In ähnlicher Weise ist die Ausgabe von rand() oder mt_rand() nicht zufällig genug für kryptografische Zwecke.

einen zufälligen Schlüssel zu generieren, müssen Sie eine gute Zufallsdatenquelle gehen, und die Funktion openssl_random_pseudo_bytes() ist so konzipiert, das zu tun:

$randkey = base64_encode(openssl_random_pseudo_bytes(32)); 

Die base64_encode() ist es in druckbare Zeichen zu machen.

Der Grund, warum die anderen Antworten openssl_random_pseudo_bytes() nicht empfehlen, ist wahrscheinlich, dass es in PHP 5.3 eingeführt wurde, und diese Frage ist fast 6 Jahre alt.

-1

Sie können auch einen zufälligen Schlüssel erzeugen und den Schlüssel in Ihrer DB überprüfen, ob der Schlüssel Exits ist, können Sie eine anderen Schlüssel mit dieser Methode erzeugen können

 function activation($lengt=20){ 
    $modalpage =new Modal;//you can call your modal page and check the key 

    $characters = "1234567890abcdefghijklmnopqrstuvwxyz"; 
    for($i=0;$i<$lengt;$i++) 

    {  

    $key .= $characters{rand(0,35)}; 
    $check= array(
    ":key" => $key, 
    ); 

    $result = $modalpage->findkey($check); 

    if($result==true){ //if the key is exits return the function and generate another key ! 

     return activation($lengt); 

    }else //if the key is not exits return the key 
    return $key; 
    } 


      } 

$mykey=activation(15); 
Verwandte Themen