您的位置:首页 > 其它

String使用上的安全问题: 为什么在密码问题上char[]优先于String?

2014-04-19 23:02 337 查看
1.字符串有一个结束标识符(‘\0’),

比如“学java”的内存空间占6个字符,长度为5(长度不仅结束标识符);

长见识了。之前还没意识这个安全问题。

转载于http://blog.csdn.net/maijunjin/article/details/21925309


问题

Swing中,密码域(JPasswordField)用
getPassword()
函数(用来返回
char[]
)取代
getText()
函数(返回字符串)。在工作中我得到类似的建议是不要用字符串去处理密码相关的问题,为什么涉及到密码问题时字符串会对安全构成威胁呢?(译注:这是提问者在Stackoverflow提了问题,他觉得用char[]处理密码并没有String方便,但为什么还要推荐使用char[]处理呢?下面是几个比较精彩的回答)。


Why
is char[] preferred over String for passwords?

In Swing, the password
field has a
getPassword()
(returns
char[]
)
method instead of the usual
getText()
(returns
String
)
method. Similarly, I have come across a suggestion not to use
String
s
to handle passwords. Why does
String
pose
a threat to security when it comes to passwords?

It feels inconvenient to use
char[]
.


回答1

String在Java中是不可变对象,这就意味着一旦创建了一个字符串,如果另一个进程把尝试内存的数据导出(dump),在GC进行垃圾回收之前该字符串会一直保留在内存中,那么该进程就可以轻易的读取到该字符串。

而对于数组,可以在该数组处理它之后再显示地擦掉数组中内容,可以以任何方式把数组内容覆盖掉,即使是GC触发前密码也不会出现在系统的任何地方。

所以,这是从安全角度来选择的,但是即便是用
char[]也只是
降低被攻击的概率而已,还是会有一些特定的手法攻破数组处理的密码。

Strings are immutable. That means once you've created the string, if another process can dump memory, there's no way (aside from reflection) you can get rid of the data before GC kicks in.

With an array, you can explicitly wipe the data after you're done with it: you can overwrite the array with anything you like, and the password won't be present anywhere in the system, even before garbage
collection.

So yes, this is a security concern - but even using
char[]
only reduces the
window of opportunity for an attacker, and it's only for this specific type of attack.

EDIT: As noted in comments, it's possible that arrays being moved by the garbage collector will leave stray copies of the data in memory. I believe this is implementation-specific - the GC may clear
all memory as it goes, to avoid this sort of thing. Even if it does, there's still the time during which the
char[]
contains
the actual characters as an attack window.


回答2

从另一方面来,若是普通的字符串,有时你会不经意间打印密码到日志中或者其他不安全的地方,而char
[] 就没那么显而易见


参考一下这段代码:

输出结果:

While other suggestions here seem valid, there is one other good reason. With plain
String
you
have much higher chances of accidentally printing the password to logs, monitors or some other insecure place.
char[]
is
less vulnerable.

Consider this:
[code]public static void main(String[] args) {
    Object pw = "Password";
    System.out.println("String: " + pw);

    pw = "Password".toCharArray();
    System.out.println("Array: " + pw);
}


Prints:
[code]String: Password
Array: [C@5829428e


回答3

引用官方的文Java加密体系结构指南说到char[]
vs String。在对象
java.lang.String
中收集和存储密码看似符合逻辑,但是字符串对象是不可变的,没有任何方法可以改变(重写)或清空内容。这一特性使得字符串对象不适合存储安全敏感信息,比如用户密码。你应当使用一个字符数组来代替,以便收集和存储安全敏感的信息。安全编码指南4.0也提到了类似的问题。


回答4

字符数组(
char[]
)在使用之后里面的元素可以被清除,字符串并不如此。如果有人能以某种方式看到内存映像,如果字符串被使用了,它们可以以纯文本方式看到密码。但如果是
char[],
 看到的是清除后的数据(用0替换的数据)
,这种方式是安全的。


最后的思考

尽管使用
char[]
并不能保证足够安全,但我也建议使用hash’d或者加密的密码来代替普通的文本字符串密码,而且使用完后立即清除。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐