问题:似乎当服务器重新启动时,Bcrypt.hashpw需要100ms来解密密码。然而,一段时间后(没有模式),Bcrypt.hashpw的性能突然从100毫秒飙升到10秒。这没有明显的原因。
问题有时是块,当它这样做时,它将看起来像是随机的:)更令人困惑的是,在尝试测试它的工作原理时,您将遇到观察者效应,即在尝试观察随机行为时,您正在生成熵,这可能导致大量的混乱,即我的结果不会与您的结果相同等。这也是为什么它看起来没有模式的原因。/dev/random
我将演示该问题,并向您展示如何在您自己的服务器上重新创建它(在合理范围内),以便您可以测试解决方案。我将尝试提供一些修复程序,请注意,这是在Linux上,但相同的问题将发生在任何需要熵来生成随机数并耗尽的系统上。
在 Linux 上是随机字节流。当您从流中读取时,您将耗尽可用的熵。当它达到某个点时,从块中读取。您可以使用此命令查看可用熵/dev/random
/dev/random
cat /proc/sys/kernel/random/entropy_avail
如果您运行以下 bash 脚本并进行监视,您会注意到,随着 bash 脚本消耗熵,熵会急剧下降。entropy_avail
while :
do
cat /dev/random > /dev/null
done
这还应该给你一个提示,告诉你如何在你的服务器上重现这个问题,即运行上面的bash脚本来减少可用的熵,问题就会显现出来。
如果你想看看你的系统每秒创建多少字节,你可以用它来测量它,即pv
pv /dev/random
如果你保持运行状态,它会产生影响,它会消耗随机的字节流,这意味着其他服务可能会开始阻塞。请注意,它还显示其输出,因此它也可能增加系统上的可用:)。pv
pv
在熵很少或没有熵的系统上,使用似乎很慢。我还体验过,VM有时在生成熵时会遇到重大问题。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
如果你在 runnng 时运行之前的 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
修复
第一个修复是从使用更改为ie/dev/random
/dev/urandom
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
要记住的关键是,由于观察者效应,测试需要从您正在测试的系统中输入的随机数据是困难的。