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

Password security in Java - Converting char[] to String

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

编辑:我知道如何将char数组转换为字符串。问题是字符串是不可变的,因为不能在Java中显式删除对象,所以密码会留在内存中。


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

如果您的意思是要在HttpPost的主体中传递密码,也就是说密码必须在HttpEntity内,那么HttpEntity是一个接口,理论上您可以根据需要实现#getContent()#writeTo(OutputStream),包括将密码一直保持为char数组。不过,要小心编码,因为在没有人泄露char[]副本的情况下将byte[]转换为byte[]是非常重要的。


为了防止堆检查,安全人员会用语言告诉您非常好的安全字符串概念。

我以前是这个的信徒,现在不再相信了。值得注意的是,与.NET相当的SecureString正在逐步淘汰--您只需观看这段精彩的YouTube视频约10分钟,就可以了解其中的原因。这个概念听起来很不错,直到你必须对数据做一些实际的处理,然后很可能你再也不能保证它的安全(就像在你的例子中一样——你需要使用Apache库)。而且,在许多平台上,加密字符串的密钥与字符串本身在相同的内存空间中,因此它实际上比安全性更模糊。另请参见安全堆栈交换讨论。

底线:这是语言中的一个固有问题,您无法做太多的工作来保护它。


使用String.valueOf();

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

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