使用alpanumeric子集生成1M唯一随机密钥

Gar*_*man 3 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"相同.

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

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

Tim*_* S. 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];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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