【问题标题】:Generating the same random SecretKey twice两次生成相同的随机 SecretKey
【发布时间】:2009-10-05 11:06:13
【问题描述】:

我需要在 Java 中生成一个随机的 SecretKey,我将能够在将来的某个时间重新生成它。这个想法是这个密钥对于创建它的机器是唯一的,并且不存储在任何地方。我正在尝试这样的事情:

KeyGenerator keyGen = KeyGenerator.getInstance("DESede");

String hostname = InetAddress.getLocalHost().getHostName();
SecureRandom random = new SecureRandom(hostname.getBytes());
keyGen.init(random);

secretKey = keyGen.generateKey();

显然,这不起作用,因为设置 SecureRandom 的种子并不像我想象的那样起作用,而且我每次都会得到一个不同的 SecretKey。也许我正在尝试的东西永远不会奏效(我知道这看起来很奇怪……)但是如果有办法,如果有人能告诉我那是什么,我会非常感激!

【问题讨论】:

  • 你想做什么?钥匙有什么用?你能解释一下你的整个环境吗?可能有更好的方法来解决这个问题。

标签: java security random


【解决方案1】:

有两种以编程方式保护密钥的方法:

  • 将密钥本身保密,或
  • 对算法保密。

密码学家(和常识)会告诉您,在两者中,第二个安全性要低得多,因为对代码进行逆向工程相对容易。所以你只剩下第一种方法了。

如果我正确阅读了您的要求,您需要一个密钥

  1. 保证每台机器都是独一无二的。
  2. 随机。
  3. 未存储在任何地方。
  4. 可重现(通过您的软件)。

但不可能满足所有这些。例如,没有存储在任何地方(作为数据或嵌入算法)的真正随机密钥不能随意复制。因此,如果我可以留有余地,我会阅读您的用例并替换这些不太严格的要求:

  1. 与主机绑定:一台机器的密钥不能在另一台机器上使用。
  2. 安全:不太可能被复制、猜测、逆向工程等
  3. 安全:不太可能在您的程序中被发现。
  4. 可重现:您的应用程序必须能够根据需要重新生成密钥。

所有这些新要求,除了#3,都可以通过这个程序得到满足:


  1. 生成将在每台机器上使用的秘密随机种子
  2. 选择每个主机唯一的与机器相关的签名,并将其附加到种子。经典示例是 MAC 地址,但在具有两个或更多 NIC 的机器上,您必须小心每次都使用同一个 NIC!
  3. Hash 使用算法(如 SHA)生成的结果将产生相当独特且不可逆的结果。

现在剩下的就是满足第三个要求,让攻击者相当难以猜测必须保密的一项:种子。这就是这个过程变得更像是宗教争论而不是技术争论的地方,因为“相当困难”取决于攻击者想要发现密钥的程度以及如果他/他成功的话会带来多大的风险。

为了尽可能安全,密钥必须存储在您的应用程序之外,例如在您的大脑中,并在每次需要时提供。但通常某种形式的较弱的安全性通过模糊性机制是可以接受的;我的最爱之一是使用0x%-6.2d 之类的东西,它可能会被忽略为printf() 格式。如果您是偏执狂,请将其分段存储,然后在您的应用程序的一部分中重新创建它,该部分与密钥处理模块无关。

如果您需要更具体的建议,请告诉我们更多关于您的应用程序及其用例的信息。

祝你好运!

【讨论】:

  • 非常感谢,这看起来像是我需要的信息。请放心,我知道我正在做的事情很容易被破解,但我被要求找到一种方法来保护用于保护对我们其余密钥的访问的密码,要求它不应该可以“微不足道”地被发现 - 即不应该偶然发现纯文本形式的密码。
  • 那么您正在寻找一个 KeyStore。 (没有双关语)
【解决方案2】:

即使它确实为您工作,您也不会真正拥有“秘密”密钥 - 您将拥有一个完全可从主机名派生的密钥。这不是秘密——就像每个人都使用自己的名字作为密码一样。任何想要攻击加密数据的人只需要知道创建密钥的机器的名称,然后他们就可以访问。

密钥的最终形式与重新创建它所需的信息几乎无关。为了使密钥有效,该信息基本上必须是秘密的。

【讨论】:

  • 但是他可以用一些盐把它变成私有的吗?或者这不是一个好主意吗?
  • chrsk:嗯,是的,但是在每台机器上,密钥将再次不同。即便如此,这仍然不是一个好主意,因为如果您知道密钥的模式,您将能够非常简单地暴力破解它。
【解决方案3】:

您不能两次生成随机密钥,因为它是随机的。

如果 InetAddress.getLocalHost().getHostName() 对于您的目的来说足够独特,请计算一个哈希值并将其用作键。正如 Jon 所说,任何知道实现的人都可以导出密钥。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    • 2017-07-30
    • 2019-05-21
    相关资源
    最近更新 更多