返回首页

基于 12 个定时器的 PHP PRNG:熵 7.1 位

ChaosRNG 类使用 12 个定时器实现 PRNG,用于生成具有 7.1+ 位熵的字节。定时器通过暂停、跳过和调制引入非线性。适用于令牌实验。

PHP PRNG:12 个定时器,提供 7+ 位熵
Advertisement 728x90

ChaosRNG:基于12个定时器的PHP伪随机字节生成器

ChaosRNG类利用12个相互关联的定时器生成字节,每个字节的熵值可达7.1–8位。每台定时器引入非线性元素——从基准时间和纳秒,到暂停和零字节插入。这种实验性方法适用于不需要认证加密原语的任务。

构造函数通过微秒(T1)、纳秒(T2)、进程ID和内存使用量(T7)的异或初始化状态。失真因子初始值为1.001,默认开启开关。

定时器逻辑

定时器形成处理流水线:

Google AdInline article slot
  • T1:自1970年起微秒数。
  • T2:系统启动以来纳秒数。
  • T3:通过累加或减去总和的最低字节更新64位状态。
  • T4:通过乘除因子k调制时间,每周期更新。
  • T5:确定切片数(1000–10000)。
  • T6:选择用于时间加权的切片。
  • T7:通过进程ID和内存缓存中断抖动。
  • T8:开关——关闭时跳过真实字节。
  • T9:根据上一个字节(<5开启,>5关闭)控制T8。
  • T10:构造函数中的隐藏起点。
  • T11:当($state & 10)=== 0时插入0x00。
  • T12:暂停1–100个周期,等待期间更新状态。
/**
 * ChaosRNG - 使用12个定时器的随机字节生成器
 * 
 * 12个定时器:
 * T1  – 标准时钟 (microtime)
 * T2  – 高精度时钟 (hrtime)
 * T3  – 内存 (状态 $state)
 * T4  – 失真器 (乘除时间)
 * T5  – 切片器 (1000-10000切片)
 * T6  – 选择器 (切片选择)
 * T7  – 隐藏噪声 (抖动、中断)
 * T8  – 开关 (输出开/关)
 * T9  – 监视器 (控制开关)
 * T10 – 起点 (初始化时刻)
 * T11 – 零字节 (插入零字节)
 * T12 – 静默器 (1-100周期暂停)
 */

class ChaosRNG {
    // 类属性
    private $state;      // T3: 64位状态
    private $k;          // T4: 失真因子
    private $enabled;    // T8: 开关 (开/关)
    private $lastByte;   // T9: 上一个输出字节
    private $dot;        // T11: 零字节标志
    private $pauseLen;   // T12: 暂停长度
    private $pauseRem;   // T12: 暂停余量
    
    /**
     * 构造函数 — T10 (起点)
     * 混合所有不可重复源
     */
    public function __construct() {
        // 异或所有源 → 唯一初始状态
        $this->state = (int)(microtime(true) * 1000000)  // T1: 微秒
                     ^ hrtime(true)                       // T2: 纳秒
                     ^ getmypid()                         // T7: 进程ID
                     ^ memory_get_usage();                // T7: 内存使用
        
        $this->k = 1.001;           // T4: 初始因子
        $this->enabled = true;      // T8: 开关开启
        $this->lastByte = 0;        // T9: 无上一个字节
        $this->dot = false;         // T11: 未插入零字节
        $this->pauseLen = 0;        // T12: 无暂停
        $this->pauseRem = 0;        // T12: 余量0
    }
    
    /**
     * T1: 标准时钟
     * 返回自1970年起微秒数
     */
    private function t1() {
        return (int)(microtime(true) * 1000000);
    }
    
    /**
     * T2: 高精度时钟
     * 返回启动以来纳秒数
     */
    private function t2() {
        return hrtime(true);
    }
    
    /**
     * 内部字节生成器 (T3-T7)
     * 更新状态并返回一个字节
     */
    private function nextByteInternal() {
        // T5: 切片数 1000 到 10000
        $K = 1000 + ($this->state % 9001);
        
        // T6: 选择特定切片
        $slot = (($this->state >> 8) % $K);
        
        // T1 和 T2: 获取当前时间
        $t1 = $this->t1();
        $t2 = $this->t2();
        
        // T4: 失真器 (拉伸或压缩时间)
        if ($this->state & 1) {
            $t1 = $t1 * $this->k;   // 拉伸 T1
        } else {
            $t2 = $t2 / $this->k;   // 压缩 T2
        }
        
        // 与选定切片求和
        $total = (int)($t1 * ($slot + 1) / $K)
               + (int)($t2 * ($slot + 1) / $K);
        
        // T3: 更新状态 (加或减)
        if ($total & 1) {
            $this->state += ($total & 0xFF);
        } else {
            $this->state -= ($total & 0xFF);
        }
        
        // 更新失真因子
        $this->k = 1.0 + (($this->state & 0xFF) / 10000.0);
        
        // 返回状态最低字节
        return $this->state & 0xFF;
    }
    
    /**
     * 公共方法:获取N个随机字节
     * 考虑所有12个定时器
     */
    public function getBytes($n) {
        $out = [];
        
        for ($i = 0; $i < $n; $i++) {
            // T12: 暂停 (静默器)
            while ($this->pauseRem > 0) {
                $this->pauseRem--;
                $this->nextByteInternal(); // 状态变化
            }
            
            // 暂停结束 — 生成新的
            if ($this->pauseRem === 0 && $this->pauseLen === 0) {
                $this->pauseLen = 1 + ($this->state % 100); // 1-100周期
                $this->pauseRem = $this->pauseLen;
            }
            
            // T11: 零字节 (插入零字节)
            if (($this->state & 10) === 0 && !$this->dot) {
                $this->dot = true;
                $this->nextByteInternal();
                $out[] = 0x00; // 零字节
                continue;
            }
            $this->dot = false;
            
            // T9: 开关监视器
            if ($this->lastByte < 5) {
                $this->enabled = true;   // 开启
            } elseif ($this->lastByte > 5) {
                $this->enabled = false;  // 关闭
            }
            // 如果==5,不变
            
            // 生成字节
            $byte = $this->nextByteInternal();
            
            // T8: 开关
            if (!$this->enabled) {
                // 关闭时 — 输出哑字节
                $out[] = $this->nextByteInternal() & 0xFF;
                continue;
            }
            
            // 保存上一个输出字节
            $this->lastByte = $byte;
            
            // 真实字节后重置暂停
            if ($this->pauseLen > 0) {
                $this->pauseLen = 0;
                $this->pauseRem = 0;
            }
            
            $out[] = $byte;
        }
        
        return $out;
    }
}

香农熵计算

静态entropy()方法使用-Σ p * log2(p)计算字节频率的香农熵。对64 KB数据的测试显示平均7.12位。

public static function entropy($bytes) {
    // 统计字节频率
    $freq = array_fill(0, 256, 0);
    foreach ($bytes as $b) {
        $freq[$b]++;
    }
    
    // 香农公式:-Σ 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;
}

// 测试
$rng = new ChaosRNG();
$data = $rng->getBytes(65536);
$entropy = ChaosRNG::entropy($data);
echo "熵值: " . round($entropy, 4) . " / 8 位\n";

非线性和鲁棒性

恢复状态需要知道k值、切片数、暂停和开关位置。64位状态在无服务器访问的情况下阻碍攻击。即使在虚拟机上,熵值>6.5位也使序列统计上接近随机。

使用场景:令牌和密码生成(16字符约113位熵)。不用于加密——仅限实验。

Google AdInline article slot

关键要点

  • 12个定时器创建非线性流水线,包含暂停和跳过以挫败分析。
  • 香农熵每字节7.1+位,64 KB测试验证。
  • T12(暂停)和T11(零字节)打破时间和序列可预测性。
  • 64位状态平衡鲁棒性和速度。
  • 非生产加密使用:实验性PRNG。

— Editorial Team

Advertisement 728x90

继续阅读