生成 1M 个具有 alpanumeric 子集的唯一随机键
本文关键字:唯一 随机 子集 alpanumeric 1M 生成 | 更新日期: 2023-09-27 18:37:25
我想生成1M个随机(出现)唯一的字母数字键并将它们存储在数据库中。每个键的长度为 8 个字符,仅使用子集"abcdefghijk n pqrstuvxyz and 0-9"。
字母 l、m、o 和 w 被抛弃。由于打印空间有限,"M和W"被省略了,因为每个键都将在非常小的空间内打印在产品上。启用删除 m 和 w 以增加 2pt 的字母大小,从而提高可读性。L和O被丢弃,因为它们在当前的打印尺寸下很容易与1,I和0混淆。我们做了一些测试字符 1,i 和 0 总是正确读取,l 和 o 有很多错误。首都被排除在外的原因与'm和w'相同。
那么为什么不是一个序列呢?几个原因:密钥可以在之后注册,我们不希望任何人猜测序列中的下一个密钥并注册其他人的密钥。外观:我们不需要客户和竞争对手就知道我们只运送了几千把钥匙。
有没有一种实用的方法来生成密钥,确保每个密钥的唯一性并将它们存储在数据库中?谢谢!
编辑:@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 方法不是很快,但可能足以满足您的目的)
100 万并不多,你可能可以在一台机器上相当快地做到这一点。毕竟这是一次性操作。
- 获取哈希表(或哈希集)
- 生成随机键并将它们作为键放入其中(或者直接放入其中,如果是集合),直到计数达到 100 万
- 将它们写入数据库
我的快速而肮脏的测试代码如下所示:
function new-key {-join'abcdefghijknpqrstuvxyz0123456789'[(0..7|%{random 32})]}
$keys = @{}
for(){$keys[(new-key)]=1}
但是PowerShell很慢,所以我希望C++或C#在这里做得很好。
有没有一种实用的方法来生成密钥,确保唯一性 每个键并将它们存储在数据库中?
由于这是单个操作,因此您只需执行以下操作:
1) 生成单个密钥
2) 验证生成的密钥在数据库中不存在。
3) 如果确实存在,则生成一个新密钥。
3b) 如果不存在,则将其写入数据库4) 返回步骤 1
当然还有其他选择,最终归结为生成密钥,并确保它不存在于数据库中。
理论上你可以生成1000万个密钥(为了节省处理能力)将它们写入文件。 生成密钥后,只需查看每个密钥,看看它是否已退出数据库。 您可能可以在不到 48 小时内编写一个完成此操作的工具。
我曾经遇到过类似的问题......我所做的是创建一个独特的序列YYYY/MM/DD/HH/MM/SS/millis/nano并获取其哈希代码。之后,我使用哈希作为键。您的客户和竞争对手将无法猜测下一个价值。这可能不是完整的证据,但就我而言,这已经足够了!
要实际获取随机字符串,您可以使用类似于以下内容的代码:
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;
}