ChaosRNG:基于12个定时器的PHP伪随机字节生成器
ChaosRNG类利用12个相互关联的定时器生成字节,每个字节的熵值可达7.1–8位。每台定时器引入非线性元素——从基准时间和纳秒,到暂停和零字节插入。这种实验性方法适用于不需要认证加密原语的任务。
构造函数通过微秒(T1)、纳秒(T2)、进程ID和内存使用量(T7)的异或初始化状态。失真因子初始值为1.001,默认开启开关。
定时器逻辑
定时器形成处理流水线:
- 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位熵)。不用于加密——仅限实验。
关键要点
- 12个定时器创建非线性流水线,包含暂停和跳过以挫败分析。
- 香农熵每字节7.1+位,64 KB测试验证。
- T12(暂停)和T11(零字节)打破时间和序列可预测性。
- 64位状态平衡鲁棒性和速度。
- 非生产加密使用:实验性PRNG。
— Editorial Team
暂无评论。