22

在 Java 中,存储秘密(例如密码)的旧方法是使用char[],因为您可以在完成后覆盖其数据。然而,这已被证明是不安全的,因为垃圾收集器会在重组堆时复制东西。在某些体系结构上,可能会释放一个页面,而当其他一些程序分配同一页面时,秘密将保留。

这非常难看,但是如果秘密存储在线程run方法的堆栈中呢?仍然需要注意优雅地终止线程,以便它可以将其数据归零,但这个问题也以旧方式存在。

我立即看到的一个主要问题是,我想不出一种安全的方法来将数据进出容器。您可以通过使用具有非常小的内部缓冲区的流来最大限度地减少泄露秘密的可能性,但最终您会遇到与char[]. [编辑:一个private static byte成员和一个标志会起作用吗?尽管这会将您限制为每个 ClassLoader 一个秘密。这增加了更多的丑陋,但隐藏在编写良好的界面后面可能很容易。]

所以我有很多问题,真的。

对于这些类型的攻击,堆栈是否比堆更安全?是否有任何纯 Java 机制以对这个问题有用的方式在两个不同的堆栈帧之间执行堆栈到堆栈的复制?如果没有,JVM 甚至会支持字节码中的这种类型的操作吗?

[编辑:在人们担心太多之前,这更像是一个思想实验。我绝对无意“在生产中测试”或在任何当前项目中使用它。我意识到我正在谈论的内容非常丑陋,可能非常庞大,并且与整个 JVM 结构相悖。我只是对它是否可能、它是否真的实现了我的目标以及实现它需要什么样的英雄主义感兴趣。]

4

1 回答 1

12

我会使用直接的 ByteBuffer。它使用的内存不会被复制,并且在 ByteBuffer 的生命周期内只在一个地方。顺便说一句,不要使用 clear() ,因为这只会重置位置。你可以用

bb.clear();
while(bb.remaining() >= 8) bb.putLong(0);
while(bb.remaining() > 0) bb.put((byte) 0);

对于这些类型的攻击,堆栈是否比堆更安全?

我不会这么认为。

是否有任何纯 Java 机制以对这个问题有用的方式在两个不同的堆栈帧之间执行堆栈到堆栈的复制?

您可以将秘密存储为一个或两个longs。

如果没有,JVM 甚至会支持字节码中的这种类型的操作吗?

字节码是为支持 Java 而设计的,其功能与您在 Java 中的功能相比几乎没有什么区别。

我只是对它是否可能感兴趣,它是否真的实现了我的目标,以及实现它需要什么样的英雄主义

按照我的建议,使用直接的 ByteBuffer。;)

于 2013-05-22T16:51:28.707 回答