几个月前,我的任务是为我们的Web应用程序实现一个独特的随机代码。代码必须是用户友好的并且尽可能小,但仍然基本上是随机的(因此用户无法轻易预测序列中的下一个代码)。
它最终产生的值看起来像这样:
Af3nT5Xf2
不幸的是,我对实施从未满意。 Guid是不可能的,它们对于用户来说太大而且难以输入。我希望能够提供更多的4或5个字符/数字的内容,但是如果我们编码为的话,我们的特定实现会生成明显的图案序列少于9个字符。
以下是我们最终做的事情:
我们从数据库中提取了一个唯一的顺序32位id。然后我们将它插入64位RANDOM整数的中心位。我们创建了一个易于键入和识别的字符的查找表(A-Z,a-z,2-9跳过容易混淆的字符,如L,l,1,O,0等)。最后,我们使用该查找表对64位整数进行base-54编码。高位是随机的,低位是随机的,但中心位是顺序的。
最终结果是一个比guid小得多的代码并且看起来是随机的,即使它绝对不是。
我对此特定实现从未满意。你们会做什么?
答案 0 :(得分:7)
我将如何做到这一点。
我会获得一个常用英语单词列表,其中包含使用频率和一些语法信息(如名词或动词?)。我想你可以看看intertubes周围的一些副本。 Firefox是开源的,它有一个拼写检查程序......所以它必须以某种方式获得。
然后我会在其上运行一个过滤器,这样就会删除模糊的单词,并排除那些太长的单词。
然后我的生成算法会从列表中选择2个单词并连接它们并添加一个随机的3位数字。
我还可以在动词/名词之间随机化单词选择模式,如
<强> eatCake778
pickBasket524
rideFlyer113 等。强>
案件不一定是骆驼套管,你也可以随机化。您还可以随机化数字和动词/名词的位置。
由于这是很多随机化,杰夫的The Danger of Naïveté是必读的。还要确保提前很好地研究字典攻击。
在我实施之后,我会进行测试以确保我的算法永远不会发生碰撞。如果碰撞率很高,那么我会玩参数(使用的名词数量,使用的动词数量,随机数的长度,单词总数,不同类型的外壳等)。
答案 1 :(得分:3)
在C#中,我使用了'System.IO.Path.GetRandomFileName() : String'方法......但是我为调试文件名生成了盐。这个方法返回看起来像你的第一个例子的东西,除了随机的'.xyz'文件扩展名。
如果您使用.NET并且只想要一个更简单(但不是'更好'的)解决方案,我会说这就是它...如果您愿意,可以删除随机文件扩展名。
答案 2 :(得分:3)
在.NET中,您可以使用RNGCryptoServiceProvider方法GetBytes(),它将“使用加密强大的随机值序列填充字节数组”(来自ms文档)。
byte[] randomBytes = new byte[4];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
您可以增加字节数组的长度并拔出您想要允许的字符值。
答案 3 :(得分:2)
在撰写本文时,该问题的标题是:
如何生成唯一,小巧,随机且用户友好的密钥?
为此,我应该注意,至少在每个随机值均独立于其他值生成的情况下,通常不可能创建也是 unique 的 random 值。此外,还有很多事情要问自己是否要生成唯一的标识符(这些标识符来自我的section on unique random identifiers):
在您的情况下,您有几个相互冲突的目标:您想要的标识符是-
您在问题中没有提及的重要要点包括:
请注意,我不涉及将唯一值格式化为“用户友好键”的问题。这样做的方法很多,它们全都归结为使用“用户友好键”一对一映射唯一值-如果输入值是唯一的,则“用户友好键”也将是唯一的。 / p>
答案 4 :(得分:0)
如果用户友好,您的意思是用户可以输入答案,那么我认为您可能希望看到不同的方向。我已经看到并完成了初始随机密码的实现,这些密码选择随机单词和数字作为一个更容易且不易出错的字符串。
如果您正在寻找一种方法来对URL字符串中的随机代码进行编码,这是我已经处理了一段时间的问题,那么我所做的就是使用64位编码的GUID。
答案 5 :(得分:0)
您可以将chakrit建议的单词列表加载到具有唯一顺序键的数据表或xml文件中。获取随机单词时,使用随机数生成器确定要通过其键获取的单词。如果你连接其中的两个,我认为你不需要在字符串中包含数字,除非“真正的随机性”是目标的一部分。