可以用java在堆栈上存储机密吗?

可以用java在堆栈上存储机密吗?,java,security,memory,jvm,java-bytecode-asm,Java,Security,Memory,Jvm,Java Bytecode Asm,在Java中,存储密码等机密的旧方法是使用char[],因为当您使用完它时,您可以覆盖它的数据。然而,这已经被证明是不安全的,因为垃圾收集器在重新组织堆时会复制东西。在某些体系结构上,当其他程序分配同一页时,可能会释放该页,并且保留秘密 这非常难看,但是如果秘密存储在线程的run方法的堆栈上呢?仍然需要谨慎地终止线程,以便它可以将其数据归零,但这个问题也是以旧的方式出现的 我马上看到的一个主要问题是,我想不出一种安全的方法来进出容器中的数据。通过使用具有非常小的内部缓冲区的流,可以最大限度地降低

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

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

我马上看到的一个主要问题是,我想不出一种安全的方法来进出容器中的数据。通过使用具有非常小的内部缓冲区的流,可以最大限度地降低泄露机密的可能性,但最终会遇到与
char[]
相同的问题。[编辑:一个
私有静态字节和一个标志是否有效?尽管这会限制每个类加载器只能有一个秘密。这会增加更多的丑陋,但可能很容易隐藏在一个编写良好的接口后面。]

所以我有一大堆问题,真的

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


[编辑:在人们担心太多之前,这更像是一个思想实验。我绝对无意“在生产中测试”或在任何当前项目中使用它。我意识到我所说的东西真的很难看,可能非常笨重,而且对整个JVM结构都起作用。我只是对我感兴趣n是否可能,它是否真的实现了我的目标,以及需要什么样的英雄才能实现。]

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

bb.clear();
while(bb.remaining() >= 8) bb.putLong(0);
while(bb.remaining() > 0) bb.put((byte) 0);
堆栈是否比堆更安全地抵御这些类型的攻击

我不这么认为

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

您可以将秘密存储为一个或两个
long
s

如果不是,JVM会支持字节码中的这种类型的操作吗

字节码是为支持Java而设计的,它所做的工作与Java中所能做的相比几乎没有什么不同

我只是想知道这是否可能,它是否真的实现了我的目标,需要什么样的英雄才能实现


如我所建议的,使用直接的ByteBuffer。

如果你合理地担心攻击者访问这样的数据,那么不管怎样,你都有可能被抓到,因为任何一个在这个级别上足够复杂的攻击者都足够复杂,足以破坏你能扔给他们的任何东西。原则上我同意,但在关闭威胁方面,这是一个非常糟糕的论点。无论哪种方式,我都是在审查客户提供给我的安全要求列表时开始这样做的。一个是我们总是将内存中的秘密归零。如果不这样做,将被审查的客户抓住。客户足够聪明,能够理解
char[]
不起作用,但他们也要求我们使用Java。幸运的是,他们是通情达理的人,他们认识到冲突,这不是一个太大的问题。但这让我想到…反对关闭威胁的理由非常糟糕*-抱歉,编辑时间期限已过。不是真的;英勇的保护工作有投资回报率,更多的时候是这样n比I小得多。不考虑投资回报率是愚蠢的,在这个层面上,这是至关重要的。在许多(大多数)情况下,金钱和时间是完全可以忽略特定类型威胁的理由。我们过去常常对芯片进行去帽,并用逻辑分析仪将它们聚集在一起,以捕获基本上所有的系统行为(知识产权盗窃调查)--如果你正在和一个能在这个级别上闲逛的人打交道,你很可能已经输了。不要认为这意味着这不是一个有趣的问题,我只是认为在你编辑解释这是一个智力练习之前,这种级别的篮球几乎是不值得的。为了这个级别的安全,使用专门的硬件。“它使用的内存没有被复制…”-它不是在内部使用
byte[]
吗?它存储在堆上,与任何其他数组(如上面提到的
char[]
一样)一样容易被GC进行堆重组。一个heap ByteBuffer使用一个byte[],直接ByteBuffer使用本机内存。本机内存不受gc的影响。类文档中指定的契约是JVM将尝试避免将数据复制到中间缓冲区。即使在C中,也不能保证寄存器不会写入内存。也不能保证我不会只从物理上读取寄存器。