2013-04-28 56 views
0

我在嘗試解密某些加密文本時遇到了一些麻煩。 CheckpswdBasedKey總是返回false,因爲在c.doFInal 的BadPaddingException的我使用AES,basicaly加密:AES解密時的瘋狂例外 - BadPaddingException

public static String generatePswdBasedKey(String password){ 
String finalKey = null; 
SecretKey sk = null; 
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, IT, KEY_LENGTH); 
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); 
sk = new SecretKeySpec(keyBytes, "AES"); 
Cipher cipher = Cipher.getInstance(Cifrador.AES_MODE);//AES_MODE = AES/CBC/PKCS5Padding 
IvParameterSpec ivParams = new IvParameterSpec(iv);//IV already initialized 
cipher.init(Cipher.ENCRYPT_MODE, sk, ivParams); 
byte pwdbytes[] = password.getBytes();//I also tried using Base64 to decode... without success 
byte cc[] = cipher.doFinal(pwdbytes); 
finalKey = Base64.encodeToString(cc, false); //.encodeToString(byte[] sArr, boolean lineSep) 
return finalKey; 

現在解密模式:

//This method compares a password received from keyboard with the decrypted password (decrypting output from generatePswdBasedKey(String password)) 
public static boolean checkPswdBasedKey(String password, String passwordInput){ 
byte bufferBytes[] = Base64.decode(password); 
SecretKey sk = new SecretKeySpec(bufferBytes, 0, bufferBytes.length, "AES"); //Also tried new SecretKeySPec(bufferBytes, "AES");... 
Cipher c = Cipher.getInstance(Cifrador.AES_MODE);//AES_MODE = AES/CBC/PKCS5Padding 
IvParameterSpec ivParams = new IvParameterSpec(iv);//IV already initialized 
c.init(Cipher.DECRYPT_MODE, sk, ivParams); 
byte result[] = c.doFinal(bufferBytes); 
String resultStr = Base64.encodeToString(result, false); //.encodeToString(byte[] sArr, boolean lineSep) 
if(passwordInput.equalsIgnoreCase(resultStr)){ 
return true; 
} 
return false; 
} 

我比較了四字節@ checkPswdBasedKey和iv @generatePswdBasedKey,它們都是相同的。 secretkey @checkPswdBasedKey(我得到這些字節:sk.getEncoded())和secretkey @generatePswdBasedKey ......它們都是平等的。 所以基本上當我解密我知道我使用相同的密鑰,相同的IV和相同的消息...和適當的長度(16字節鍵,16字節味精,16字節iv,使用AES 128)任何想法?

+0

有點題外話,但任何特別的理由不使用安全散列的口令? – 2013-04-28 14:59:26

+0

將解密端設置爲無填充並查看您獲得的內容。各種各樣的錯誤都是可能的,並且知道明文的末尾可以消除其中的一些錯誤。 – rossum 2013-04-28 18:43:20

+0

@rossum好吧,我做到了,thxü,現在沒有任何異常,但解密輸出doenst匹配passwordInput – Aero 2013-04-28 18:59:24

回答

0

由於約阿希姆·伊薩克森評論說,如果你想實現一個密碼檢查,你應該使用密碼的安全散列表示,這是不可逆的。這樣,即使散列+密鑰被泄露,密碼也不能通過解密獲得。

反正,在你generatePswdBasedKey使用PBKDF2WithHmacSHA1算法生成SecretKey,然後使用該密鑰來加密密碼。現在您有兩個選項來驗證checkPswdBasedKey中的密碼。要麼你:

  • 加密密碼相同的方式,在generatePswdBasedKey和比較,他們給予同樣的加密字符串

,或者你

  • 解密加密版本,並用結果比較密碼清晰。

我認爲您嘗試後一種方法,你初始化你的密碼與解密:

c.init(Cipher.DECRYPT_MODE,SK,ivParams);

Hovewer,於這個方法的工作,你需要來實例SecretKey以同樣的方式 如您在generatePswdBasedKey一樣 - 目前你最終有兩個不同的密鑰。

在generatePswdBasedKey:

SecretKey sk = null; 
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, IT, KEY_LENGTH); 
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); 
sk = new SecretKeySpec(keyBytes, "AES"); 

在checkPswdBasedKey:

byte bufferBytes[] = Base64.decode(password); 
SecretKey sk = new SecretKeySpec(bufferBytes, 0, bufferBytes.length, "AES"); 

當這是固定的,你還需要看看你的比較邏輯。在比較之前,您不應該對結果編碼Base64,並且比較應該區分大小寫。 不要使用:

byte result[] = c.doFinal(bufferBytes); 
String resultStr = Base64.encodeToString(result, false); 
if (passwordInput.equalsIgnoreCase(resultStr)) { 
    return true; 
} 

而是使用:

byte result[] = c.doFinal(bufferBytes); 
String resultStr = new String(result); 
if (passwordInput.equals(resultStr)) { 
    return true; 
} 
+0

你做了我的一天,這完美的作品!謝謝 – Aero 2013-04-29 12:22:40