You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求将自增Integer ID映射为固定长度非序混淆整数的PHP方案

解决自增ID可逆混淆为7位无顺序整数的PHP实现

首先得说,你之前用的「乘37+XOR」方案有顺序性是正常的——乘法是线性操作,哪怕加了XOR,相邻ID的结果变化还是有规律(比如ID+1后结果的低位波动很容易被察觉)。要实现真正看起来无规律的可逆转换,咱们可以用简化版Feistel密码结构,这玩意儿天生可逆,而且不需要数据库映射,纯算法就能搞定,刚好适合你的场景(1-70000的范围,转7位整数完全够)。

核心思路

Feistel网络通过多轮的「拆分-混淆-交换」操作打乱原数据,因为每一轮的操作都是可逆的,所以解密只需要反向执行步骤就行。咱们针对70000的范围做简化,不用太复杂的轮数,2-3轮就足够打乱顺序了,同时保证结果是7位整数。

PHP实现代码

<?php

// 自定义的轮函数,用来增加非线性混淆
function feistelRound($num, $key) {
    // 用乘法、加法、XOR组合,避免线性规律
    return (($num * 123) + 456) ^ $key;
}

// 加密:自增ID转7位无顺序整数
function encryptId($id) {
    if ($id < 1 || $id > 70000) {
        throw new InvalidArgumentException("ID必须在1-70000之间");
    }
    
    // 把ID拆分成高低两部分(70000的二进制是17位,拆成8位和9位)
    $left = $id >> 8;
    $right = $id & 0xFF;
    
    // 两轮混淆,用不同的密钥增强随机性
    $key1 = 98765;
    $key2 = 13579;
    
    // 第一轮
    $temp = $right;
    $right = $left ^ feistelRound($right, $key1);
    $left = $temp;
    
    // 第二轮
    $temp = $right;
    $right = $left ^ feistelRound($right, $key2);
    $left = $temp;
    
    // 合并高低位,再加上基准数1000000,确保结果是7位整数
    $encrypted = ($left << 8) | $right;
    return $encrypted + 1000000;
}

// 解密:7位整数转回原ID
function decryptId($encryptedNum) {
    if ($encryptedNum < 1000000 || $encryptedNum > 9999999) {
        throw new InvalidArgumentException("输入必须是7位整数");
    }
    
    // 先减去基准数,还原原始混淆值
    $num = $encryptedNum - 1000000;
    
    // 拆分高低位,和加密时的拆分方式一致
    $left = $num >> 8;
    $right = $num & 0xFF;
    
    $key1 = 98765;
    $key2 = 13579;
    
    // 反向执行第二轮(解密是加密的逆过程,轮数倒过来)
    $temp = $left;
    $left = $right ^ feistelRound($left, $key2);
    $right = $temp;
    
    // 反向执行第一轮
    $temp = $left;
    $left = $right ^ feistelRound($left, $key1);
    $right = $temp;
    
    // 合并得到原ID
    return ($left << 8) | $right;
}

// 测试示例
$testId = 1;
$encrypted = encryptId($testId);
echo "ID $testId 加密后: $encrypted\n";
echo "加密值 $encrypted 解密后: " . decryptId($encrypted) . "\n";

$testId2 = 2;
$encrypted2 = encryptId($testId2);
echo "ID $testId2 加密后: $encrypted2\n";
echo "加密值 $encrypted2 解密后: " . decryptId($encrypted2) . "\n";
?>

关键细节说明

  • 轮函数设计:feistelRound里用了乘法、加法、XOR的组合,避免线性操作带来的顺序性,你也可以自己调整里面的常数(比如123、456),只要保证可逆就行(这里的操作都是可逆的:加法逆是减法,乘法逆是除法(因为123和256互质,在8位范围内可逆),XOR逆是自身)。
  • 基准数:加1000000是为了确保结果一定是7位整数,避免出现小于6位的情况,解密时再减去就行。
  • 密钥:你可以自定义key1和key2,密钥不同,混淆后的结果也不同,增强自定义性。

为什么比之前的方案好?

这个方案通过多轮的非线性混淆,相邻ID的加密结果会完全无规律,比如ID=1和ID=2的加密值不会有明显的数值关联,完美解决你之前遇到的顺序性问题。而且全程纯算法,不需要数据库存储映射关系,适合分散的输入节点使用。

内容的提问来源于stack exchange,提问作者BSDG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:18:53