背景:
PHP的bcrypt默认采用的是CRYPT_BLOWFISH加密算法,使用的salt是$2y$,而Java使用的salt是$2a$,当使用Java对由PHP的bcrypt加密的密文进行校验时,会因为salt的这个差异导致Java出现下面的错误:
Encoded password does not look like BCrypt
从官方文档对CRYPT_BLOWFISH的说明里,可以证实:
CRYPT_BLOWFISH
- Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithm and must be in range 04-31, values outside this range will cause crypt() to fail. "$2x$" hashes are potentially weak; "$2a$" hashes are compatible and mitigate this weakness. For new hashes, "$2y$" should be used. Please refer to » this document for full details of the related security fix.解决办法,分为两种:
第一种,也是最简单的,在密文校验前,先将密文的$2y$替换为$2a$
第二种,重写spring boot的BCryptPasswordEncoder.java,之所以会出现上述错误,主要是下面这个方法:
public boolean matches(CharSequence rawPassword, String encodedPassword) { if (encodedPassword == null || encodedPassword.length() == 0) { logger.warn("Empty encoded password"); return false; } if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) { logger.warn("Encoded password does not look like BCrypt"); return false; } return BCrypt.checkpw(rawPassword.toString(), encodedPassword); }
参考资料:
https://www.php.net/manual/en/function.crypt.php