人类可读的 GUID

发布于 2024-08-15 20:24:16 字数 518 浏览 5 评论 0原文

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

优惠券需要用户输入的代码。该代码需要具有以下品质:

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

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

感谢您的帮助!


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

I'm writing a small system that will allow me to sell my band's music at gigs by generating vouchers that can be redeemed for MP3s at our website.

The vouchers will need a code that the user types in. The code needs to have the following qualities:

  1. Some level of human readability in terms of length and content, to prevent user frustration and data entry error.
  2. Given one voucher code, not trivial to guess another voucher code.

If I use GUIDs I'm concerned about point 1. If I use an incrementing integer I'm concerned about point 2. There has to be some happy medium in between, right? I thought perhaps this work has already been done and there's an ideal solution waiting out there for me. In the absence of that, I'm thinking I'll go with a random alphanumeric string, or possibly letters only (excluding I and O for clarity), and have the application block IP addresses that fail X number of times, which would indicate a possible brute force attack. If I went with that, how long of a string and what value of X would work, and why?

Thanks for your help!


Update: I wasn't totally explicit about the method: I will generate lists of voucher codes for printing, then enter the "sold" codes after a gig. Therefore I think elements like a checksum are not necessary like they are in software keys that don't use validation servers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

榕城若虚 2024-08-22 20:24:16

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

You could use a Markov Chain trained on English syllables to create a sentence composed of pronounceable-gibberish words. Just add the generated sentence to a database of valid vouchers when you print them (and invalidate them when they're redeemed, of course).

那伤。 2024-08-22 20:24:16

AOL 曾经在他们发出的 CD 上使用两个单词的随机组合。您可以采用相同的方法,只需增加单词数即可获得所需的赔率。

AOL used to use a random combination of two words for the CDs they sent out. You can take the same approach, and just increase the number of words to get the odds that you require.

陌生 2024-08-22 20:24:16

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

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

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

I would use your own encoding scheme. In addition to omitting I and O, for optimal readability it's also a good idea to omit all but one letter out of near-homonym sets (C/E, M/N) and multisyllabic letters, such as W, and of course stick to one case.

As far as length, you could use 60 bits, plus a 4-bit checksum. 64 bits is enough to store the time to millisecond granularity for several thousand years, so it's for all practical purposes unguessable. At say 4 bits per letter, that's 16 letters long. Even half that length is probably plenty.

Another way to think of this is in the form of automobile license plates: 3 letters and 3 numbers is enough to cover a pretty large state, and tends to be very readable. Unless you provide a way for someone to hack codes at high-speed, they certainly won't be guessable at human time scales.

最单纯的乌龟 2024-08-22 20:24:16

好吧,如果您确实想要人类可读,您可以使用 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 的答案应该很好(并且与我们对某些软件密钥所做的非常接近)。

Well, if you really want human readable, you can use BubbleBabble. Create a Perl script like the following:

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

Then feed it any command line argument you want to get output like the following:

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

Or if Perl's not your preference, you can use PWGen (also available online to get output like this:

aiCee5om Ohxai2is tae3Gael Gaeth7ei ooCh0ish

Honestly, this level of human readability is overkill; RickNZ's answer should work just fine (and is pretty close to what we did for some software keys). But BubbleBabble is kind of fun.

野の 2024-08-22 20:24:16

仅 8 个字母数字字母(I 和 O 除外)就有 1785793904896 种可能的组合。只要你没有 50 亿代金券,这从任何角度来说都是不可猜测的。

Only 8 alphanumeric letters (except I and O) have 1785793904896 possible combinations. That's for all intent and purposes unguessable as long as you don't have 5 billions vouchers.

渡你暖光 2024-08-22 20:24:16

上下文

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

问题

  • 设计一种用于生成“人类可读”UUID (HR-UUID) 的算法
  • 强力猜测
  • HR-UUID 应该对人类的 输入和回忆具有鲁棒性应该是简单的而不是错误的-容易
  • 拥有 1 个或多个已知的有效 HR-UUID 不应与猜测其他有效 HR-UUID 具有统计相关性

解决方案

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

    蟹肉教练正确驾驶瑜伽雪貂
    版鼠织物萌芽书太平间
    摇摇欲坠-无冕-耳朵多数-转租-逃避
    

另请参阅

Context

  • human-readable UUID
  • language-independent algorithm

Problem

  • devise an algorithm for generating "human readable" UUIDs (HR-UUID)
  • HR-UUID should be robust against brute-force guesses
  • entry and recall by a human being should be straightforward and not error-prone
  • having 1 or more known valid HR-UUID should not be statistically relevant for guessing other valid HR-UUIDs

Solution

  • Use the DiceWare password algorithm.
  • In contrast to the other solutions offered in this thread, this approach solves the human-readable UUID problem by re-casting the problem to that of password generation.
  • In contrast to the BubbleBabble solution offered elsewhere in this thread, Diceware allows you to choose how many elements are included in each UUID, depending on how many times you wish to "roll the die" ... this means you get to choose the entropy per UUID.
  • DiceWare password algorithm solves the problem of generating high-entropy passphrases that are nonetheless easy for humans to both enter and remember.
  • Below is a sampling of Diceware "UUIDs" consisting of six elements each:

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

See also

两个我 2024-08-22 20:24:16

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

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

5 blocks of 5 characters each should be sufficient - four blocks for the "key", the fifth as a checksum to ensure validity. And of course, don't use the whole keyspace.

That's roughly how software serial numbers appear to be laid out, anyway.

淡紫姑娘! 2024-08-22 20:24:16

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

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

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

将为您提供电话号码长度 GUID,

但只有 99999 使用!多赫

hmm, I do not know how most systems work, but I think it would be neat and simple to define a static number and multiply that number by a random other number. Then if the big GUID is a multiple of your static you are good.

Easy to produce, not easy to guess a new one (short term use only)

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

will give you a phone number length GUID

only 99999 uses though! doh

心房的律动 2024-08-22 20:24:16

也许最好避免所有元音[*],从而避免所有脏话。

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

Probably best to avoid all the vowels[*], thus avoiding all the swearwords.

[*] Including W if you're Welsh!

鸢与 2024-08-22 20:24:16

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

One simple solution is to call the getHashCode method that most languages have on their string types. Set the string to some word from your list of approved words. Then call gethashcode and that will be your key. To verify it, compare it against your list of existing word hashes and maybe delete it from the list so it can't be used again.

乖乖兔^ω^ 2024-08-22 20:24:16

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

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

I'm assuming you're getting an email address when they purchase the voucher (you should). If so, why not just email them a single-use GUID? That way both you and they have a record of it, you can track redemptions, you don't run the risk of guessing (or at least not one worth bothering with), the user doesn't have to remember anything because it's there in the email, and you don't have to code anything.

They give you email address. You email GUID (with link). They click link and get song. GUID use is registered in system and will no longer work.

ι不睡觉的鱼゛ 2024-08-22 20:24:16

为什么不直接使用 GUID,然后用不同的字母替换任何有问题的字符(因此 0 变为“h”,1 变为“q”等等)。

Why not just go with the GUID and then replace any questionable characters with a different letter (so 0 becomes 'h', 1 is 'q' and so forth).

反差帅 2024-08-22 20:24:16

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

you can try something like random letter sequence generator ?. You can mix and match letters/numbers as well

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文