Java将敏感“密钥”存储为String还是char[]?

13

可能存在重复:
为什么比起 String,char[] 更适合用于存储密码?

我曾经看到过一个观点,认为将敏感的密码等秘钥存储为 char[] 而非 String 更安全,因为后者可能会留存在内存中。这个观点似乎有点道理,也由于 JPasswordField 的 getText() 方法已被弃用。

这是真的吗?


2
FYI:String 将其内容存储为 char[] - Radu Murzea
2
@SoboLAN 是的,String 基本上就是内部有一个 char[],但我们可以改变声明为 char[] 的变量中保存的单个字符,而不能对 String 对象中保存的字符进行修改,仅仅将指向 String 的变量置空并不能保证它会被垃圾回收器删除。即使删除了 String,也不能保证该 String 使用的内存很快就会被覆盖。 - Bobulous
@user1515834,我的意思是:如果你查看RAM内部,那么Stringchar[]看起来是一样的。因为它们基本上是相同的。对于黑客来说,这不会有太大的区别。至于更改char[]内容与垃圾回收String的立即变化:是的,你是正确的。 - Radu Murzea
1个回答

14
一旦您在char[]中使用密码后,可以随时用0或随机值覆盖它。但是,您不能使用String对象进行覆盖,因为Java中的字符串是不可变对象,直到垃圾回收器启动并清除它们之前,它们一直存在。
http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html上有一个有趣的注释。
我们从用户那里提示一个密码,然后生成加密密钥。 收集和存储密码的类型为java.lang.String的对象似乎是合理的。但是,需要注意的是:String类型的对象是不可变的,即没有定义允许您在使用后更改(覆盖)或清零字符串内容的方法,这使得String对象不适合存储安全敏感信息,例如用户密码。您应始终使用char数组来收集和存储安全敏感信息。因此,javax.crypto.spec.PBEKeySpec类将(并返回)密码作为char数组。

谢谢,你讲解得非常好! - LanguagesNamedAfterCofee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接