BCrypt 性能恶化

2024-01-28

我们在 Jboss 服务器 6.1 中运行三个 Web 应用程序(标准 Spring MVC-Hibernate)。所有三个应用程序共享一个通用的身份验证方法,该方法被编译为 JAR 并包含在每个 WAR 文件中。我们的身份验证方法使用 org.springframework.security.crypto.bcrypt.BCrypt 来散列用户密码,请参见以下内容:

hashedPassword.equals(BCrypt.hashpw(plainTextPassword, salt));

JBOSS 启动选项

set "JAVA_OPTS=-Xms2048m -Xmx4096m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -verbosegc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:gc.txt -XX:+UseParallelOldGC

Problem:看来,当服务器重新启动时,Bcrypt.hashpw 需要 100ms 来解密密码。然而,一段时间后(没有模式),Bcrypt.hashpw 性能突然从 100 毫秒飙升至 10 秒。这没有明显的原因。

更多信息:

  • 休眠版本:4.2.4.Final
  • 春季版本:4.0.5.RELEASE 春季
  • 安全版本:3.2.4.RELEASE

以前有其他人见过这个问题吗?


问题:似乎当服务器重新启动时,Bcrypt.hashpw 会占用 100ms 解密密码。然而一段时间后(没有模式) 突然间,Bcrypt.hashpw 性能从 100 毫秒飙升至 10 秒。 这没有明显的原因。

问题是/dev/random有时会阻塞,当它发生时,它看起来是随机的:)更令人困惑的是,在尝试测试它如何工作时,你会遇到观察者效应,即在尝试观察随机行为时,你会生成熵,这可能会导致大量的混乱,即我的结果不会与你的结果相同等。这也是为什么它看起来没有模式。

我将演示该问题并向您展示如何在您自己的服务器上重新创建它(在合理范围内),以便您可以测试解决方案。我将尝试提供一些修复程序,请注意这是在 Linux 上,但在任何需要熵来生成随机数并用完的系统上都会发生同样的问题。

在 Linux 上/dev/random是随机字节流。当你读到 流你耗尽了可用的熵。当达到某一点时 读取自/dev/random堵塞。您可以使用此命令查看可用的熵

cat /proc/sys/kernel/random/entropy_avail

如果您运行以下 bash 脚本并监控entropy_avail你会 请注意,当 bash 脚本消耗熵时,熵会急剧下降。

while :
do
  cat /dev/random > /dev/null
done

这还应该为您提供有关如何在服务器上重现此问题的提示,即运行上述 bash 脚本以减少可用熵,问题将自行显现。

如果您想查看系统每秒创建多少字节 可以使用pv来测量它,即

pv /dev/random

如果你走pv运行它会产生影响,它会消耗随机字节流,这意味着其他服务可能会开始阻塞。注意pv还显示其输出,因此它也可能会增加系统上的可用熵:)。

在熵很少或没有的系统上使用pv /dev/random会显得非常缓慢。我还经历过虚拟机有时在生成熵方面存在重大问题。

要重新创建问题,请使用以下类...

import java.security.SecureRandom;
import org.mindrot.jbcrypt.BCrypt;
public class RandTest {
    public static void main(String[] args) {
        SecureRandom sr = new SecureRandom();
        int out = 0;
        String password = "very-strong-password-1729";
        String hashed;
        for (int i = 0; i < 200000 ; i++) {
            hashed = BCrypt.hashpw(password, BCrypt.gensalt());
            //If we print, we're generating entroy :) System.out.println(hashed);
        }
    }
}

我将 bcrypt 下载到本地目录。我编译并运行如下

javac -cp ./jBCrypt-0.4/src/   RandTest.java
java  -cp ./jBCrypt-0.4/src/:. RandTest

如果您在运行时运行之前的 bash 脚本RandTest你会看到系统阻塞等待更多熵的大停顿。如果你跑strace你会看到以下内容...

1067 [pid 22481] open("/dev/random", O_RDONLY|O_LARGEFILE) = 12
11068 [pid 22481] fstat64(12, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 8), ...}) = 0
11069 [pid 22481] fcntl64(12, F_GETFD)        = 0
11070 [pid 22481] fcntl64(12, F_SETFD, FD_CLOEXEC) = 0
.....
11510 [pid 22481] read(12, "\320\244\317RB\370", 8) = 6

该程序正在读取/dev/random。测试熵的问题是 您可能会在尝试测试它时生成更多的它,即观察者效应。

Fixes

第一个修复是从使用更改/dev/random to /dev/urandom ie

time java  -Djava.security.egd=file:///dev/./urandom -cp ./jBCrypt-0.4/src/:.  RandTest

另一种修复方法是重新创建/dev/random设备作为/dev/urandom设备。您可以从手册页找到如何执行此操作,即,而不是创建它们......

mknod -m 644 /dev/random c 1 8
mknod -m 644 /dev/urandom c 1 9
chown root:root /dev/random /dev/urandom

我们删除一个并伪造它,即

rm /dev/random
mknod -m 644 /dev/random c 1 9
chown root:root /dev/random

/dev/random现在实际上是/dev/urandom

要记住的关键是测试需要来自 由于观察者效应,您正在测试的系统很困难。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

BCrypt 性能恶化 的相关文章

随机推荐