1. 程式人生 > >java常用加密演算法之pbkdf2

java常用加密演算法之pbkdf2

PBKDF2簡介

       常見的加密演算法,如MD5,此類演算法為單向的,無法通過逆向破解,但由於技術的不斷進步,可以通過字典和暴力破解。後來人們通過加鹽來增加密碼的安全性,但彩虹表的出現讓這種方式也變得不安全。以至於出現了現在的PBKDF2演算法。

       PBKDF2演算法通過多次hash來對密碼進行加密。原理是通過password和salt進行hash,然後將結果作為salt在與password進行hash,多次重複此過程,生成最終的密文。此過程可能達到上千次,逆向破解的難度太大,破解一個密碼的時間可能需要幾百年,所以PBKDF2演算法是安全的。

       在web系統中最基礎的一個功能就是使用者密碼的驗證,採用pbkdf2演算法對使用者的密碼進行加密是比較常見的作法,本篇部落格將簡單的給出加密的Java實現。

演算法的Java實現

public class PBKDF2 
{
	public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";  
	  
	//鹽的長度  
    public static final int SALT_SIZE = 16;  
  
     //生成密文的長度 
    public static final int HASH_SIZE = 32;  
  
     // 迭代次數 
    public static final int PBKDF2_ITERATIONS = 1000;  
  
    /** 
     * 對輸入的密碼進行驗證 
     *  
     */  
    public static boolean verify(String password, String salt, String key)  
            throws NoSuchAlgorithmException, InvalidKeySpecException {  
        // 用相同的鹽值對使用者輸入的密碼進行加密  
        String result = getPBKDF2(password, salt);  
        // 把加密後的密文和原密文進行比較,相同則驗證成功,否則失敗  
        return result.equals(key);  
    }  
  
    /**
     * 根據password和salt生成密文
     * 
     */
    public static String getPBKDF2(String password, String salt) throws NoSuchAlgorithmException,  
            InvalidKeySpecException {  
    	//將16進位制字串形式的salt轉換成byte陣列
    	byte[] bytes = DatatypeConverter.parseHexBinary(salt);
        KeySpec spec = new PBEKeySpec(password.toCharArray(), bytes, PBKDF2_ITERATIONS, HASH_SIZE * 4);  
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);  
        byte[] hash = secretKeyFactory.generateSecret(spec).getEncoded();
		//將byte陣列轉換為16進位制的字串
        return DatatypeConverter.printHexBinary(hash);  
    }  
    
  
    /** 
     * 生成隨機鹽值
     *  
     */  
    public static String getSalt() throws NoSuchAlgorithmException {  
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");  
        byte[] bytes = new byte[SALT_SIZE / 2];  
        random.nextBytes(bytes);  
        //將byte陣列轉換為16進位制的字串
        String salt = DatatypeConverter.printHexBinary(bytes);
        return salt;  
    }  
}