2016-06-07 83 views
0

我正在寫一個簡單的自定義加密器/解密器。
基本上,我只是取大文件的前1024個字節並加密它。
我使用了一個RandomAccessFile,這樣我就可以快速地加密和解密第一個1024字節。現在對於文件使用相同的AES算法的Bad Padding Exception?

,我面臨的問題是,即使我使用的加密和解密的算法相同。
加密工作正常,但解密拋出一個javax.crypto.BadPaddingException:鑑於最終塊未正確填充

不管我多麼搜索,我無法弄清楚什麼是錯的。對此的一些研究告訴我,由於UTF和base64等格式不同,填充不正確。但我不確定如果我讀取這樣一個大文件的第一個1024字節如何填充可能是不正確的&加密沒有任何例外。另外我沒有對字符串進行轉換。

我已經提供了簡單的評論,下面的代碼

public class Encryptor { 

private static final String ALGORITHM = "AES"; 
private static final String TRANSFORMATION = "AES"; 

public void encrypt(String key, File inputFile, File outputFile) throws CryptoException { 
    doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile); 
} 

public void decrypt(String key, File inputFile, File outputFile) throws CryptoException { 
    doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile); 
}  
private void doCrypto(int cipherMode, String key, File inputFile, File outputFile) throws CryptoException { 
    try { 

     Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM); 
     Cipher cipher = Cipher.getInstance(TRANSFORMATION); 
     cipher.init(cipherMode, secretKey); 

     byte[] inputBytes = new byte[16]; 
     byte[] outputBytes = new byte[16]; 

     //Open the file in read write mode 
     RandomAccessFile fileStore = new RandomAccessFile(inputFile, "rw"); 
     fileStore.seek(0); 

     //encrypt first 1024bytes 
     int bytesRead = 0; 
     for(int ctr=0;bytesRead!= -1 && ctr<64 ;ctr++){ 
      //get file pointer position 
      long prevPosition = fileStore.getFilePointer(); 

      //read 16 bytes to array 
      bytesRead = fileStore.read(inputBytes); 

      //if successful, go move back pointer and overwrite these 16 bytes with encrypted bytes 
      if(bytesRead != 1){ 
       outputBytes = cipher.doFinal(inputBytes); 
       fileStore.seek(prevPosition); 
       fileStore.write(outputBytes); 
      } 
     } 

     fileStore.close(); 

    } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException 
      | IllegalBlockSizeException | IOException ex) { 
     throw new CryptoException(ex); 
    } 
} 

回答

3

首先,在"AES"算法串內部由Sun提供者轉化爲"AES/ECB/PKCS5Padding"。這意味着您正在使用不安全的ECB模式加密,而不是更安全的CBC模式。

爲什麼你BadPaddingException很簡單的道理。當您使用PKCS5Padding(或更確切地說是PKCS#7填充)時,每個16字節在加密過程中最多填充32個字節。但是,您只能存儲未填充的16個字節。如果你試圖解密unpadding機制,試圖取消你的原始未加填充的明文,這將會失敗。

其次,read方法實際上可能不讀16個字節。它只是讀取高達 16個字節。您需要創建一個單獨的方法來始終精確讀取16個字節。

調用doFinal多次是不是一個好主意。您最好一次讀取1024個字節,然後撥打doFinal或者 - 更好 - 只需要一次update。在這種情況下,你應該使用例如"AES/CBC/NoPadding"作爲算法字符串。


注:

  • 沒有一個隨機IV你仍然能夠區分具有相同字節(或文件中的時間被重新加密,在相同字節開始)開頭的文件;
  • 你可能想要某種協議來處理小於1024字節的文件;
  • 使用「試用資源」可能是一個非常好的主意;
  • 使用文件的內存映射來實現更清潔的設計和(可能)更快的操作。
+0

清潔和對點..(y)的 – user3041058