Hallo,
also:
1. chr(rand(1, 2000)); ist totaler Unsinn, es gibt nur 256 Ascii Werte, weswegen das keinen Sinn macht, zufallszahlen bis 2000 zu verwenden.
und, vieleicht täusche ich mich, aber ist sha512 im gegensatz zu sha1 nicht noch ungeknackt? müsste der "cracker" nicht zuerst sha512 oder whirlpool (je nach wahl) auflösen?
Nein, ein Angreifer würde nicht sha512 o.ä. auflösen, sondern ______
das_____ (!!!) entscheidene ist dein Entropy-Pool. Hast du einen großen entropy pool, d.h., viele zufällige, schwer/nicht erratbare Zufallsquellen, ist es nahezu ein Kinderspiel daraus 1 Zufallszahl zu erzeugen [*].
Man kann auf den entropy pool sogut wie jede Funktion verwenden, um eine gute Zufallszahl zu erhalten, solange die gesamte Eingabe gleichmäßig gewichtet wird (also nicht das die ersten 5 Bytes zu 99,9% das Ergebnis bestimmen). Selbst CRC32 o.ä. würde bei einem guten entropy pool keine Probleme erstellen.
Hat man stattdessen einen miserablen (=kleinen) entropy pool, wie z.B. es bei OpenSSL unter Debian war, nur 16 Bit, ist es absolut unmöglich daraus eine gute Zufallszahl zu gewinnen, egal welche weiteren Algorithmen und Tricks du anwendest.
Mal davon abgesehen das deine Implementierung haufenweise Fehler hat, ist dein entropy pool viel zu klein, um die Zufallszahl halbwegs ernst zu nehmen, da du dich ausschließlich auf die Seed von rand() verlässt, die nur 32 Bit beträgt.
Egal was du machst, könntest einen nachweisbar 100% sicheren Hash-Algorithmus verwenden (der nicht existiert), deine Zufallszahlen sind und bleiben miserabel. Über diese 32 Bit wirst du nicht herauskommen, sondern im Gegenteil, mit jeder weiteren Finesse reduzierst du potenziell die Anzahl an zufälligen Kombinationen.
mir gefällt die methode mit den ascii-zeichen eigentlich recht gut.
Mir eigentlich gar nicht.
oder täusche ich mich, wenn ich denke, das eine grössere vielfalt von zeichen sicherer ist?
Ja. Nur weil es scheinbar mehr Zeichen gibt, erhöht dies nicht die Anzahl an Kombinationen.
ASCII Zeichen ist nichts anderes als Representanten im 256er System.
Sagen wir du hast eine 32 Bit Zahl, ob du diese nun Binär, Dezimal oder Hexadezimal darstellen lässt, ändert dies nichts an der Anzahl der möglichen Kombinationen, was soweit hoffentlich klar ist.
Aber, wie erwähnt, sind ASCII (o.ä.) Zeichen nur Representanten im 256er System, ähnlich wie z.B. die 9 im Dez. System für etwas steht oder das A im Hexadezimalsystem.
Konvertierst du nun deine 32 Bit Zahl ins ASCII System, hast du im best case immer noch soviele Kombinationen, als hättest du die 32 Bit Zahl direkt verwendet.
Aber!!: Bei (der sinnlosen) Konvertierung können sehr schnell Informationen verloren gehen, womit sich die Anzahl der möglichen Kombinationen drastisch reduzieren kann.
Deswegen bringt solch eine ASCII Representation null Sicherheitsgewinn, sondern im Gegenteil, reduziert erheblich die Sicherheit deines Systems und es ist jedem unbedingt davon abzuraten, dieses zu verwenden.
Sollte eigentlich auch klar sein, dein Computer kann nur mit Binärzahlen etwas anfangen, und A ist im Speicher nichts anders als die Zahl 65 (Dez) oder 01000001 Binär. Weswegen sollte man also eine Zufallszahl, z.B. 99, in das ASCII Zeichen 'c' umwandeln, wenn 'c' im Speicher als 01100011 = 99 hinterlegt wird? Irgendwie schwachsinnig, oder?
Aber wie erwähnt, bei jeder dieser Konvertierung kann verlust entstehen, d.h. du könntest Zufallszahlen zwischen 0-100 erzeugen, aber evt. gibts nach der Konvertierung nur noch 80 Zahlen/Zeichen.
Ansonsten wie erwähnt: Das wichtigste ist nicht, welche tollen Hash-Algorithmus man bekommt, sondern wie groß der entropy pool ist. Bei deiner jetzigen Implementierung ist dieser 32 Bit groß (und mehr wird man ausschließlich rand() auch _nie_ erreichen), wobei deine sehr merkwürdigen Schleifen und konstrukte diesen entropy pool erheblich Reduzieren können (und wahrscheinlich auch tun).
Das primäre Ziel ist also, möglich viele Zufallsquellen zu bekommen, ich habe dir bereits einen Ansatz geliefert. Diese Zufallsquellen kann man dann z.B. per sha1() oder md5() zusammenfassen, um eine kürzer zufällige Zahl zu erhalten.
Ob sha1/md5 nun gebrochen ist oder nicht, was so nicht stimmt, ist egal, solange deine Funktion 'full diffusion' besitzt, d.h., alle Ausgangsbits beruhen auf allen Eingangsbits und nur 1 Bit-Änderung am Eingang ändert im Schnitt 50% der Ausgangsbits, und genau dieses bieten sha1/md5.
Ansonsten mehr zu Thema schau mal hier:
Cryptanalytic Attacks on Pseudorandom Number Generators
[*]: Wenn man nur 1 Zufallszahl aus einem entropy pool erzeugen möchte, ist dies recht leicht.
Oft möchte man aber mehrere Zufallszahlen hintereinander generieren, und da stellt sich dann die Frage wie man dieses macht.
Was man gut machen kann, ist per md5/sha1 aus allen Zufallsquellen einen zufälligen Wert erstellen und diesen dann als Seed für einen kryptographisch sicheren Pseudozufallsgenerator verwenden, sofern dieser z.B. nur eine 128 Bit seed erlaubt.
Ansonsten kann man die Zufallsquellen, sofern nicht zu groß, direkt als Seed verwenden.
In PHP ist das vorhaben deutlich schwieriger, da man in PHP selbst schlecht einen globalen Zufallsgenerator implementieren kann und man oft pro Script-Aufruf darauf angewiesen, den Zufallsgenerator neu zu initialisieren.
Wenn man nur 1 Zufallszahl braucht, kann man die obige Methode bedenkenlos verwenden. Benötigt man mehrere Werte, wäre eine Implementierung mit Gedächtnis nicht schlecht.
Könnte in etwa aussehen (ungetestet):
PHP:
<?php
$initialisieren = true;
$int_value = "";
$alt ="";
function randValue() {
global $initialisieren, $alt, $int_value;
$string = $alt.microtime();
$string .= rand().mt_rand().rand().mt_rand().rand().mt_rand();
$string .= memory_get_usage().memory_ get_ peak_ usage();
if($initialisieren) {
$string .= implode("", $_GLOBALS); //Hier evt. auf $_SERVER + $_GET + $_COOKIE umsteigen, wenn per $_POST viel übertragen wird
$string .= getmygid().getmyinode().getmypid().getmyuid().implode("",@getrusage());
//Evt. noch auf mcrypt_create_iv() zurückgreifen
//Weitere 'zufällige' Werte die einem einfallen
$int_value = sha1($string);
$initialisieren = false;
}
$alt = sha1($string.$int_value);
return $alt;
}
?>