Volver al inicio

PRNG en 12 temporizadores PHP: entropía 7.1 bits

La clase ChaosRNG implementa PRNG en 12 temporizadores para generar bytes con entropía de 7.1+ bits. Los temporizadores introducen no linealidad mediante pausas, saltos y modulación. Adecuada para experimentos con tokens.

PHP PRNG: 12 temporizadores para entropía de 7+ bits
Advertisement 728x90

# ChaosRNG: Generador de bytes pseudoaleatorios en PHP con 12 temporizadores

La clase ChaosRNG aprovecha 12 temporizadores interconectados para generar bytes con entropía de hasta 7,1–8 bits por byte. Cada temporizador añade no linealidad: desde tiempo base y nanosegundos hasta pausas e inserciones de bytes cero. Este enfoque experimental es ideal para tareas que no requieren primitivas criptográficas certificadas.

El constructor inicializa el estado mediante XOR de microsegundos (T1), nanosegundos (T2), PID y uso de memoria (T7). El factor de distorsión arranca en 1,001, con el interruptor activado por defecto.

Lógica de temporizadores

Los temporizadores forman una tubería de procesamiento:

Google AdInline article slot
  • T1: Microsegundos desde 1970.
  • T2: Nanosegundos desde el arranque del sistema.
  • T3: Actualiza el estado de 64 bits sumando o restando el byte más bajo del total.
  • T4: Modula el tiempo multiplicando/dividiendo por el factor k, actualizado en cada ciclo.
  • T5: Determina rebanadas (1000–10000).
  • T6: Selecciona rebanada para ponderación temporal.
  • T7: Ruido oculto mediante PID y memoria (caché e interrupciones).
  • T8: Interruptor: omite bytes reales cuando está apagado.
  • T9: Controla T8 según el último byte (<5 encendido, >5 apagado).
  • T10: Punto de inicio oculto en el constructor.
  • T11: Inserta 0x00 cuando ($state & 10) === 0.
  • T12: Pausa de 1–100 ciclos con actualizaciones de estado durante la espera.
/**
 * ChaosRNG - generador de bytes aleatorios con 12 temporizadores
 * 
 * 12 temporizadores:
 * T1  – reloj estándar (microtime)
 * T2  – reloj de alta resolución (hrtime)
 * T3  – memoria (estado $state)
 * T4  – distorsionador (multiplica/divide tiempo)
 * T5  – rebanador (1000-10000 rebanadas)
 * T6  – selector (elige rebanada)
 * T7  – ruido oculto (jitter, interrupciones)
 * T8  – interruptor (salida on/off)
 * T9  – vigilante (controla interruptor)
 * T10 – punto de inicio (momento init)
 * T11 – inserción cero (byte cero)
 * T12 – silenciador (pausas 1-100 ciclos)
 */

class ChaosRNG {
    // Propiedades de la clase
    private $state;      // T3: estado de 64 bits
    private $k;          // T4: factor de distorsión
    private $enabled;    // T8: interruptor (on/off)
    private $lastByte;   // T9: último byte de salida
    private $dot;        // T11: bandera de punto
    private $pauseLen;   // T12: longitud de pausa
    private $pauseRem;   // T12: resto de pausa
    
    /**
     * Constructor — T10 (punto de inicio)
     * Mezcla todas las fuentes irrepetibles
     */
    public function __construct() {
        // XOR de todas las fuentes → estado inicial único
        $this->state = (int)(microtime(true) * 1000000)  // T1: microsegundos
                     ^ hrtime(true)                       // T2: nanosegundos
                     ^ getmypid()                         // T7: PID del proceso
                     ^ memory_get_usage();                // T7: uso de memoria
        
        $this->k = 1.001;           // T4: factor inicial
        $this->enabled = true;      // T8: interruptor encendido
        $this->lastByte = 0;        // T9: sin último byte
        $this->dot = false;         // T11: sin punto insertado
        $this->pauseLen = 0;        // T12: sin pausa
        $this->pauseRem = 0;        // T12: resto 0
    }
    
    /**
     * T1: reloj estándar
     * Devuelve microsegundos desde 1970
     */
    private function t1() {
        return (int)(microtime(true) * 1000000);
    }
    
    /**
     * T2: reloj de alta resolución
     * Devuelve nanosegundos desde arranque
     */
    private function t2() {
        return hrtime(true);
    }
    
    /**
     * Generador interno de bytes (T3-T7)
     * Actualiza estado y devuelve un byte
     */
    private function nextByteInternal() {
        // T5: número de rebanadas 1000 a 10000
        $K = 1000 + ($this->state % 9001);
        
        // T6: selecciona rebanada específica
        $slot = (($this->state >> 8) % $K);
        
        // T1 y T2: obtener tiempo actual
        $t1 = $this->t1();
        $t2 = $this->t2();
        
        // T4: distorsionador (estira o comprime tiempo)
        if ($this->state & 1) {
            $t1 = $t1 * $this->k;   // estira T1
        } else {
            $t2 = $t2 / $this->k;   // comprime T2
        }
        
        // Suma con rebanada seleccionada
        $total = (int)($t1 * ($slot + 1) / $K)
               + (int)($t2 * ($slot + 1) / $K);
        
        // T3: actualizar estado (sumar o restar)
        if ($total & 1) {
            $this->state += ($total & 0xFF);
        } else {
            $this->state -= ($total & 0xFF);
        }
        
        // Actualizar factor de distorsión
        $this->k = 1.0 + (($this->state & 0xFF) / 10000.0);
        
        // Devolver byte más bajo del estado
        return $this->state & 0xFF;
    }
    
    /**
     * Método público: obtener N bytes aleatorios
     * Considera los 12 temporizadores
     */
    public function getBytes($n) {
        $out = [];
        
        for ($i = 0; $i < $n; $i++) {
            // T12: pausa (silenciador)
            while ($this->pauseRem > 0) {
                $this->pauseRem--;
                $this->nextByteInternal(); // cambia el estado
            }
            
            // Si terminó la pausa — generar nueva
            if ($this->pauseRem === 0 && $this->pauseLen === 0) {
                $this->pauseLen = 1 + ($this->state % 100); // 1-100 ciclos
                $this->pauseRem = $this->pauseLen;
            }
            
            // T11: punto (inserción de byte cero)
            if (($this->state & 10) === 0 && !$this->dot) {
                $this->dot = true;
                $this->nextByteInternal();
                $out[] = 0x00; // punto = byte cero
                continue;
            }
            $this->dot = false;
            
            // T9: vigilante del interruptor
            if ($this->lastByte < 5) {
                $this->enabled = true;   // encender
            } elseif ($this->lastByte > 5) {
                $this->enabled = false;  // apagar
            }
            // si ==5, sin cambio
            
            // Generar byte
            $byte = $this->nextByteInternal();
            
            // T8: interruptor
            if (!$this->enabled) {
                // Si apagado — salida byte falso
                $out[] = $this->nextByteInternal() & 0xFF;
                continue;
            }
            
            // Guardar último byte de salida
            $this->lastByte = $byte;
            
            // Reiniciar pausa tras byte real
            if ($this->pauseLen > 0) {
                $this->pauseLen = 0;
                $this->pauseRem = 0;
            }
            
            $out[] = $byte;
        }
        
        return $out;
    }
}

Cálculo de entropía de Shannon

El método estático entropy() calcula la entropía de Shannon usando *-Σ p log2(p) para las frecuencias de bytes. Pruebas con 64 KB de datos muestran un promedio de 7,12 bits**.

public static function entropy($bytes) {
    // Contar frecuencias de bytes
    $freq = array_fill(0, 256, 0);
    foreach ($bytes as $b) {
        $freq[$b]++;
    }
    
    // Fórmula 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;
}

// Prueba
$rng = new ChaosRNG();
$data = $rng->getBytes(65536);
$entropy = ChaosRNG::entropy($data);
echo "Entropía: " . round($entropy, 4) . " / 8 bits\n";

No linealidad y resistencia

Recuperar el estado requiere conocer k, número de rebanadas, pausas y posición del interruptor. El estado de 64 bits dificulta ataques sin acceso al servidor. Entropía >6,5 bits incluso en máquinas virtuales hace que la secuencia sea estadísticamente casi aleatoria.

Casos de uso: generación de tokens y contraseñas (16 caracteres ~113 bits de entropía). No para criptografía — solo experimentos.

Google AdInline article slot

Lecciones clave

  • 12 temporizadores crean una tubería no lineal con pausas y saltos para frustrar análisis.
  • Entropía de Shannon 7,1+ bits por byte, probada en 64 KB.
  • T12 (pausas) y T11 (ceros) rompen predictibilidad temporal y secuencial.
  • Estado de 64 bits equilibra resistencia y velocidad.
  • No para cripto en producción: PRNG experimental.

— Editorial Team

Advertisement 728x90

Leer después