密码哈希的方法:PBKDF2,Scrypt,Bcrypt 和 ARGON2

1 BCryptPasswordEncoder

BCryptPasswordEncoder 的实现使用广泛支持的 bcrypt 算法对密码进行散列。为了使它对密码破解有更强的抵抗力,bcrypt故意做得很慢。像其他自适应单向函数一样,它应该被调整为在你的系统上验证一个密码需要1秒左右。BCryptPasswordEncoder 的默认实现使用 BCryptPasswordEncoder 的 Javadoc 中提到的强度10。我们鼓励你在自己的系统上调整和测试强度参数,使其大约需要1秒钟来验证一个密码。

// Create an encoder with strength 16*
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));

2 Argon2PasswordEncoder

Argon2PasswordEncoder 的实现使用 Argon2 算法对密码进行散列。Argon2是 密码哈希大赛 的冠军。为了打败定制硬件上的密码破解,Argon2是一种故意的慢速算法,需要大量的内存。像其他自适应单向函数一样,它应该被调整为在你的系统上验证一个密码需要1秒左右。 Argon2PasswordEncoder 的当前实现需要 BouncyCastle。

*// Create an encoder with all the defaults*
Argon2PasswordEncoder encoder = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));

3 Pbkdf2PasswordEncoder

Pbkdf2PasswordEncoder 的实现使用 PBKDF2 算法对密码进行散列。为了抵御密码破解,PBKDF2是一种故意的慢速算法。像其他自适应单向函数一样,它应该被调整为在你的系统上验证一个密码需要1秒左右。当需要FIPS认证时,这种算法是一个不错的选择。

*// Create an encoder with all the defaults*
Pbkdf2PasswordEncoder encoder = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));

4 SCryptPasswordEncoder

SCryptPasswordEncoder 的实现使用 scrypt 算法对密码进行散列。为了打败定制硬件上的密码破解,scrypt是一个故意的慢速算法,需要大量的内存。像其他自适应单向函数一样,它应该被调整为在你的系统上验证一个密码需要1秒左右。

*// Create an encoder with all the defaults*
SCryptPasswordEncoder encoder = SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));

结论

不要使用 PBKDF2 或 BCrypt,并强烈建议将 Argon2(最好是 Argon2id)用于最新系统。

Scrypt 是当 Argon2 不可用时的不二选择,但要记住,它在侧侧信道泄露方面也存在相同的问题。