【问题标题】:How can I generate unique, non-sequential serial keys without 3rd party software?如何在没有第三方软件的情况下生成唯一的、非顺序的序列密钥?
【发布时间】:2011-10-03 14:59:58
【问题描述】:

我正在从事一个涉及为硬件实现编写低级 C 软件的项目。我们希望为我们的设备实施一项新功能,我们的用户可以在购买关联的许可证密钥时解锁该功能。

所需的实施步骤很简单。用户打电话给我们,他们请求该功能并向我们发送付款。接下来,我们通过电子邮件向他们发送产品密钥,他们将其输入硬件以解锁该功能。

我们的硬件没有连接到互联网。因此,必须以这样一种方式实施算法,即可以从服务器和设备内部生成这些密钥。密钥的种子可以从硬件序列号派生,这两个位置都可用。

我需要一个简单的算法,它可以采用连续数字并生成 16-20 个字母数字字符的唯一、非连续键。

更新

SHA-1 看起来是最好的方法。但是,我从 SHA-1 密钥的示例输出中看到的是它们很长(40 个字符)。如果我使用 40 char 键并截断除最后 16 个字符之外的所有字符,我会获得足够的结果吗?

【问题讨论】:

  • 如果您只使用 16 个 base-64 字符,那么就是 96 位。如果您生成 281474976710656 个序列号(即 2^36 个键 - birthday paradox 50% 界限),您可能会发生冲突(读取:非唯一序列号)
  • 为什么输入必须是序号?
  • @ThomasM.DuBuisson 如果他们以每个 2 美元的价格出售 2^36 个许可证,那就是新西兰的 GDP。我认为它们在一段时间内是安全的。
  • @NickJohnson 是的,这就是我的观点;-)。尽管如此,如果他们想要更安全,他们可以在 CNT 模式下使用 BlowFish(或仅 3DES)来生成 64 位值(11 个 base-64 字符),这些值在数学上肯定是唯一的,计数为 2^64。跨度>
  • @NickJ,输入的是设备序列号,在设备制造时顺序生成。这些序列号存储在数据库中,因此客户硬件和我为办公室创建的任何密钥生成器都可以访问种子。

标签: c algorithm security copy-protection


【解决方案1】:

您可以将设备的序列号、功能名称/代码和一些秘密盐连接起来,然后使用 SHA1(或其他安全散列算法)对结果进行散列。设备将给定的哈希值与为每个功能生成的哈希值进行比较,如果找到匹配项,则启用该功能。

顺便说一句,为了减少字符计数,我建议在哈希传递之后使用 base64 作为编码。

SHA-1 看起来是最好的方法。但是,我从 SHA-1 密钥的示例输出中看到的是它们很长(40 个字符)。如果我取 40 个字符的结果并截断除最后 16 个字符之外的所有字符,我会获得足够的结果吗?

通常,截断哈希不是一个好主意,它们旨在利用输出的所有长度来提供良好的安全性和抗冲突性。不过,您可以使用 base64 而不是十六进制字符来减少字符数,它将从 40 个字符减少到 27 个。

Hex:    a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
Base64: qUqP5cyxm6YcTAhz05Hph5gvu9M

---编辑---

实际上,@Nick Johnson 以令人信服的论点声称,散列可以被截断而不会产生重大的安全隐患(显然会增加你丢弃的每一位发生两次冲突的机会)。

您还应该使用HMAC,而不是天真地将密钥添加或附加到哈希中。根据维基百科:

HMAC 规范的设计是由 攻击将密钥与哈希组合的更简单的机制 功能。例如,可以假设与 HMAC 相同的安全性 提供可以通过 MAC = H(key ∥ message) 来实现。然而,这 方法有一个严重的缺陷:对于大多数散列函数,它是 在不知道密钥的情况下轻松将数据附加到消息并获取 另一个有效的 MAC。另一种方法是使用 MAC = 附加密钥 H(message ∥ key),遇到的问题是攻击者可以 在(未加密的)散列函数中找到一个冲突 在 苹果电脑。使用 MAC = H(key ∥ message ∥ key) 更好,但是各种 安全文件表明这种方法存在漏洞, 即使使用了两个不同的键。

有关此和长度截断的安全影响的更多详细信息,请参阅RFC2104 的第 5 节和第 6 节。

【讨论】:

  • 这是一个可能的解决方案,但是,我有点好奇是否有一个更简单的解决方案,即完整的 SHA-1 哈希实现。如果这很简单并且仍然满足我的要求,我可以接受这个答案。但是,我必须编写自己的 SHA-1 实现。
  • 这是一个很好的答案。我要指出的是,散列函数的选择并不是那么重要,只要它在密码学上相当安全。
  • @RLH:我认为您不需要编写 SHA-1 实现,在许可的开源许可下,有大量现成的 C 实现。
  • 使用 RFC3174 中的参考实现怎么样?它是便携式 C。
  • @MatteoItalia 我一般同意,但加密哈希的一个基本属性是它们分布良好。如果哈希的给定子集可以比暴力破解更快,那么哈希本身就会被破坏。有关实践中的示例,请参阅 RFC 4226 - HOTP。
【解决方案2】:

一种选择是使用 Matteo 描述的哈希。

另一个是使用分组密码(例如 AES)。只需选择一个随机 nonce 并使用您的序列号作为计数器调用 counter mode 中的密码。

当然,这会使密钥可逆,这可能是也可能不是理想的属性。

【讨论】:

    【解决方案3】:

    您可以使用Xorshift random number 生成器生成唯一的 64 位密钥,然后使用您想要的任何方案对该密钥进行编码。如果使用 base-64,则密钥长度为 11 个字符。如果使用十六进制编码,则密钥长度为 16 个字符。

    Xorshift RNG 基本上只是一个位混合器,并且有些版本的保证周期为 2^64,这意味着它保证为每个输入生成唯一值。

    另一种选择是使用线性反馈移位寄存器,它也会为每个不同的输入生成一个唯一的数字。

    【讨论】:

    • 使用非加密安全的 PRNG 生成密钥是一个坏主意,并且会允许可以观察多个密钥的攻击者生成自己的密钥。从您的回答中也不清楚您将如何验证生成的密钥。
    猜你喜欢
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2012-10-15
    相关资源
    最近更新 更多