標籤:加密 pbkdf2
在系統中密碼通常需要以密文的形式來儲存到系統中去,所以在操作過程中通常需要將明文的密碼加密。
加密的方式可以分為:雙向加密 單向加密。
- 雙向加密:簡單來理解就是可以通過密鑰將加密後的密文解密為明文。常用的加密DES、IDEA、RC2、RC4、SKIPJACK、RC5、AES。
- 反之,單向加密則為無法復原的加密方式。常見的如:MD5 、SHA 。
而雙向加密中又分為對稱式加密和非對稱式加密。這個是根據加密和解密的密鑰是否相同來決定的,對稱式加密則加密和解密的密鑰相同,非對象加密則反之。
由於一般的加密後方式很容器破解,如對於MD5加密來說攻擊者只需要一個簡單的sql語句
`:select * from userInfo where password=’4QrcOUm6Wau+VuBX8g+IPg==’
` 就可以知道有幾個使用者密碼是”123456”,這對一個項目來說十分危險。所以一般在加密之前,配上一個一串的隨機序列。稱之為salt。
鹽是一個添加到使用者的密碼雜湊過程中的一段隨機序列。這個機制能夠防止通過預先計算結果的彩虹表破解。每個使用者都有自己的鹽,這樣的結果就是即使使用者的密碼相同,通過加鹽後雜湊值也將不同。然而,在將鹽與密文儲存的位置上有很多矛盾的地方,有的時候將兩者存在一起比較方便,有的時候為了安全考慮又不得不將兩者分開儲存。由於PBKDF2演算法通過key的機制避免了暴力破解,我覺得沒必要將鹽隱藏起來,就跟密文儲存在同一個位置。
本文主要分享一個PBKDF2加密的工具類,如下。
public static final int HASH_MILLIS = 1231; public static final String ALGORITHM = "asfdasdfdfsafs";public static final int ITERATION_COUNT = 123123;public static final int KEY_SIZE = 123;public static final int SALT_LENGTH = 123;/** * * @Title: getSalt * @author:陳方林* @Description: TODO(得到salt) * @param @return 設定檔案 * @return String 傳回型別 * @date 上午9:28:18 */public static String getSalt(){ String salt=new String(Base64.encodeBase64(nextSalt())); return salt;}/** * * @author:cfl* @Description: TODO(密碼加密) * @param @param salt * @param @param password 明文* @param @return 加鹽後的密文* @param @throws Exception 設定檔案 * @return String 傳回型別 * @date 2015年7月20日18:36:21 */public static String encryptPassword(String salt,String password) throws Exception{ byte[] saltByte = Base64.decodeBase64(salt.getBytes()); byte[] hash = PasswordsUtils.hashPassword(password.toCharArray(), saltByte); String pwd_hash_str = new String(Base64.encodeBase64(hash)); return pwd_hash_str;}public static byte[] hashPassword(char[] password, byte[] salt) throws GeneralSecurityException { return hashPassword(password, salt, ITERATION_COUNT, KEY_SIZE);}public static byte[] hashPassword(char[] password, byte[] salt, int iterationCount, int keySize) throws GeneralSecurityException { try { PBEKeySpec spec = new PBEKeySpec(password, salt, iterationCount, keySize); SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); return factory.generateSecret(spec).getEncoded(); } catch (IllegalArgumentException e) { throw new GeneralSecurityException("key size " + keySize, e); }}public static boolean matches(char[] password, byte[] passwordHash, byte[] salt) throws GeneralSecurityException { return matches(password, passwordHash, salt, ITERATION_COUNT, KEY_SIZE);}public static boolean matches(char[] password, byte[] passwordHash, byte[] salt, int iterationCount, int keySize) throws GeneralSecurityException { return Arrays.equals(passwordHash, hashPassword(password, salt, iterationCount, keySize));}public static byte[] nextSalt() { byte[] salt = new byte[SALT_LENGTH]; SecureRandom sr = new SecureRandom(); sr.nextBytes(salt); return salt;}
驗證樣本
UserInfo userinfo=SessionManager.getLoginUser();String salt=userinfo.getSalt();String realPassword=userinfo.getPassword();String inputPassword; //使用者輸入的password//返回使用者輸入密碼加密後的密文String encryptPassword=PasswordsUtils.encryptPassword(salt, inputPassword); if(encryptPassword.equals(realPassword)){ return true;}else{ return false;}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Java版PBKDF2驗證