在PHP/MySQL中生成唯一代码?

14
我正在与一位客户合作,需要生成数百万个字母数字代码,用于杂志刮刮卡、瓶盖奖品等。它们必须足够短以便打印在瓶盖上,确保不包括模糊字符(如1和I、0和O等),并且必须明确存储以供将来使用 -- 我们不能仅通过算法来确定“有效性”当有人试图兑换某一个的时候。最后,他们希望确保这些代码在大型“代码空间”内是随机分布的,以便人们无法通过遍历字母表来猜测额外的代码。
有没有关于生成这种代码集的合理高效算法的指针?我已经在信封背面草草地写了几个,但这个问题看起来很容易陷入陷阱。
5个回答

13
如果您需要大约1000万个唯一的密钥(例如),最好的方法是选择指数级别更大的密钥空间,然后开始随机生成。请阅读生日悖论--这是您应该担心的主要问题。如果您想要2^n个唯一且安全的密钥,请确保至少有2^(2 * n)个可能的值。以下是一个粗略的O(n log n)算法:
  • 使用至少2^50的密钥空间(因此,换句话说,允许2^50个可能的唯一值),您将在整个数据集中几乎没有任何冲突--并且任何暴力破解您的密钥的人尝试其中的2^25个密钥时,他们都有相同的胜率。
  • 生成尽可能多的随机数字
  • 按照密钥索引数据库(这是O(n lg n)步骤:排序)
  • 浏览数据库并遍历整个数据集以修剪重复项(下面是伪代码)
  • 删除重复行,完成。

伪代码:

$last = null;
while ($current = getnext()) {
    if ($last == $current) {
        push($toDelete, $current);
    }
    $last = $current;
}

1
我的目标是特别避免这种情况,因此您无需在插入时对每一行进行唯一性检查。相反,您可以插入完整的数据列表并对其进行一次排序,复杂度为O(n lg n)。除非DB在小于O(lg n)的时间内验证您的唯一键,否则未索引的DB就是您想要的。 - ojrac

7
假设您可以使用一个由40个字符组成的字符集,其中包括明确的大写、小写和数字字符。
对于长度为n的字符序列,您有40n种组合。
  • 404 = 2,560,000
  • 405 = 102,400,000
  • 406 = 4,096,000,000
  • 407 = 163,840,000,000
  • 408 = 6,553,600,000,000
因此,8个字符提供了一个相当好的工作空间 - 如果您生成了1000万个代码,您需要尝试数十万个组合才能强制破解代码。
或者您可以从另一个角度考虑 - 给出可能的代码数量,您应该生成多少代码以避免他们所谓的生日悖论陷阱?

将这个8位字符代码,6,553,600,000,000约等于2的42次方,因此您可以合理地从中生成2的21次方个代码,即2,097,152个


0

使用一次性密码算法?

RFC4225详细介绍了基于HMAC算法的一种算法。

http://www.ietf.org/rfc/rfc4226.txt

但是,不要使用0-9数字的十进制编码,而是使用基于32的编码。


0
无论你使用什么方法,我建议你添加一个或两个校验位作为“第一道防线”,以防止人们输入错误或试图编造数字。

-3

奇怪的是,使用以下种子,我只能生成32个唯一的字符串。

ABCDEFGHJKLMNPQRSTUVWXYZ23456789

使用更长的种子,我能够成功地生成了40,000个唯一的字符串。

ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接