1

在 Java 中,当有需要安全处理的对象时,有哪些选项?

考虑到:

a) The when:您需要对对象何时被处理的一些保证。调用 System.gc() 是唯一/更好的选择吗?

b) how : GC 是不够的,您需要确保对象实例正在使用的内存被正确擦除。可以首先通过反射获取对内部对象表示的引用(在字符串中获取 char[])并覆盖数据。但是,此方法需要对每种类型的对象进行实现。

有没有更好的方法来确保密码和私钥对象不会留在 RAM 上?

更新:密码就是一个例子。这个问题的重点是对象安全销毁的一般方法。想想 BigInteger、PGPPrivateKey、RSAWhatever 等。

4

3 回答 3

2

免责声明:这使用反射,可能不是最好的方式。

但是,此方法需要对每种类型的对象进行实现。

不,不是。您可以遍历字段并销毁它们,甚至可以遍历整个对象图。第一步是基元和基元数组,并清空作为您尝试“分解”的对象的字段的对象引用。事实上,最后一步可以通过空检查递归地完成。

于 2013-09-09T15:10:59.467 回答
2

我会使用堆外内存,这样它就不会出现在任何堆转储中,也不会被复制(即使你清除 char[],旧副本仍然可以读取)一旦你覆盖它,你就知道在哪里不会在某处成为另一个副本。

堆外内存更难使用,因为您必须处理原语,但很容易将其归零,因为您可以覆盖其中的所有内容。

于 2013-09-09T15:11:44.093 回答
1

你不能依赖垃圾收集来从内存中删除你的对象;调用System.gc()不会导致 gc 运行 - 它只是“很好地询问”。它可以在记忆中徘徊一段时间。

标准方法是使用可以在处置前擦除的对象,例如char[]代替String

char[] password = <read password from input stream etc>
// check password
Arrays.fill(password, 'x');
// password available for gc, but now wiped

这只会减少密码在内存中的时间。它不会消除它。如果有人在正确的时间获得了内存转储,他们也许能够找到字节。如果你很好地保护了你的服务器,那么首先获得转储应该是困难的,甚至是不可能的。

于 2013-09-09T15:12:49.317 回答