2011-07-08 34 views
0

我正在嘗試使用BouncyCastle對加密和解密字符串密碼進行加密的java測試類進行編碼。 main()非常簡單,我做encryptPass()然後decryptPass(),我看着控制檯跟蹤。獲取javax.crypto中的填充異常

問題是,當它試圖解密,我得到了一個填充異常:

javax.crypto.BadPaddingException: pad block corrupted 
    at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown Source) 
    at javax.crypto.Cipher.doFinal(DashoA13*..) 
    at com.kiengi.crypto.Crypto.decryptPass(Crypto.java:79) 

我的代碼是用於加密類以下內容:

// password to be crypted 
public String pass = "password_go_here"; 

// key for encrypt pass 
public String passKey = generateRandomKey(); // generation clef 16 caractere [a-zA-Z0-9] 

// Encrypted pass 
public String cryptedPass; 

public final Logger logger = Logger.getLogger(this.getClass()); 

private final static byte[] IV_BYTES = new byte[] { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 
     0x00, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; 

public Crypto() { 
    super(); 
} 

public void encryptPass(){ 

    Security.addProvider(new BouncyCastleProvider()); 
    IvParameterSpec _ivSpec = new IvParameterSpec(IV_BYTES); 

    try{ 
     KeyGenerator _keygen = KeyGenerator.getInstance("AES"); 
     _keygen.init(new SecureRandom(passKey.getBytes())); 
     SecretKey _key = _keygen.generateKey(); 
     logger.trace("Secret key generated"); 

     Cipher _cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); 
     _cipher.init(Cipher.ENCRYPT_MODE, _key, _ivSpec); 

     cryptedPass = asHex(_cipher.doFinal(pass.getBytes("UTF-8"))); 


     logger.trace("Encrypted pass : "+cryptedPass); 


    }catch (Exception e) { 
     logger.warn("encrypt failed"); 
     e.printStackTrace(); 
    } 
} 

public void decryptPass() { 
    byte[] _passKey = passKey.getBytes(); 
    byte[] _cryptedPass = hexFromString(cryptedPass); 

    Security.addProvider(new BouncyCastleProvider()); 
    IvParameterSpec _ivSpec = new IvParameterSpec(IV_BYTES); 

    try {   
     KeyGenerator _keygen = KeyGenerator.getInstance("AES"); 
     _keygen.init(new SecureRandom(_passKey)); 
     SecretKey _key = _keygen.generateKey(); 
     logger.trace("Secret key generated"); 

     Cipher _cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); 
     _cipher.init(Cipher.DECRYPT_MODE, _key, _ivSpec); 

     String _pass = new String(_cipher.doFinal(_cryptedPass), "UTF-8"); 

     logger.trace("Decrypted pass : "+_pass); 

    } catch (Exception e) { 
     logger.warn("decrypt failed"); 
     e.printStackTrace(); 
    } 

} 

private int fromDigit(char ch) { 
    if ((ch >= '0') && (ch <= '9')) { 
     return ch - '0'; 
    } else if ((ch >= 'A') && (ch <= 'F')) { 
     return ch + 10 - 'A'; 
    } else if ((ch >= 'a') && (ch <= 'f')) { 
     return ch + 10 - 'a'; 
    } else { 
     throw new IllegalArgumentException(String.format(
       "Invalid hex character 0x%04x", 0xff & ch)); 
    } 
} 

private byte[] hexFromString(String hex) { 
    final byte[] buf = new byte[hex.length()/2]; 
    for (int i = 0, j = 0; i < hex.length(); i += 2) { 
     buf[j++] = (byte) (fromDigit(hex.charAt(i)) << 4 | fromDigit(hex 
       .charAt(i + 1))); 
    } 
    return buf; 
} 

private static String asHex(byte buf[]) { 
    final Formatter formatter = new Formatter(new StringBuffer()); 
    for (int i = 0; i < buf.length; i++) { 
     formatter.format("%02x", 0xff & buf[i]); 
    } 
    return formatter.toString(); 
} 

private String generateRandomKey() { 
    String _chars = "abcdefABCDEF1234567890"; 
    StringBuffer _pass = new StringBuffer(); 
    for (int x = 0; x < 32; x++) { 
     int i = (int) Math.floor(Math.random() * (_chars.length() - 1)); 
     _pass.append(_chars.charAt(i)); 
    } 
    return _pass.toString(); 
} 

有誰知道這是什麼異常的手段?

回答

0

此代碼有一個錯誤。它假定new SecureRandom(passKey.getBytes())將初始化SecureRandom實例只有在構造函數中提供的字節。這是錯誤的。在構造函數中的數據將會被補充爲,無論是SecureRandom使用的是什麼熵源,都不會取代他們。

您需要使用適當的基於密碼的加密(PBE)方案。

+1

好的。是的,您需要將密碼散列到密鑰長度,以便與您的加密算法一致(即使用SHA256(密碼)作爲AES 256密鑰)。目前,您正在爲加密和解密隨機生成密鑰。 –

0

此異常意味着填充塊已損壞。您使用16B塊的PKCS#7填充。在這個例子中,你的輸出也是16B。所以它總是應該添加16個字節值爲0x10的塊。
由於解密已損壞,填充已損壞。您的SecureRandom實施會添加自己的熵並生成錯誤的解密密鑰。此SecureRandom構造函數使用已註冊SecureRandom實現的第一個提供程序的第一個PRNG算法。