Tag: char

为什么字符[]优先于字符串的密码?

在Swing中,密码字段有一个getPassword()(返回char)方法,而不是通常的getText()(返回String)方法。同样,我遇到了一个不使用String密码处理的建议。 为什么String在涉及密码时对安全构成威胁?使用感觉不方便char。  答案 字符串是不可变的。这意味着一旦你创建了String,如果另一个进程可以转储内存,就没有办法(除了反射),你可以在垃圾收集开始之前摆脱数据。 使用数组,您可以在完成数据后明确清除数据。你可以用你喜欢的任何东西覆盖这个数组,甚至在垃圾收集之前密码也不会出现在系统的任何地方。 所以是的,这是一个安全问题 – 但即使char只使用也能减少攻击者的机会之窗,而且这只是针对这种特定类型的攻击。 正如注释中指出的那样,垃圾收集器移动的数组可能会将数据的杂散副本留在内存中。我相信这是针对特定实现的 – 垃圾收集器可能会清除所有内存,以避免这种情况。即使这样做,仍然存在char将实际字符作为攻击窗口的时间。 虽然其他建议似乎有效,但还有一个很好的理由。很简单,String你有更高的机会将密码意外地打印到日志,监视器或其他不安全的地方。char不太脆弱。 考虑这个: public static void main(String args) { Object pw = "Password"; System.out.println("String: " + pw); pw = "Password".toCharArray(); System.out.println("Array: " + pw); } 打印: String: Password Array: [C@5829428e 引用官方文档时,Java密码体系结构指南中提到了密码char与String密码(关于基于密码的加密,但这更一般地涉及密码当然): 将密码收集并存储在类型的对象中似乎是合乎逻辑的java.lang.String。然而,这里需要注意的是:Objects的类型String是不可变的,也就是说,没有定义的方法可以让你改变(覆盖)或者String 使用后的内容为零。此功能使String对象不适合存储安全敏感信息(如用户密码)。您应该始终将安全敏感信息收集并存储在 char数组中。 Java编程语言4.0版安全编码指南的准则2-2也提到了类似的内容(尽管它最初是在日志记录的上下文中): 准则2-2:不要记录高度敏感的信息 一些信息,如社会安全号码(SSN)和密码,非常敏感。这些信息的保存时间不应超过必要的时间,即使是管理员也不能保存。例如,它不应该被发送到日志文件,并且它的存在不应该通过搜索被检测到。一些瞬态数据可能保存在可变数据结构中,如char数组,并在使用后立即清除。清除数据结构会降低典型Java运行时系统的效率,因为对象会透明地移动到程序员的内存中。 本指南还对实施和使用不具备所处理数据的语义知识的低级库有影响。作为一个例子,一个低级别的字符串解析库可能会记录它所处理的文本。应用程序可以解析一个SSN与库。这创造了SSN可供管理员访问日志文件的情况。 字符数组(char)可以在使用后通过将每个字符设置为零而不是字符串来清除。如果某人可以以某种方式查看内存映像,那么如果使用了字符串,他们可以以纯文本形式查看密码,但如果char使用了,则在用0清除数据后,密码是安全的。 有些人认为,一旦你不再需要密码,你就必须重写用来存储密码的内存。这减少了攻击者从您的系统读取密码的时间窗口,并完全忽略了攻击者已经需要足够的访问权来劫持JVM内存的事实。有这么多访问权限的攻击者可以捕获你的关键事件,使其完全无用(AFAIK,所以如果我错了,请纠正我)。 更新 感谢评论我必须更新我的答案。显然有两种情况可以增加(非常)小的安全性改进,因为它减少了密码可能落在硬盘上的时间。尽管如此,我认为这对大多数用例来说都是过度的。 您的目标系统可能配置错误,或者您必须假定它是,并且您必须对核心转储产生偏执(如果系统不是由管理员管理,则可能是有效的)。 您的软件必须过分偏执,以防止攻击者访问硬件时发生数据泄露 – 使用诸如TrueCrypt(已停用),VeraCrypt或CipherShed等软件。 如果可能,禁用核心转储和交换文件将处理这两个问题。但是,他们需要管理员权限,并且可能会减少功能(使用较少的内存),并从正在运行的系统中提取RAM仍然是一个值得关注的问题。