13

我正在编写一个小型系统,通过生成可以在我们的网站上兑换 MP3 的优惠券,我可以在演出中出售我乐队的音乐。

代金券需要用户输入的代码。代码需要具有以下特性:

  1. 在长度和内容方面具有一定程度的人类可读性,以防止用户感到沮丧和数据输入错误。
  2. 给定一个优惠券代码,猜测另一个优惠券代码并非易事。

如果我使用 GUID,我会担心第 1 点。如果我使用递增整数,我会担心第 2 点。两者之间必须有一些快乐的媒介,对吧?我想也许这项工作已经完成,并且有一个理想的解决方案在等着我。如果没有,我想我会使用随机的字母数字字符串,或者可能只有字母(为了清楚起见,不包括 I 和 O),并让应用程序阻止失败 X 次的 IP 地址,这表明可能的蛮力攻击。如果我这样做,字符串的长度和 X 的值会起作用,为什么?

谢谢你的帮助!


更新:我并没有完全明确该方法:我将生成用于打印的凭证代码列表,然后在演出后输入“已售”代码。因此,我认为校验和之类的元素不是必需的,就像它们在不使用验证服务器的软件密钥中一样。

4

13 回答 13

9

您可以使用经过英语音节训练的马尔可夫链来创建一个由可发音的胡言乱语单词组成的句子。只需在打印时将生成的句子添加到有效凭证的数据库中(当然,在兑换时使它们无效)。

于 2009-12-18T04:06:18.487 回答
5

我会使用你自己的编码方案。除了省略 I 和 O,为了获得最佳可读性,在近同音词集(C/E、M/N)和多音节字母(例如 W)中省略一个字母以外的所有字母也是一个好主意,当然要坚持一个案例。

至于长度,您可以使用 60 位,外加 4 位校验和。64 位足以将时间以毫秒为粒度存储数千年,因此对于所有实际目的而言,它是不可猜测的。假设每个字母 4 位,即 16 个字母长。即使是这个长度的一半也可能足够了。

另一种思考方式是汽车牌照的形式:3 个字母和 3 个数字足以覆盖一个相当大的状态,并且往往非常易读。除非你为某人提供一种高速破解代码的方法,否则它们在人类时间尺度上肯定是不可猜测的。

于 2009-12-18T04:14:53.850 回答
4

好吧,如果你真的想要人类可读,你可以使用BubbleBabble。创建一个 Perl 脚本,如下所示:

#!/usr/bin/perl
use Digest::BubbleBabble qw(bubblebabble);
use Digest::SHA1 qw(sha1);
print bubblebabble(Digest => sha1(join(' ', @ARGV))), "\n";

然后向它提供您想要获得输出的任何命令行参数,如下所示:

xogan-nydut-zogiv-kotyn-ledah-taseb-gyhib-tucel-vudul-mykom-mexax

或者,如果 Perl 不是您的偏好,您可以使用PWGen (也可以在线获得这样的输出:

aiCee5om Ohxai2is tae3Gael Gaeth7ei ooCh0ish

老实说,这种程度的人类可读性是多余的。RickNZ 的答案应该可以正常工作(并且非常接近我们为某些软件密钥所做的)。但是 BubbleBabble 很有趣。

于 2009-12-18T04:50:18.540 回答
4

只有 8 个字母数字字母(I 和 O 除外)有 1785793904896 种可能的组合。只要您没有 50 亿张代金券,所有意图和目的都是不可猜测的。

于 2009-12-18T04:06:36.943 回答
4

AOL 过去常常使用两个词的随机组合来表示他们发送的 CD。您可以采用相同的方法,只需增加单词的数量即可获得所需的几率。

于 2009-12-18T04:08:19.200 回答
2

5 个块,每块 5 个字符就足够了 - 四个块用于“密钥”,第五个块作为校验和以确保有效性。当然,不要使用整个键空间。

无论如何,这大致就是软件序列号的排列方式。

于 2009-12-18T04:05:17.597 回答
2

嗯,我不知道大多数系统是如何工作的,但我认为定义一个静态数字并将该数字乘以一个随机的其他数字会很简洁。然后,如果大 GUID 是您的静态的倍数,那么您就很好。

易于生产,不易猜出新的(仅限短期使用)

int i = 61234;
int j = rand()%99999
long GUID = i * j;

会给你一个电话号码长度的 GUID

虽然只有 99999 次使用!多哈

于 2009-12-18T04:06:41.290 回答
2

可能最好避免使用所有元音 [*],从而避免使用所有脏话。

[*] 如果你是威尔士人,包括 W!

于 2009-12-18T04:18:56.227 回答
2

语境

  • 人类可读的 UUID
  • 语言无关算法

问题

  • 设计一种算法来生成“人类可读”的 UUID (HR-UUID)
  • HR-UUID 应该对暴力猜测具有鲁棒性
  • 人工录入和召回应该简单明了,不易出错
  • 具有 1 个或多个已知的有效 HR-UUID 不应该与猜测其他有效 HR-UUID 的统计相关性

解决方案

  • 使用DiceWare 密码算法
  • 与该线程中提供的其他解决方案相比,这种方法通过将问题重新转换为密码生成问题来解决人类可读的 UUID 问题。
  • 与此线程中其他地方提供的BubbleBabble解决方案相比,Diceware 允许您选择每个 UUID 中包含多少元素,具体取决于您希望“掷骰子”的次数......这意味着您可以选择熵每个 UUID。
  • DiceWare 密码算法解决了生成高熵密码短语的问题,这些密码短语仍然易于人类输入和记住。
  • 以下是 Diceware “UUID”的示例,每个包含六个元素:

    crabmeat-coach-properly-driving-yoga-ferret
    edition-mousy-fabric-budding-book-mortuary
    rickety-uncrown-earful-majority-sublet-evade
    

也可以看看

于 2019-12-16T17:42:26.543 回答
1

一种简单的解决方案是调用大多数语言的字符串类型的 getHashCode 方法。将字符串设置为您批准的单词列表中的某个单词。然后调用 gethashcode 这将是你的关键。要验证它,请将其与您现有的单词哈希列表进行比较,并可能将其从列表中删除,使其无法再次使用。

于 2009-12-18T04:14:09.653 回答
1

我假设您在购买优惠券时会收到一个电子邮件地址(您应该)。如果是这样,为什么不通过电子邮件向他们发送一次性 GUID?这样你和他们都有记录,你可以跟踪兑换,你不会冒猜测的风险(或者至少不值得打扰),用户不必记住任何东西,因为它就在那里电子邮件,您无需编写任何代码。

他们给你电子邮件地址。您通过电子邮件发送 GUID(带有链接)。他们点击链接并获取歌曲。GUID 使用已在系统中注册,将不再有效。

于 2009-12-18T04:25:39.037 回答
1

为什么不直接使用 GUID,然后用不同的字母替换任何有问题的字符(所以 0 变成 'h',1 是 'q' 等等)。

于 2009-12-18T04:30:40.343 回答
0

您可以尝试随机字母序列生成器之类的东西吗?. 您也可以混合和匹配字母/数字

于 2009-12-18T04:09:38.163 回答