Java 中的密码安全性 - 将 char[] 转换为字符串



我正在尝试为网站构建一个非官方的api。它将要求用户登录,并且将使用标准 Console.readPassword(( 方法从控制台读取密码。现在,这给了我一个字符数组,但我必须使用 Apache 的 HttpClient 库中的 HttpPost 类通过 POST 请求发送密码。为此,需要字符串,但将密码转换为字符串会产生安全风险。我能做什么?

编辑:我知道如何将字符数组转换为字符串。问题是字符串是不可变的,并且由于您无法在 Java 中显式删除对象,因此密码将保留在内存中。

安全人员会告诉您语言中精彩的安全字符串概念,以防止堆检查。

我曾经相信这一点,现在不是了。 值得注意的是,.Net等价物SecureString正在逐步淘汰 - 你只需要观看这个精彩的YouTube视频大约10分钟就可以了解原因。 这个概念听起来很棒,直到你必须对数据做一些事情,然后很可能你不能再保持它的安全了(就像你的情况一样 - 你需要使用Apache库(。 此外,在许多平台上,加密字符串的密钥与字符串本身位于同一内存空间中,因此它确实比安全性更令人困惑。 另请参阅安全堆栈交换讨论。

底线:这是语言中固有的问题,你无能为力来防止它。

如果您的意思是要在HTTP"基本"身份验证中使用密码,那么从5.0版本开始,Apace HTTP的UsernamePasswordCredentials支持传递char[]

相反,如果您的意思是要在HttpPost正文中传递密码,也就是说它必须在HttpEntity内,HttpEntity是一个接口,理论上您可以根据需要实现#getContent()#writeTo(OutputStream),包括始终将密码保留为 char 数组。不过要小心编码,因为将char[]转换为byte[]而不有人泄露它的副本并不重要。

我的建议是在客户端对输入用户的密码进行哈希处理并将哈希发送到服务器,因为在服务器端存储纯文本密码首先存在安全风险。这个答案列出了在java中散列密码的整个方法,然后在用户登录时使用存储在服务器上的散列对密码进行身份验证。

使用 String.valueOf();

String str = String.valueOf(Console.readPassword());

最新更新