Retour à l'accueil

PRNG sur 12 timers PHP : entropie 7.1 bits

La classe ChaosRNG implémente PRNG sur 12 timers pour générer des bytes avec entropie 7.1+ bits. Les timers introduisent la non-linéarité via pauses, skips et modulation. Convient pour expériences avec tokens.

PHP PRNG : 12 timers pour entropie 7+ bits
Advertisement 728x90

# ChaosRNG : Générateur PHP de bytes pseudo-aléatoires avec 12 timers

La classe ChaosRNG exploite 12 timers interconnectés pour générer des bytes avec une entropie allant jusqu'à 7,1–8 bits par byte. Chaque timer introduit de la non-linéarité — du temps de base et des nanosecondes aux pauses et insertions de bytes nuls. Cette approche expérimentale convient aux tâches ne nécessitant pas de primitives cryptographiques certifiées.

Le constructeur initialise l'état via un XOR de microsecondes (T1), nanosecondes (T2), PID et utilisation mémoire (T7). Le facteur de distorsion démarre à 1,001, avec l'interrupteur activé par défaut.

Logique des timers

Les timers forment un pipeline de traitement :

Google AdInline article slot
  • T1 : Microsecondes depuis 1970.
  • T2 : Nanosecondes depuis le démarrage du système.
  • T3 : Met à jour l'état 64 bits en ajoutant ou soustrayant le byte le plus bas du total.
  • T4 : Module le temps en multipliant/divisant par le facteur k, mis à jour à chaque cycle.
  • T5 : Détermine les tranches (1000–10000).
  • T6 : Sélectionne la tranche pour le pondération temporelle.
  • T7 : Cache et jitter d'interruptions via PID et mémoire.
  • T8 : Interrupteur — saute les vrais bytes quand éteint.
  • T9 : Contrôle T8 en fonction du dernier byte (<5 allumé, >5 éteint).
  • T10 : Point de départ caché dans le constructeur.
  • T11 : Insère 0x00 quand ($state & 10) === 0.
  • T12 : Pauses de 1–100 cycles avec mises à jour d'état pendant l'attente.
/**
 * ChaosRNG - générateur de bytes aléatoires avec 12 timers
 * 
 * 12 timers :
 * T1  – horloge standard (microtime)
 * T2  – horloge haute résolution (hrtime)
 * T3  – mémoire (état $state)
 * T4  – distorsion (multiplie/divise le temps)
 * T5  – trancheur (1000-10000 tranches)
 * T6  – sélecteur (choix de tranche)
 * T7  – bruit caché (jitter, interruptions)
 * T8  – interrupteur (sortie on/off)
 * T9  – surveillant (contrôle l'interrupteur)
 * T10 – point de départ (moment d'init)
 * T11 – insertion (byte nul)
 * T12 – silencieux (pauses 1-100 cycles)
 */

class ChaosRNG {
    // Propriétés de la classe
    private $state;      // T3: état 64 bits
    private $k;          // T4: facteur de distorsion
    private $enabled;    // T8: interrupteur (on/off)
    private $lastByte;   // T9: dernier byte de sortie
    private $dot;        // T11: drapeau point
    private $pauseLen;   // T12: longueur de pause
    private $pauseRem;   // T12: reste de pause
    
    /**
     * Constructeur — T10 (point de départ)
     * Mélange toutes les sources non reproductibles
     */
    public function __construct() {
        // XOR de toutes les sources → état initial unique
        $this->state = (int)(microtime(true) * 1000000)  // T1: microsecondes
                     ^ hrtime(true)                       // T2: nanosecondes
                     ^ getmypid()                         // T7: PID du processus
                     ^ memory_get_usage();                // T7: utilisation mémoire
        
        $this->k = 1.001;           // T4: facteur initial
        $this->enabled = true;      // T8: interrupteur allumé
        $this->lastByte = 0;        // T9: pas de dernier byte
        $this->dot = false;         // T11: pas de point inséré
        $this->pauseLen = 0;        // T12: pas de pause
        $this->pauseRem = 0;        // T12: reste 0
    }
    
    /**
     * T1: horloge standard
     * Retourne les microsecondes depuis 1970
     */
    private function t1() {
        return (int)(microtime(true) * 1000000);
    }
    
    /**
     * T2: horloge haute résolution
     * Retourne les nanosecondes depuis le démarrage
     */
    private function t2() {
        return hrtime(true);
    }
    
    /**
     * Générateur interne de byte (T3-T7)
     * Met à jour l'état et retourne un byte
     */
    private function nextByteInternal() {
        // T5: nombre de tranches 1000 à 10000
        $K = 1000 + ($this->state % 9001);
        
        // T6: sélectionne une tranche spécifique
        $slot = (($this->state >> 8) % $K);
        
        // T1 et T2: temps actuel
        $t1 = $this->t1();
        $t2 = $this->t2();
        
        // T4: distorsion (étire ou compresse le temps)
        if ($this->state & 1) {
            $t1 = $t1 * $this->k;   // étire T1
        } else {
            $t2 = $t2 / $this->k;   // compresse T2
        }
        
        // Somme avec la tranche sélectionnée
        $total = (int)($t1 * ($slot + 1) / $K)
               + (int)($t2 * ($slot + 1) / $K);
        
        // T3: mise à jour de l'état (ajout ou soustraction)
        if ($total & 1) {
            $this->state += ($total & 0xFF);
        } else {
            $this->state -= ($total & 0xFF);
        }
        
        // Mise à jour du facteur de distorsion
        $this->k = 1.0 + (($this->state & 0xFF) / 10000.0);
        
        // Retourne le byte le plus bas de l'état
        return $this->state & 0xFF;
    }
    
    /**
     * Méthode publique: obtenir N bytes aléatoires
     * Prend en compte les 12 timers
     */
    public function getBytes($n) {
        $out = [];
        
        for ($i = 0; $i < $n; $i++) {
            // T12: pause (silencieux)
            while ($this->pauseRem > 0) {
                $this->pauseRem--;
                $this->nextByteInternal(); // état change
            }
            
            // Si pause terminée — génère une nouvelle
            if ($this->pauseRem === 0 && $this->pauseLen === 0) {
                $this->pauseLen = 1 + ($this->state % 100); // 1-100 cycles
                $this->pauseRem = $this->pauseLen;
            }
            
            // T11: point (insertion byte nul)
            if (($this->state & 10) === 0 && !$this->dot) {
                $this->dot = true;
                $this->nextByteInternal();
                $out[] = 0x00; // point = byte nul
                continue;
            }
            $this->dot = false;
            
            // T9: surveillant d'interrupteur
            if ($this->lastByte < 5) {
                $this->enabled = true;   // allume
            } elseif ($this->lastByte > 5) {
                $this->enabled = false;  // éteint
            }
            // si ==5, pas de changement
            
            // Génère le byte
            $byte = $this->nextByteInternal();
            
            // T8: interrupteur
            if (!$this->enabled) {
                // Si éteint — sortie byte factice
                $out[] = $this->nextByteInternal() & 0xFF;
                continue;
            }
            
            // Sauvegarde le dernier byte de sortie
            $this->lastByte = $byte;
            
            // Réinitialise la pause après byte réel
            if ($this->pauseLen > 0) {
                $this->pauseLen = 0;
                $this->pauseRem = 0;
            }
            
            $out[] = $byte;
        }
        
        return $out;
    }
}

Calcul de l'entropie de Shannon

La méthode statique entropy() calcule l'entropie de Shannon via -Σ p * log2(p) pour les fréquences des bytes. Des tests sur 64 Ko de données montrent une moyenne de 7,12 bits.

public static function entropy($bytes) {
    // Compte les fréquences des bytes
    $freq = array_fill(0, 256, 0);
    foreach ($bytes as $b) {
        $freq[$b]++;
    }
    
    // Formule de Shannon: -Σ 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";

Non-linéarité et résilience

Récupérer l'état nécessite de connaître k, le nombre de tranches, les pauses et la position de l'interrupteur. L'état 64 bits complique les attaques sans accès au serveur. Une entropie >6,5 bits même sur VM rend la séquence statistiquement proche du hasard.

Cas d'usage : génération de tokens et mots de passe (16 caractères ~113 bits d'entropie). Pas pour la cryptographie — expérimental uniquement.

Google AdInline article slot

Points clés

  • 12 timers créent un pipeline non linéaire avec pauses et sauts pour contrer l'analyse.
  • Entropie de Shannon 7,1+ bits par byte, testée sur 64 Ko.
  • T12 (pauses) et T11 (zéros) brisent la prévisibilité temporelle et séquentielle.
  • État 64 bits équilibre résilience et vitesse.
  • Pas pour crypto en production : PRNG expérimental.

— Editorial Team

Advertisement 728x90

Lire ensuite