【问题标题】:How can I generate a unique, small, random, and user-friendly key?如何生成唯一、小的、随机且用户友好的密钥?
【发布时间】:2010-09-07 06:36:59
【问题描述】:

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

我从未对这种特殊的实现感到满意。你们会怎么做?

【问题讨论】:

  • 为什么需要顺序值?你有回过头来吗?如果是,请使用加密函数使用密钥加密您的序列号,并使用您选择的字母对密码进行编码。
  • 很久没有问这个问题了。我很久以前就拒绝了这种方法。多年来,我现在使用加密强随机数生成器生成所需位的随机数,将数字存储在具有唯一密钥约束的数据库中,并在一段时间后(通常为 24 小时)使数字失效。我从未见过碰撞,如果有,我会重试。简单有效的解决方案。

标签: encoding cryptography key


【解决方案1】:

我会这样做。

我会获得一个常用英语单词列表以及使用频率和一些语法信息(比如它是名词还是动词?)。我认为您可以在 intertubes 周围寻找一些副本。 Firefox 是开源的,它有一个拼写检查器......所以它必须以某种方式获得。

然后我会对其运行过滤器,以便删除晦涩的单词并排除太长的单词。

然后我的生成算法将从列表中选择 2 个单词并将它们连接起来并添加一个随机的 3 位数字。

我还可以在动词/名词之间随机化单词选择模式,例如

eatCake778
pickBasket524
乘坐Flyer113 等等。

外壳不必是驼色外壳,您也可以随机化。您还可以随机排列数字和动词/名词的位置。

因为这是很多随机性,所以 Jeff 的 The Danger of Naïveté 是必读的。还要确保提前研究好字典攻击。

在我实现它之后,我会运行一个测试以确保我的算法永远不会发生冲突。如果冲突率很高,那么我会使用参数(使用的名词数量,使用的动词数量,随机数的长度,单词总数,不同类型的套管等)

【讨论】:

  • 普通的英语单词对于类似 tinyurl 的网站来说并不好。您更多地描述了密码生成器 IMO。
  • @dfrankow 来自问题“我们的 Web 应用程序的唯一和随机代码。代码必须是用户友好的并且尽可能小,但仍然基本上是随机的”......我错过了什么?
【解决方案2】:

在 C# 中,我使用了 'System.IO.Path.GetRandomFileName() : String' 方法...但我正在为调试文件名生成盐。这个方法返回的东西看起来像你的第一个例子,除了随机的“.xyz”文件扩展名。

如果您使用 .NET 并且只想要一个更简单(但不是“更好”的)解决方案,我会说就是这样...如果您愿意,可以删除随机文件扩展名。

【讨论】:

    【解决方案3】:

    在 .NET 中,您可以使用 RNGCryptoServiceProvider 方法 GetBytes(),该方法将“用加密强的随机值序列填充字节数组”(来自 ms 文档)。

    byte[] randomBytes = new byte[4];
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetBytes(randomBytes);
    

    您可以增加字节数组的长度并提取您想要允许的字符值。

    【讨论】:

      【解决方案4】:

      在撰写本文时,此问题的标题是:

      如何生成唯一、小的、随机且用户友好的密钥?

      对此,我应该注意,通常不可能创建一个 random 值也是 unique,至少如果每个随机值是独立于任何其他值生成的.此外,如果你想生成唯一标识符(来自我的section on unique random identifiers),你应该问自己很多事情:

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

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

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

      您在问题中未提及的要点包括:

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

      请注意,我不会讨论将唯一值格式化为“用户友好键”的问题。有很多方法可以做到这一点,它们都归结为将唯一值与“用户友好键”一对一地映射——如果输入值是唯一的,那么“用户友好键”也将是唯一的。

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 2020-10-07
            • 2017-06-06
            • 2011-02-18
            • 1970-01-01
            • 1970-01-01
            • 2020-04-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多