每天一道Java题[1]
问题:char[]与String相比,有什么优胜的地方?
回答:
针对安全保密高的信息,char[]比String做得更好。因为String是不可变得,即使你修改原先的变量,实际上也是在内存中新建一个对象,原数据还是保留在内存中,等待回收。而char[]中的元素是可以更改的。这就意味着,如密码等保密信息用完之后,你可以马上修改它而不能痕迹。从而相对于String有更好的安全性。可从下面例子中看出,char[]变更内容后,仍是那个对象。而String已经不是原来的String了。
引用:
这个对比,在知乎中这个贴有非常好的回答,我把它引用在下面:
作者:知乎用户
链接:https://www.zhihu.com/question/36734157/answer/68767786
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原答案
=====================
图里说的很清楚,虽然String加载密码之后可以把这个变量扔掉,但是字符串并不会马上被GC回收,一但进程在GC执行到这个字符串之前被dump,dump出的的转储中就会含有这个明文的字符串。
那如果我去"修改"这个字符串,比如把它赋一个新值,那么是不是就没有这个问题了?
答案是否定的,因为String本身是不可修改的,任何基于String的修改函数都是返回一个新的字符串,原有的还会在内存里。
对于char[]来说,你可以在抛弃它之前直接修改掉它里面的内容,密码就不会存在了。但是如果你什么也不做直接交给gc的话,也会存在上面一样的问题。
有的大神说这个是毫无根据的扯淡
这些所谓的大神应该没有什么安全方面的常识,这非常普遍。
FAQ
======================
1. 这种做法意义有多大?
如果没有及时清空而由GC来清除的话,暴露窗口大约是秒这个数量级,如果能够在计算HASH后立即清除,暴露窗口大约是微秒数量级。如此简单的设计就可以降低如此多的被攻击概率,性价比是非常高的。
2. 如何使用反射来修改String? 和修改char[] 相比,有何区别和风险?
通过reflection机制可以查看String的内部的内存成员,从而可以直接修改其中的数据区。但是这样的做法会有问题,内部化的String为了提高HASH速度,节省空间,值相同的字符串通常只有一个实例。
你自己的char[],修改它是没有副作用的。但是String里的char[],很可能是多个String所共享的,你改掉它就会殃及别的String。举个例子,有一个密码是"Password",而你密码框提示密码输入的文字也是"Password",改掉第一个"Password"会把后面那个也改掉。
3. 如果一点明文也不想出现,应该怎么做?
为了保证"全部处理流程均无明文密码",需要底层API在给你密码之前就做了HASH,并且这个HASH算法就是你想要的那种。最好还加盐。不过这只是在用户程序方面无明文,底层获取中会不会有明文就保证不了了。
4. 有没有绝对安全策略?
安全往往是相对于攻击成本而言的,攻击收益越高,黑客就越能接受攻击成本高的方案。因此,你采取的安全策略应该与这个攻击收益相匹配。对于极其敏感和宝贵的数据来源,就需要在安全方面上下很大功夫。目前来看,没有绝对的安全,只有相对的安全。