使用JVM的GuardedString和内存持久性

问题描述 投票:1回答:1

上下文

我最近有一个加密讲座,我们讨论了关于内存中关键元素的持久性。通常,C / C ++库Libsodium建议清除任何包含敏感信息的缓冲区,例如秘密(ref)。我知道GuardedString是由一个字节数组支持的,文档建议在不再使用存储的密码后调用方法dispose,使用Arrays.fill填充字节数组。

JVM是否保证在覆盖时字节数组的值消失,或者在某些条件下原始值是否保留在内存中?例如,在Java字符串池中保留未使用/未引用的Strings,直到触发垃圾收集。是否有类似的缓存或其他类型的机制,如字节数组,可以破坏应该从GuardedString处置的秘密? JVM规范中的任何引用?

非常感谢 !

java cryptography jvm internals
1个回答
1
投票

在Java中,通常会使用char[]数组而不是String,因为这允许手动将数组中的数据归零。

然而,即使这样,根据this answer,数据也可能没有完全取消:

正如评论中所指出的那样,垃圾收集器移动的数组可能会将数据的杂散副本留在内存中。我相信这是特定于实现的 - 垃圾收集器可以清除所有内存,以避免这种情况。即使它确实存在,仍然有时间char []包含实际字符作为攻击窗口。

如果编译器决定优化memset,则在C / C ++中存在类似的问题。根据11.4. Specially Protect Secrets (Passwords and Keys) in User Memory

Andy Polyakov(2002年11月7日)发布的Bugtraq帖子报道,C / C ++编译器gcc版本3或更高版本,SGI MIPSpro和Microsoft编译器消除了对memset的简单内联调用,旨在覆盖机密。这是C和C ++标准所允许的。其他C / C ++编译器(例如gcc小于版本3)在所有优化级别保留了对memset的内联调用,表明该问题是特定于编译器的。简单地声明目标数据是易失性的并没有帮助所有编译器; MIPSpro和Microsoft编译器都忽略了简单的“挥发”。简单地“触摸”秘密数据的第一个字节也无济于事;他发现MIPSpro和GCC> = 3只巧妙地使第一个字节无效并保持其余部分完整(这实际上非常聪明 - 问题在于编译器的聪明性正在干扰我们的目标)。

© www.soinside.com 2019 - 2024. All rights reserved.