关于安全性:jBCrypt与checkpw有关的严重问题(是否应该返回true?

jBCrypt serious issue with checkpw (return true when it shouldn't?)

编辑:好的,所以我在这里找到了答案。BCrypt说,很长一段时间,类似的密码是等效的-我,gem或密码学领域有问题吗?

但是,这是一个新问题,如果在我们试图教育用户选择越来越复杂的密码(甚至密码)的世界中,如果您必须限制用户的密码长度,那么有人建议使用bCrypt进行哈希运算,说您的密码必须短于n个字符似乎是一种结束于thedailywtf.com星期五屏幕截图的方法:)

以下是原始问题:

我正在为应用程序重构旧的登录页面,并决定使用JAVA实现jBCrypt(http://www.mindrot.org/projects/jBCrypt/)来给bCrypt一个旋转,并遇到了一个主要的显示停止器。

问题是checkpw方法,使用长种子时似乎总是返回true。我将使用{InternalSalt} {username} {password}设置用户密码,然后使用bCrypt对其进行哈希处理。

所以我有以下代码(尽可能将其剥离以隔离checkpw)。

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
public static void main(String[] args) {
    String plaintext ="jw~ct/f61y1m7q458GiLVQpiqDK|8kG=d368Id:D@$^_80I{qrn1HM6423{FtestAccountO1nu3jKN";

    String pw_hash = BCrypt.hashpw(plaintext, BCrypt.gensalt());

    if (BCrypt.checkpw("jw~ct/f61y1m7q458GiLVQpiqDK|8kG=d368Id:D@$^_80I{qrn1HM6423{FtestAccountO1nu3jKN", pw_hash))
        System.out.println("It matches");
    else
        System.out.println("It does not match");

}

}

这将按要求打印" It match"。

我遇到的问题是说您在传递给checkpw的密码中添加了aaa

BCrypt.checkpw(" jw?ct / f61y1m7q458GiLVQpiqDK | 8kG = d368Id:D @ $ ^ _ 80I {qrn1HM6423 {FtestAccountO1nu3jKNaaa",pw_hash)

它仍然返回true!不完全是我的期望。我在文档中没有看到任何密码长度限制,但是无法使用较小的密码种子来重现它,而且看起来如果我修改了除字符串末尾以外的任何内容,它会按预期返回false。

我错过了重要的事情吗?我知道我一定不是在这些论坛上唯一使用jBcrypt的人,因为我在做一些研究时在许多帖子中都看到了BCrypt的建议。

编辑:Windows 7 64位-Java(TM)SE运行时环境(内部版本1.6.0_24-b07)


好的,这样的措辞使我有足够的能力来真正弄清楚我要寻找的东西(橡皮鸭的欢呼声)。密码学领域现在是安全的!

BCrypt使用P_orig进行XOR,它是18个4个字节的整数,直到结束为止,这将您的加密"密钥"限制为72个字节。 72个字节后的Eveyrything将被忽略(警告会很好)。

似乎可以接受的折衷办法不是将用户密码限制为72个字符或更少,而只是让其静默通过。无论如何,背后的想法是使用72个字符的bCrypted密码比快速哈希替代方法更好。

资料来源:BCrypt说,很长一段时间,类似的密码是等效的-我,gem或密码学领域有问题吗?


实际上,您自己的答案很棒,并帮助我找到了令人讨厌的问题;)对于在哈希之前向普通用户添加某种应用程序秘密的人(即使他们限制了密码长度),有一些技巧:特别是在最后添加应用程序秘密如果应用程序的机密长度为72个字符-否则每次匹配都会返回true

所以与其:

String hashed = BCrypt.hashpw(APP_SECRET + plain, BCrypt.gensalt())

采用:

String hashed = BCrypt.hashpw(plain + APP_SECRET, BCrypt.gensalt())

即使发生Bcrypt的裁剪,checkpw结果也将有效!