在Java中,存储 key (例如密码)的旧方法是使用char[]
,因为使用完后可以覆盖其数据。但是,由于垃圾收集器在重新组织堆时会在周围复制内容,因此已证明这是不安全的。在某些体系结构上,有可能页面将被释放,而当其他程序分配同一页面时, secret 将保留。
这太丑陋了,但是如果 secret 存储在Thread的run
方法的堆栈中怎么办?仍然需要谨慎地优雅地终止线程,以便可以将其数据清零,但是这个问题也以旧的方式出现。
我立即看到的一个主要问题是,我想不出一种安全的方法来将数据进出容器。通过使用具有非常小的内部缓冲区的流,可以使 secret 泄漏的可能性降到最低,但是最终,您将遇到与char[]
相同的问题。 [编辑:一个private static byte
成员和一个标记会起作用吗?尽管那将限制您每个ClassLoader一个 secret 。这增加了更多的丑陋性,但隐藏在编写良好的界面后面可能很容易。
所以我确实有很多问题。
堆栈比堆栈更安全地抵御这些类型的攻击吗?是否有任何纯Java机制以对这个问题有用的方式在两个不同的堆栈框架之间执行堆栈到堆栈的复制?如果不是,JVM甚至会以字节码支持这种类型的操作吗?
[编辑:在人们过于担心之前,这比其他任何事情都更是一种思想实验。 我绝对不打算“在生产中进行测试”或在任何当前项目中使用它。我意识到我所谈论的内容确实很丑陋,可能非常庞大,并且可以与整个JVM结构配合使用。我只是想知道它是否可能,它是否真正实现了我的目标以及实现它需要采取什么样的英勇措施。
最佳答案
我将使用直接的ByteBuffer。所使用的内存不会被复制,并且在ByteBuffer的整个生命周期内仅位于一个位置。顺便说一句,不要使用clear(),因为这只会重置位置。您可以使用覆盖
bb.clear();
while(bb.remaining() >= 8) bb.putLong(0);
while(bb.remaining() > 0) bb.put((byte) 0);
我不会这样。
您可以将密码存储为一个或两个
long
。字节码被设计为支持Java,并且比您在Java中所能做的仅多。
我建议使用直接ByteBuffer。 ;)
关于java - 是否可以在Java中将 secret 存储在堆栈上?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16697117/