如何生成一个独特,小巧,随机且用户友好的密钥?

时间:2008-08-29 16:49:24

标签: encoding cryptography key

几个月前,我的任务是为我们的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小得多的代码并且看起来是随机的,即使它绝对不是。

我对此特定实现从未满意。你们会做什么?

6 个答案:

答案 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):

  1. 应用程序能否轻松检查标识符在所需范围和范围内的唯一性(例如,检查是否已存在具有该标识符的文件或数据库记录)?
  2. 应用程序可以承受为不同资源生成相同标识符的风险吗?
  3. 标识符是否必须很难猜测,仅仅是“看起来随机”还是都不是?
  4. 最终用户是否必须输入标识符或以其他方式中继标识符?
  5. 一个标识符标识的资源是否对知道该标识符的任何人可用(即使没有登录或以某种方式未授权)?
  6. 标识符必须令人难忘吗?

在您的情况下,您有几个相互冲突的目标:您想要的标识符是-

  • 独特,
  • 易于最终用户(包括小型用户)键入,并且
  • 难以猜测(包括随机)。

您在问题中没有提及的重要要点包括:

  • 密钥将如何使用?
  • 是否允许其他用户只要知道密钥就访问该密钥标识的资源?如果没有,那么将需要额外的访问控制或更长的密钥长度。
  • 您的应用程序可以承受重复密钥的风险吗?如果是这样,则可以完全随机生成密钥(例如通过加密RNG)。如果不是这样,那么您的目标将很难实现,尤其是对于出于安全目的的密钥。

请注意,我不涉及将唯一值格式化为“用户友好键”的问题。这样做的方法很多,它们全都归结为使用“用户友好键”一对一映射唯一值-如果输入值是唯一的,则“用户友好键”也将是唯一的。 / p>

答案 4 :(得分:0)

如果用户友好,您的意思是用户可以输入答案,那么我认为您可能希望看到不同的方向。我已经看到并完成了初始随机密码的实现,这些密码选择随机单词和数字作为一个更容易且不易出错的字符串。

如果您正在寻找一种方法来对URL字符串中的随机代码进行编码,这是我已经处理了一段时间的问题,那么我所做的就是使用64位编码的GUID。

答案 5 :(得分:0)

您可以将chakrit建议的单词列表加载到具有唯一顺序键的数据表或xml文件中。获取随机单词时,使用随机数生成器确定要通过其键获取的单词。如果你连接其中的两个,我认为你不需要在字符串中包含数字,除非“真正的随机性”是目标的一部分。