使用字母数字子集生成1M唯一随机密钥

时间:2012-06-15 15:08:53

标签: c# random unique

我想生成1M随机(出现)唯一字母数字键并将它们存储在数据库中。每个密钥长度为8个字符,仅使用子集“abcdefghijk n pqrstuvxyz和0-9”。

丢弃字母l,m,o和w。由于打印空间有限,“m和w”被省略,因为每个键将在非常小的空间内打印在产品上。删除m和w可以使字母大小增加2pt,从而提高可读性。 l和o被丢弃,因为它们很容易与当前打印尺寸的1,i和0混合。我们做了一些测试字符1,i和0总是正确读取,l和o有很多错误。资本被遗漏的原因与“m和w”相同。

那为什么不是一个序列呢?有几个原因:密钥可以在之后注册,我们不希望任何人猜测序列中的下一个密钥并注册其他人的密钥。外观:我们不需要客户和竞争对手知道我们只发了几千把钥匙。

是否有实用的方法来生成密钥,确保每个密钥的唯一性并将其存储在数据库中?谢谢!

5 个答案:

答案 0 :(得分:6)

编辑:@CodeInChaos指出了一个问题:System.Random不是很安全,并且可以毫不费力地重现序列。我在这里用安全生成器替换了Random

var possibilities = "abcdefghijknpqrstuvxyz0123456789".ToCharArray();
int goal = 1000000;
int codeLength = 8;
var codes = new HashSet<string>();
var random = new RNGCryptoServiceProvider();
while (codes.Count < goal)
{
    var newCode = new char[codeLength];
    for (int i = 0; i < codeLength; i++)
        newCode[i] = possibilities[random.Next(possibilities.Length)];
    codes.Add(new string(newCode));
}
// now write codes to database

static class Extensions
{
    public static byte Next(this RNGCryptoServiceProvider provider, byte maximum)
    {
        var b = new byte[1];
        while (true)
        {
            provider.GetBytes(b);
            if (b[0] < maximum)
                return b[0];
        }
    }
}

(Next方法不是很快,但可能对你的目的而言足够好)

答案 1 :(得分:1)

  

是否有实用的方法来生成密钥,确保唯一性   每个密钥并将它们存储在数据库中?

由于这是一项操作,您只需执行以下操作:

1)生成单个键
2)验证数据库中是否存在生成的密钥 3)如果确实存在,则生成新密钥 3b)如果不存在,请将其写入数据库 4)返回步骤1

当然还有其他选择,最后归结为生成密钥,并确保它不存在于数据库中。

理论上,您可以生成1000万个密钥(为了节省处理能力)将它们写入文件。生成密钥后,只需查看每个密钥,看它是否已经退出数据库。 您可能会在不到48小时内编写一个可以执行此操作的工具。

答案 2 :(得分:1)

这些天100万并不多,你可以很快地在一台机器上做到这一点。毕竟这是一次性操作。

  1. 获取哈希表(或哈希集)
  2. 生成随机密钥并将其作为密钥(或直接在一组中)放入其中,直到计数为100万
  3. 将它们写入数据库
  4. 我快速而肮脏的测试代码如下所示:

    function new-key {-join'abcdefghijknpqrstuvxyz0123456789'[(0..7|%{random 32})]}
    $keys = @{}
    for(){$keys[(new-key)]=1}
    

    但PowerShell ,所以我希望C ++或C#在这里表现得非常好。

答案 3 :(得分:1)

我曾经遇到类似的问题..我所做的是创建一个独特的序列YYYY / MM / DD / HH / MM / SS / millis / nano并获取其哈希码。之后我使用哈希作为关键。您的客户和您的竞争对手将无法猜测下一个价值。它可能不是完整的证据,但在我的情况下它已经足够了!

答案 4 :(得分:0)

要实际获取随机字符串,您可以使用与此类似的代码:

Random rand = new Random(new DateTime().Millisecond);
String[] possibilities = {"a","b","c","d","e","f","g","h","i","j","k",
    "l","n","p","q","r","s","t","u","v","x","y","z","0","1","2","3","4",
    "5","6","7","8","9"};
for (int i = 0; i < 1000000; ++i)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    for (int j = 0; j < 8; ++j)
    {
        sb.Append(possibilities[rand.Next(possibilities.Length)]);
    }
    if (!databaseContains(sb.ToString()))
        databaseAdd(sb.ToString());
    else
        --i;
}