2016-06-07 40 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

相关问题