轉載地址:http://blog.dreamlikes.cn/archives/880
[版權聲明] 本站內容採用 知識共享署名-非商業性使用-相同方式共享 3.0 中國大陸 (CC BY-NC-SA 3.0 CN) 進行許可。
部分內容和資源來自網絡,純學習研究使用。如有侵犯您的權益,請及時聯繫我,我將盡快處理。
如轉載請註明來自: Broly的博客,本文鏈接: Java和PHP(Laravel)的Bcrypt加密兼容
後端早期使用的是Laravel構建的,用戶系統的密碼加密方式用的是原生的語法:password_hash
// $hash = password_hash('broly', PASSWORD_DEFAULT);
$hash = '$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO';
if (password_verify('broly', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
現在需要部分業務用到Java做用戶驗證,這裏就涉及到密碼驗證的兼容問題。先來用spring security的BCryptPasswordEncoder測試一下:
package com.dreamlike.dmlkdemo;
import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author Broly
*
*/
public class CryptTests {
@Test
public void bcryptTest() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
System.out.println(bCryptPasswordEncoder.encode("broly"));
// $2a$10$h.cMz2AmkBbkuUKnFY837uCB3/JZgtJUV7BBUnaGWUCrMk/FF4nX.
String encodedPassword = "$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
boolean bMatch = bCryptPasswordEncoder.matches("broly", encodedPassword);
System.out.println(bMatch); // false
}
}
發現測試通不過。網上查了下password_hash()默認的加密算法是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 algorithmeter and must be in range 04-31, values outside this range will cause crypt() to fail. Versions of PHP before 5.3.7 only support "$2a$" as the salt prefix: PHP 5.3.7 introduced the new prefixes to fix a security weakness in the Blowfish implementation. Please refer to » this document for full details of the security fix, but to summarise, developers targeting only PHP 5.3.7 and later should use "$2y$" in preference to "$2a$".
可以發現二者之間的區別在於字符串開頭 $2a$ 與 $2y$。大意是$2y$開頭的是新版本的安全修復。Java僅支持$2a$。
其實解決方法很簡單,在判斷之前,用正則把$2y$改成$2a$,然後進行判斷:
package com.dreamlike.dmlkdemo;
import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author Broly
*
*/
public class CryptTests {
@Test
public void bcryptTest() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
System.out.println(bCryptPasswordEncoder.encode("broly"));
// $2a$10$h.cMz2AmkBbkuUKnFY837uCB3/JZgtJUV7BBUnaGWUCrMk/FF4nX.
// String encodedPassword = "$2y$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
String encodedPassword = "$2a$10$wO./FnpCf8NkqjXbgV5ZT.juYia/Ts4Fz6ZBZgfWObmOjlAQwKtfO";
boolean bMatch = bCryptPasswordEncoder.matches("broly", encodedPassword);
System.out.println(bMatch); // true
}
}
參考鏈接:《How to calculate in java a Bcrypt password compatible with Laravel》
其他:https://laravel-china.org/docs/laravel/5.6/hashing/1383#4881e0