14

我正在与需要生成数百万用于杂志刮刮卡、瓶盖奖品等的字母数字代码的客户合作。它们必须足够短才能打印在帽子上,它们要确保不包括像 1 和 I、0 和 O 等模棱两可的字符,并且必须明确存储它们以供将来使用——我们可以当有人试图赎回一个时,它只有一个确定“有效性”的算法。最后,他们希望确保代码随机分布在一个大的“代码空间”内,这样人们就不能通过遍历字母表来猜测其他代码。

是否有任何指向生成此类代码集的合理有效算法的指针?我在一个信封的背面刮了一些,但这个问题闻起来像一个粗心的陷阱。

4

5 回答 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;
}
于 2008-10-20T19:24:11.343 回答
7

假设您可以使用一个字符集,例如 40 个明确的大写、小写和数字字符。

对于 n 个字符的序列,您有 40 n 个组合

  • 40 4 = 2,560,000
  • 40 5 = 102,400,000
  • 40 6 = 4,096,000,000
  • 40 7 = 163,840,000,000
  • 40 8 = 6,553,600,000,000

因此 8 个字符提供了一个很好的工作空间——如果你生成了 1000 万个代码,你将不得不尝试数十万个组合来暴力破解代码。

或者你从另一个方向来 - 给出可能的代码数量,你应该生成多少代码以避免他们称之为生日悖论的陷阱?

取 8 个字符代码, 6,553,600,000,000 约为 2 42,因此您可以合理地从中生成 2 21 个代码,或 2,097,152

于 2008-10-20T19:08:51.297 回答
0

使用一次性密码算法?

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

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

但不要使用 0-9 位 base10 编码,而是使用 base32。

于 2008-10-20T19:51:01.867 回答
0

无论您使用哪种方法,我都建议您添加一个或两个校验位,作为防止人们误输入或试图发明数字的“第一线”防御。

于 2008-10-30T23:04:17.440 回答
-3

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

ABCDEFGHJKLMNPQRSTUVWXYZ23456789

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

ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789

于 2009-08-28T21:00:46.400 回答