我需要在 Java 中生成一个随机的 SecretKey,我将能够在未来的某个时候重新生成它。这个想法是这个 key 对于创建它的机器是唯一的并且不存储在任何地方。我正在尝试这样的事情:
KeyGenerator keyGen = KeyGenerator.getInstance("DESede");
String hostname = InetAddress.getLocalHost().getHostName();
SecureRandom random = new SecureRandom(hostname.getBytes());
keyGen.init(random);
secretKey = keyGen.generateKey();
显然,这不起作用,因为设置 SecureRandom 的种子并不像我想象的那样起作用,而且我每次都得到一个不同的 SecretKey。也许我正在尝试的东西永远不会奏效(我知道想要做这件事看起来很奇怪......)但如果有办法,如果有人能告诉我那是什么,我将不胜感激!
最佳答案
有两种以编程方式保护 key 的方法:
- 将 key 本身保密,或者
- 对算法保密。
密码学家(和常识)会告诉您,在这两种方法中,第二种方法的安全性要低得多,因为它相对容易对代码进行逆向工程。所以你只剩下第一种方法了。
如果我没看错您的要求,您需要一把 key
- 保证每台机器都是唯一的。
- 随机。
- 不存储在任何地方。
- 可重现(通过您的软件)。
但要满足所有这些是不可能的。例如,无法随意复制未存储在任何地方(作为数据或嵌入算法中)的真正随 secret 钥。因此,如果我可以留出一些余地,我会阅读您的用例并替换这些不太严格的要求:
- 绑定(bind)到主机:一台机器上的 key 不能在另一台机器上使用。
- 安全:不太可能被复制、猜测、逆向工程等。
- 安全:不太可能在您的程序中被发现。
- 可重现:您的应用程序必须能够根据需要重新生成 key 。
所有这些新要求,除了 #3 之外,都可以通过此过程得到满足:
- 生成将在每台机器上使用的 secret 随机种子。
- 选择每个主机唯一的依赖于机器的签名,并将其附加到种子。经典示例是 MAC 地址,但在具有两个或多个 NIC 的计算机上,您必须小心每次都使用相同的 NIC!
- > Hash算法(如 SHA)的结果将生成相当独特且不可逆的结果。
现在剩下的就是满足第三个要求,让攻击者相当难以猜测必须保密的一项:种子。这就是这个过程更像是一种宗教争论而不是技术争论的地方,因为“相当困难”取决于攻击者想要发现 key 的严重程度以及他/她成功后的风险。
为了尽可能安全, key 必须存储在您的应用程序之外,例如在您的大脑中,并在每次需要时提供。但一般来说,某种形式的较弱的通过模糊的安全机制是可以接受的;我最喜欢的方法之一是使用像 0x%-6.2d
这样的格式,它很可能被忽略为 printf()
格式。如果您有疑虑,请将其分段存储并在您的应用程序中与 key 处理模块无关的部分重新创建。
如果您需要更具体的建议,请告诉我们更多关于您的应用程序及其用例的信息。
祝你好运!
关于java - 两次生成相同的随机 SecretKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1519435/