使用BCrypt和char

几个小时前,我在Stack Overflow上询问了如何将char []转换为MD5哈希的方法。 提供了一个解决方案,但被认为是不安全的 – 正如几个人所概述的那样: 使用char []生成MD5哈希

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?

提前致谢!

我发现的两个Java impel都是一个String作为输入。 您似乎知道,将密码放入字符串可以打开内存攻击。

您可以使用PBKDF2以及bcrypt。 两者都被认为是一流的。 这里和这里有PBKDF2 Java代码示例。 两者都允许将char[]传递给函数。

要回答注释中的隐含问题,不使用MD5或任何哈希的原因是它们太快了。 可以使用特殊硬件强制执行密码。 Bcrypt和PBKDF2设计得很慢。

即使你打算使用哈希(我建议反对),你也必须加盐。 反转未加密的密码哈希是微不足道的(请参阅此工具 )。

CrackStation对密码存储的参考是一个很好的一般参考。

因此,根据https://github.com/jeremyh/jBCrypt中提供的实现,您需要更改hashpwcheckpw方法以接受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 ,但我们试图避免这种情况。 相反,基于从转换char []到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帐户,您实际上可以克隆原始仓库,进行建议的更改并生成拉取请求。 我个人会想要摆脱需要Stringcheckpwhashpw方法

我也发现了PDKDF2的这个实现,它使用了String ,但后来迅速将它转换为char[] …所以,这很简单就是改变……

对你的问题的简短回答: 是的 ,可以在Java中使用char[]和BCrypt。

用于Java的Bouncy Castle加密包在1.52版(2015年3月)中添加了BCrypt密码散列算法(使用OpenBSD上的参考实现的String格式和Base64编码), 并且它仅支持char[]密码

可以在org.bouncycastle.crypto.generators中找到生成BCrypt字符串的相关方法。 OpenBSDBCrypt类并具有以下签名:

 String generate(char[] password, byte[] salt, int cost) 

如果您想在源代码中validationchar[]被保留而不转换为String,则相关的类是OpenBSDBcrypt , Strings和BCrypt 。