如何从内存中 'Zero out' Java 中的 AES SecretKeySpec 密钥

how to 'Zero out' from memory an AES SecretKeySpec Key in Java

我正在使用 Java AES 加密

SecretKeySpec(byte[] key, String algorithm) 

生成Key对象。

加密后,我想从内存中删除密钥。

我可以删除对密钥的所有引用,但这并不能保证密钥不会漂浮在内存中的某个地方。

我可以 "zero out" 我用来生成密钥的 byte[] 数组,但我怎样才能清零或清除实际密钥内存。

在 Java 版本 7 中似乎没有办法执行此操作,但已通过添加 Destroyable 接口为 Java 8 修复此问题。

https://bugs.openjdk.java.net/browse/JDK-6263419

Addess this requirement by enhancing java.security.PrivateKey and javax.crypto.SecretKey classes to extend the javax.security.auth.Destroyable interface.

但是,请注意评论:

clearing out a BigInteger or byte[] reference doesn't guarantee that the sensitive information is gone from memory. The operating system's virtual memory may have been swapped to disk, for example, leaving a copy on the local hard drive. In addition, the Java runtime VM may itself have multiple internal copies of the information.

另请注意,将原始字节数组清零不会清除 SecretKeySpec,因为它需要字节数组的副本 in its constructor

但是,您可以使用 Java Reflection 更改对该字段的访问权限来访问字节数组的 SecretKeySpec 副本(即使它是私有的)。

如果 Java 8 不可用,您需要发挥一点创意。即,为工作选择正确的工具。在这种情况下,我建议使用 C。C 使您可以完全访问 actual 内存; Java 将几乎所有这些都从你身上抽象出来。所以解释如下:

  • 获取对象的内存地址。这可以使用 this code.
  • 使用此内存地址,将其传递给 C 程序。然后你可以 create a variable at that memory address.
  • 手动清零内存地址。

正如评论中所指出的,出现了更多的实现级别细节。这个答案的重点是强调其他语言在这方面做得更好,可能值得研究。