我正在与需要生成数百万用于杂志刮刮卡、瓶盖奖品等的字母数字代码的客户合作。它们必须足够短才能打印在帽子上,它们要确保不包括像 1 和 I、0 和 O 等模棱两可的字符,并且必须明确存储它们以供将来使用——我们可以当有人试图赎回一个时,它只有一个确定“有效性”的算法。最后,他们希望确保代码随机分布在一个大的“代码空间”内,这样人们就不能通过遍历字母表来猜测其他代码。
是否有任何指向生成此类代码集的合理有效算法的指针?我在一个信封的背面刮了一些,但这个问题闻起来像一个粗心的陷阱。
我正在与需要生成数百万用于杂志刮刮卡、瓶盖奖品等的字母数字代码的客户合作。它们必须足够短才能打印在帽子上,它们要确保不包括像 1 和 I、0 和 O 等模棱两可的字符,并且必须明确存储它们以供将来使用——我们可以当有人试图赎回一个时,它只有一个确定“有效性”的算法。最后,他们希望确保代码随机分布在一个大的“代码空间”内,这样人们就不能通过遍历字母表来猜测其他代码。
是否有任何指向生成此类代码集的合理有效算法的指针?我在一个信封的背面刮了一些,但这个问题闻起来像一个粗心的陷阱。
如果您需要大约 1000 万个唯一键(例如),最好的方法是选择一个指数级更大的键空间,然后开始随机生成。阅读有关生日悖论的信息——这是您应该担心的主要问题。如果您想要 2^n 个唯一且安全的密钥,请确保至少有 2^(2 * n) 个可能的值。这是一个粗略的 O(n log n) 算法:
伪代码:
$last = null;
while ($current = getnext()) {
if ($last == $current) {
push($toDelete, $current);
}
$last = $current;
}
假设您可以使用一个字符集,例如 40 个明确的大写、小写和数字字符。
对于 n 个字符的序列,您有 40 n 个组合
因此 8 个字符提供了一个很好的工作空间——如果你生成了 1000 万个代码,你将不得不尝试数十万个组合来暴力破解代码。
或者你从另一个方向来 - 给出可能的代码数量,你应该生成多少代码以避免他们称之为生日悖论的陷阱?
取 8 个字符代码, 6,553,600,000,000 约为 2 42,因此您可以合理地从中生成 2 21 个代码,或 2,097,152
使用一次性密码算法?
RFC4225 详细介绍了一种基于 HMAC 算法的方法。
http://www.ietf.org/rfc/rfc4226.txt
但不要使用 0-9 位 base10 编码,而是使用 base32。
无论您使用哪种方法,我都建议您添加一个或两个校验位,作为防止人们误输入或试图发明数字的“第一线”防御。
奇怪的是,使用以下种子我只能生成 32 个唯一字符串。
ABCDEFGHJKLMNPQRSTUVWXYZ23456789
使用更长的种子,我能够生成更多——成功生成 40,000 个唯一字符串。
ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789