Java控制台;readPassword,数组如何保护密码值不被确定?

11

我在一本Java认证书中读到了关于java.io.Console类的内容,可能我错过了之前章节的一些基础知识,但能有人解释以下吗?

文中提到readPassword方法返回一个字符数组而不是字符串,以防止潜在的黑客找到该字符串并找到密码。

字符数组为什么更安全?如果您可以获取数组中的值,那么难道您不能创建一个脚本来循环尝试各种组合,最终还是会找到密码吗?

3个回答

13

来自文档

控制台对象通过其readPassword方法支持安全密码输入。该方法以两种方式帮助保护密码输入。首先,它抑制了回显,因此密码不会显示在用户的屏幕上。其次,readPassword返回一个字符数组而不是字符串,因此密码可以被覆盖,一旦不再需要,便从内存中删除。

这里的想法是,您可以调用Arrays.fill(或等效方法)来“清空”char数组,一旦验证了密码,从那时起,密码将不再存储在内存中。由于字符串是不可变的,所以字符串将一直存在于堆中,直到被垃圾收集 - 如果它成功地使自己成为国际化字符串,则永远不会被收集,否则在任何其他情况下仍可能“太长”。 在此期间,它可能容易受到各种向量的嗅探攻击。


4

这是一种最佳实践。虽然看起来并没有太多意义,但我们之所以这样做是为了让生活更轻松。

如果密码在内存中,缓冲区读取溢出可能会导致密码被读取。或者它可能保存在核心转储或休眠映像中。使用可变的char[]允许数据在一个希望很窄的时间窗口之后被销毁,只要它没有被复制到字符串中,复制到其他地方,它可能在缓冲区中,垃圾收集器喜欢移动对象等等。

在Swing中有一个有趣的例子,JPasswordField提供了一种char[]读取数据的方式,但例如如果它有一个操作监听器(这是非常常见的使用方式),它将从数据创建一个String


2

字符串是一个不可变的类,当密码存储在字符串中时,您无法控制其生命周期,这意味着它可能长时间存在于内存中(即使它没有被interned,它也会一直存在于内存中,直到JVM退出),并且可能受到内存转储等影响。当密码存储在字符数组中时,您可以清除该数组,从而在验证密码后从内存中删除密码。


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