ChaosRNG: PHP-Pseudozufallsgenerator mit 12 Timern
Die ChaosRNG-Klasse nutzt 12 miteinander verknüpfte Timer, um Bytes mit einer Entropie von bis zu 7,1–8 Bits pro Byte zu erzeugen. Jeder Timer trägt zur Nichtlinearität bei – von Basiszeit und Nanosekunden bis hin zu Pausen und Nullbyte-Einfügungen. Dieser experimentelle Ansatz eignet sich für Aufgaben, die keine zertifizierten kryptografischen Primitiven benötigen.
Der Konstruktor initialisiert den Zustand durch XOR von Mikrosekunden (T1), Nanosekunden (T2), PID und Speicherverbrauch (T7). Der Verzerrungsfaktor startet bei 1,001, der Schalter ist standardmäßig aktiviert.
Timer-Logik
Die Timer bilden eine Verarbeitungspipeline:
- T1: Mikrosekunden seit 1970.
- T2: Nanosekunden seit Systemstart.
- T3: Aktualisiert 64-Bit-Zustand durch Addition oder Subtraktion des niedrigsten Bytes des Totals.
- T4: Moduliert die Zeit durch Multiplikation/Division mit Faktor k, der jeden Zyklus aktualisiert wird.
- T5: Bestimmt Scheiben (1000–10000).
- T6: Wählt Scheibe für Zeitgewichtung aus.
- T7: Cache- und Interrupt-Jitter über PID und Speicher.
- T8: Schalter – überspringt echte Bytes, wenn aus.
- T9: Steuert T8 basierend auf letztem Byte (<5 ein, >5 aus).
- T10: Versteckter Startpunkt im Konstruktor.
- T11: Fügt 0x00 ein, wenn ($state & 10) === 0.
- T12: Pausiert 1–100 Zyklen mit Zustandsaktualisierungen während der Wartezeit.
/**
* ChaosRNG - Zufallsbyte-Generator mit 12 Timern
*
* 12 Timer:
* T1 – Standarduhr (microtime)
* T2 – Hochauflösende Uhr (hrtime)
* T3 – Speicher (Zustand $state)
* T4 – Verzerrer (multipliziert/dividiert Zeit)
* T5 – Scheider (1000-10000 Scheiben)
* T6 – Auswähler (Scheiben-Selektor)
* T7 – Versteckte Rauschquelle (Jitter, Interrupts)
* T8 – Schalter (Ein/Aus-Ausgabe)
* T9 – Beobachter (steuert Schalter)
* T10 – Startpunkt (Init-Moment)
* T11 – Nullbyte (Nullbyte-Einfügung)
* T12 – Pauser (1-100 Zyklus-Pausen)
*/
class ChaosRNG {
// Klassen-Eigenschaften
private $state; // T3: 64-Bit-Zustand
private $k; // T4: Verzerrungsfaktor
private $enabled; // T8: Schalter (Ein/Aus)
private $lastByte; // T9: letztes Ausgabebyte
private $dot; // T11: Nullbyte-Flag
private $pauseLen; // T12: Pausenlänge
private $pauseRem; // T12: Pauserest
/**
* Konstruktor — T10 (Startpunkt)
* Mischt alle nicht wiederholbaren Quellen
*/
public function __construct() {
// XOR aller Quellen → einzigartiger Initialzustand
$this->state = (int)(microtime(true) * 1000000) // T1: Mikrosekunden
^ hrtime(true) // T2: Nanosekunden
^ getmypid() // T7: Prozess-PID
^ memory_get_usage(); // T7: Speicherverbrauch
$this->k = 1.001; // T4: Initialfaktor
$this->enabled = true; // T8: Schalter ein
$this->lastByte = 0; // T9: kein letztes Byte
$this->dot = false; // T11: kein Nullbyte eingefügt
$this->pauseLen = 0; // T12: keine Pause
$this->pauseRem = 0; // T12: Rest 0
}
/**
* T1: Standarduhr
* Gibt Mikrosekunden seit 1970 zurück
*/
private function t1() {
return (int)(microtime(true) * 1000000);
}
/**
* T2: Hochauflösende Uhr
* Gibt Nanosekunden seit Start zurück
*/
private function t2() {
return hrtime(true);
}
/**
* Interner Byte-Generator (T3-T7)
* Aktualisiert Zustand und gibt ein Byte zurück
*/
private function nextByteInternal() {
// T5: Scheibenzahl 1000 bis 10000
$K = 1000 + ($this->state % 9001);
// T6: wähle spezifische Scheibe
$slot = (($this->state >> 8) % $K);
// T1 und T2: aktuelle Zeit holen
$t1 = $this->t1();
$t2 = $this->t2();
// T4: Verzerrer (dehnen oder komprimieren)
if ($this->state & 1) {
$t1 = $t1 * $this->k; // T1 dehnen
} else {
$t2 = $t2 / $this->k; // T2 komprimieren
}
// Summe mit gewählter Scheibe
$total = (int)($t1 * ($slot + 1) / $K)
+ (int)($t2 * ($slot + 1) / $K);
// T3: Zustand aktualisieren (addieren oder subtrahieren)
if ($total & 1) {
$this->state += ($total & 0xFF);
} else {
$this->state -= ($total & 0xFF);
}
// Verzerrungsfaktor aktualisieren
$this->k = 1.0 + (($this->state & 0xFF) / 10000.0);
// Niedrigstes Zustandsbyte zurückgeben
return $this->state & 0xFF;
}
/**
* Öffentliche Methode: N Zufallsbytes holen
* Berücksichtigt alle 12 Timer
*/
public function getBytes($n) {
$out = [];
for ($i = 0; $i < $n; $i++) {
// T12: Pause (Pauser)
while ($this->pauseRem > 0) {
$this->pauseRem--;
$this->nextByteInternal(); // Zustand ändert sich
}
// Wenn Pause endet — neue erzeugen
if ($this->pauseRem === 0 && $this->pauseLen === 0) {
$this->pauseLen = 1 + ($this->state % 100); // 1-100 Zyklen
$this->pauseRem = $this->pauseLen;
}
// T11: Nullbyte (Nullbyte-Einfügung)
if (($this->state & 10) === 0 && !$this->dot) {
$this->dot = true;
$this->nextByteInternal();
$out[] = 0x00; // Nullbyte
continue;
}
$this->dot = false;
// T9: Schalter-Beobachter
if ($this->lastByte < 5) {
$this->enabled = true; // einschalten
} elseif ($this->lastByte > 5) {
$this->enabled = false; // ausschalten
}
// bei ==5 keine Änderung
// Byte erzeugen
$byte = $this->nextByteInternal();
// T8: Schalter
if (!$this->enabled) {
// Wenn aus — Dummy-Byte ausgeben
$out[] = $this->nextByteInternal() & 0xFF;
continue;
}
// Letztes Ausgabebyte speichern
$this->lastByte = $byte;
// Pause nach echtem Byte zurücksetzen
if ($this->pauseLen > 0) {
$this->pauseLen = 0;
$this->pauseRem = 0;
}
$out[] = $byte;
}
return $out;
}
}
Shannon-Entropie-Berechnung
Die statische Methode entropy() berechnet die Shannon-Entropie mit der Formel -Σ p * log2(p) für Bytehäufigkeiten. Tests mit 64 KB Daten ergeben im Durchschnitt 7,12 Bits.
public static function entropy($bytes) {
// Bytehäufigkeiten zählen
$freq = array_fill(0, 256, 0);
foreach ($bytes as $b) {
$freq[$b]++;
}
// Shannon-Formel: -Σ p * log2(p)
$e = 0;
$total = count($bytes);
foreach ($freq as $c) {
if ($c > 0) {
$p = $c / $total;
$e -= $p * log($p, 2);
}
}
return $e;
}
// Test
$rng = new ChaosRNG();
$data = $rng->getBytes(65536);
$entropy = ChaosRNG::entropy($data);
echo "Entropie: " . round($entropy, 4) . " / 8 Bits\n";
Nichtlinearität und Robustheit
Zur Wiederherstellung des Zustands muss man k, Scheibenzahl, Pausen und Schalterposition kennen. Der 64-Bit-Zustand erschwert Angriffe ohne Serverzugriff. Entropie >6,5 Bits sogar auf VMs macht die Sequenz statistisch nahezu zufällig.
Anwendungsfälle: Token- und Passwortgenerierung (16 Zeichen ~113 Bits Entropie). Nicht für Kryptografie – nur Experimente.
Wichtige Erkenntnisse
- 12 Timer erzeugen eine nichtlineare Pipeline mit Pausen und Übersprüngen zur Verhinderung von Analysen.
- Shannon-Entropie 7,1+ Bits pro Byte, getestet auf 64 KB.
- T12 (Pausen) und T11 (Nullbytes) brechen zeitliche und sequenzielle Vorhersagbarkeit.
- 64-Bit-Zustand balanciert Robustheit und Geschwindigkeit.
- Nicht für Produktions-Krypto: experimenteller PRNG.
— Editorial Team
Noch keine Kommentare.