Java和PHP(Laravel)的Bcrypt加密兼容

轉載地址: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

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章