您需要一些构造上正确的东西,即排列函数:这是一个将一个整数(顺序计数器)到另一个整数进行一对一、可逆映射的函数。
一些示例(这些的任意组合也应该有效):
- 反转一些位(例如使用 XOR,PHP 中的 ^)
- 交换位的位置 (($i & 0xc) >> 2 | ($i & 0x3)
- 添加一个以最大范围为模的常数值(如果您将其与上面的值结合起来,则必须是两倍)
示例:此函数会将 0, 1, 2, 3, 5, .. 转换为 13, 4, 12, 7, 15, .. 对于 15 以内的数字:
$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;
EDIT
一种更简单的方法是使用线性同余生成器(LCG,通常用于生成随机数),它由以下形式的公式定义:
X_n+1 = (a * X_n + c) mod m
For 良好的价值观 http://en.wikipedia.org/wiki/Linear_congruential_generator对于 a、c 和 m,X_0、X_1 .. X_m-1 的序列将仅包含 0 到 m-1 之间的所有数字一次。现在您可以从线性增加的索引开始,并使用nextLCG 序列中的值作为您的“秘密”密钥。
EDIT2
执行:
你可以设计您自己的 LCG 参数 http://en.wikipedia.org/wiki/Linear_congruential_generator,但如果你弄错了,它不会覆盖整个范围(因此有重复项),所以我将使用这里发布的和尝试过的参数集这张纸 http://www.taygeta.com/rwalks/node1.html:
a = 16807, c = 0, m = 2147483647
这将为您提供 2**31 的范围。使用 pack(),您可以将结果整数作为字符串获取,base64_encode() 使其成为可读字符串(最多 6 个有效字符,每个字节 6 位),因此这可以是您的函数:
substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)