几个小时前,我在Stack Overflow上询问了如何将char []转换为MD5哈希的方法。提供了一个解决方案,但被认为是不安全的 - 正如一些人所概述的那样:Generating an MD5 Hash with a char[]
Neil Smithline建议我使用BCrypt,但我无法使用char []的。
我使用char []存储从登录表单中检索到的密码的原因是因为.getPassword()
仅支持char []。
char[] passwordChars = passwordInputField.getPassword();
String hashed = BCrypt.hashpw(passwordChars, BCrypt.gensalt(12));
目前,我正在尝试使用上面的代码生成哈希,但由于变量passwordCars的类型为char [],BCrypt.haspw()
不支持
现在我没有使用常规字符串的唯一原因是因为它无法从内存中清除。
我现在的问题是 - 是否有可能以某种方式将char []用于BCrypt?
提前致谢!
答案 0 :(得分:4)
因此,根据https://github.com/jeremyh/jBCrypt中提供的实施,您需要更改hashpw
和checkpw
方法以接受char[]
而不是String
可能最困难的部分是hashpw
......
try {
passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
throw new AssertionError("UTF-8 is not supported");
}
最简单的解决方案是将char[]
包裹回String
,但我们会尝试避免这种情况。相反,根据Converting char[] to byte[]得分最高的答案,我们可以做更像......的事情。
char[] expanded = password;
if (minor >= 'a') {
expanded = Arrays.copyOf(expanded, expanded.length + 1);
expanded[expanded.length - 1] = '\000';
}
CharBuffer charBuffer = CharBuffer.wrap(expanded);
ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
passwordb = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
checkpw
方法实际上不需要任何修改(除参数外),因为它使用hashpw
方法检查结果。
所以,测试......
// We want the same salt for comparison
String salt = BCrypt.gensalt(12);
String original = BCrypt.hashpw("Testing", salt);
System.out.println(original);
String hash = BCrypt.hashpw("Testing".toCharArray(), salt);
System.out.println(hash);
System.out.println(BCrypt.checkpw("Testing", hash));
System.out.println(BCrypt.checkpw("Testing".toCharArray(), hash));
...输出
$2a$12$KclXlnca78yhcrg1/mNrRepLYqeJE//SRhrh1X3UM7YUQMjY4x8gy
$2a$12$KclXlnca78yhcrg1/mNrRepLYqeJE//SRhrh1X3UM7YUQMjY4x8gy
true
true
现在,如果您有一个GitHub帐户,您实际上可以克隆原始仓库,进行建议的更改并生成拉取请求。我个人想要摆脱需要checkpw
的{{1}}和hashpw
方法
我还发现了this PDKDF2的实现,它使用了String
,但随后迅速将其转换为String
...所以,这非常简单地改变......
答案 1 :(得分:1)
我发现的两个Java impel都是以字符串作为输入。您似乎知道,将密码放入字符串会让您受到内存攻击。
您可以使用PBKDF2以及bcrypt。两者都被认为是一流的。有PBKDF2 Java代码示例here和here。两者都允许将char[]
传递给函数。
要回答评论中的隐含问题,您不使用MD5或任何哈希的原因是它们太快了。可以使用特殊硬件强制执行密码。 Bcrypt和PBKDF2设计得很慢。
即使您要使用哈希(我建议反对),您也必须加盐。反转未加密的密码哈希值很简单(参见this tool)。
密码存储上的CrackStation's reference是一个很好的一般参考。
答案 2 :(得分:0)
对您的问题的简短回答:是,可以在Java中使用char[]
和BCrypt。
Bouncy Castle crypto packages for Java在版本1.52(2015年3月)中添加了BCrypt密码哈希算法(使用String格式和OpenBSD上参考实现的Base64编码),它只支持{{1}密码。
生成BCrypt字符串的相关方法可以在org.bouncycastle.crypto.generators.OpenBSDBCrypt类中找到,并具有以下签名:
char[]
如果您想在源代码中验证String generate(char[] password,
byte[] salt,
int cost)
是否保留而未转换为字符串,则相关的类为OpenBSDBcrypt,Strings和{{3} }。