3

我构建了一个即将启动 beta 测试的 Web 应用程序。我真的很想分发看起来不错的 beta 邀请和密钥。

即A3E6-7C24-9876-235B

这是大约 16 个字符的十六进制数字。它看起来像您可能会看到的典型 beta 密钥。我的问题是生成这样的东西的标准方法是什么,并确保它是唯一的,并且有人猜测 beta 密钥并生成自己的密钥并不容易。

我有一些可能适用于 beta 密钥的想法:

  • MD5 对此足够安全,但它又长又难看,可能会导致 0 和 O 或 1 和 l 之间的混淆。
  • 我可以从一个长度为 16 位的大十六进制数开始。为了防止人们猜测下一个 beta 密钥可能每次都会将值增加一个随机数。即使我跳过大量数字,1111-1111-1111-1111 和 eeee-eeee-eeee-eeee 之间的数字范围也会有足够的空间。

我想我只是想知道是否有一种我在谷歌找不到的标准方法。有没有更好的办法?

4

3 回答 3

3

规范的“唯一标识号”是uuid。有多种形式 - 例如,您可以从随机数(版本 4)或某个值的哈希(用户的电子邮件 + salt?)(版本 3 和 5)生成一种。

存在用于 java、python 和更多库的库。

PS我必须补充一点,当我阅读您的问题标题时,我认为您正在寻找一些很酷和不同的东西。您可能会考虑使用“有趣”的单词列表并将单词与连字符组合来对数字进行编码(基于电子邮件 + salt 的哈希值)。恕我直言,这将更具吸引力:“您的 beta 代码是 secret-wombat-cookie-ninja”(我确定我读过一篇描述示例的文章,但现在找不到)。

于 2012-04-29T00:54:41.177 回答
3

一种方法(C#,但代码很简单,可以移植到其他语言):

private static readonly Random random = new Random(Guid.NewGuid().GetHashCode());

static void Main(string[] args)
{
    string x = GenerateBetaString();
}

public static string GenerateBetaString()
{
    const string alphabet = "ABCDEF0123456789";

    string x = GenerateRandomString(16, alphabet);

    return x.Substring(0, 4) + "-" + x.Substring(4, 4) + "-"
         + x.Substring(8, 4) + "-" + x.Substring(12, 4);
}

public static string GenerateRandomString(int length, string alphabet)
{
    int maxlen = alphabet.Length;
    StringBuilder randomChars = new StringBuilder(length);

    for (int i = 0; i < length; i++)
    {
        randomChars.Append(alphabet[random.Next(0, maxlen)]);
    }

    return randomChars.ToString();
}

输出:

97A8-55E5-C6B8-959E
8C60-6597-B71D-5CAF
8E1B-B625-68ED-107B
A6B5-1D2E-8D77-EB99
5595-E8DC-3A47-0605

这样做可以让您精确控制字母表中的字符。如果您需要加密强度随机性(不太可能),请使用 cryto 随机类来生成随机字节(可能修改字母长度)。

于 2012-04-29T01:02:07.090 回答
1

计算能力很便宜,采用您对 MD5 的想法并运行您自己设计的“美学”。下面的代码几乎瞬间生成了 2000 个唯一键,其中没有0,1,L,O字符。修改aesthetic以适应任何附加条件:

import random, hashlib

def potential_key():
    x = random.random()
    m = hashlib.md5()
    m.update(str(x))
    s = m.hexdigest().upper()[:16]
    return "%s-%s-%s-%s" % (s[:4],s[4:8],s[8:12],s[12:])

def aesthetic(s):
    bad_chars = ["0","1","L","O"]
    for b in bad_chars: 
        if b in s: return False
    return True

key_set = set()

while len(key_set) < 2000:
    k = potential_key()
    if aesthetic(k): 
        key_set.add(k)

print key_set

示例键:

'4297-CAC6-9DA8-625A', '43DD-2ED4-E4F8-3E8D', '4A8D-D5EF-C7A3-E4D5', 
'A68D-9986-4489-B66C', '9B23-6259-9832-9639', '2C36-FE65-EDDB-2CF7', 
'BFB6-7769-4993-CD86', 'B4F4-E278-D672-3D2C', 'EEC4-3357-2EAB-96F5', 
'6B69-C6DA-99C3-7B67', '9ED7-FED5-3CC6-D4C6', 'D3AA-AF48-6379-92EF', ...
于 2012-05-01T21:17:42.813 回答