使用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中提供的实现,您需要更改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
,但我们试图避免这种情况。 相反,基于从转换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帐户,您实际上可以克隆原始仓库,进行建议的更改并生成拉取请求。 我个人会想要摆脱需要String
的checkpw
和hashpw
方法
我也发现了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 。