2017-07-19 300 views
0

獲取org.tukaani.xz.CorruptedInputException:壓縮數據已損壞嘗試解密密碼保護時出錯(AES 256)7z文件。而沒有密碼保護的7z文件解壓沒有任何問題。這兩種情況相同的xls文件被壓縮。使用apache compress/org.tukaani.xz在java中解壓縮/解密密碼保護(AES 256)7z文件的問題

我使用Apache commons compress和org.tukaani.xz。

示例代碼以供參考。

package com.concept.utilities.zip; 

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.lang.reflect.Field; 

import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry; 
import org.apache.commons.compress.archivers.sevenz.SevenZFile; 
import org.apache.poi.hssf.usermodel.HSSFWorkbook; 
import org.apache.poi.ss.usermodel.Workbook; 

public class DecryptionUtil { 


    static { 
     try { 
      Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted"); 
      field.setAccessible(true); 
      field.set(null, java.lang.Boolean.FALSE); 
     } catch (Exception ex) { 
     } 
    } 


    public void SevenZFile(String directory, String encryptCompressFileName, String password) { 

     SevenZFile sevenZFile = null; 
     SevenZArchiveEntry entry = null; 

     try { 

      File file = new File(directory+encryptCompressFileName); 
      byte[] inputData = new byte[(int) file.length()]; 
      FileInputStream fis = new FileInputStream(file); 
      fis.read(inputData); 
      fis.close(); 

      // SeekableInMemoryByteChannel inMemoryByteChannel = new SeekableInMemoryByteChannel(inputData); 
      if(null != password){ 
       byte[] pass = password.getBytes("UTF16"); 
       sevenZFile = new SevenZFile(file, pass); 
      }else{ 
       sevenZFile = new SevenZFile(file); 
      } 

      // Go through all entries 
      while (null != (entry = sevenZFile.getNextEntry())) { 

       // Maybe filter by name. Name can contain a path. 
       String processingFileName = entry.getName(); 
       if (entry.isDirectory()) { 
        System.out.println(String.format("Found directory entry %s", processingFileName)); 

       } else { 

        // If this is a file, we read the file content into a ByteArrayOutputStream ... 
        System.out.println(String.format("Unpacking start %s ...", processingFileName)); 
        ByteArrayOutputStream contentBytes = new ByteArrayOutputStream(); 

        // ... using a small buffer byte array. 
        byte[] buffer = new byte[2048]; 
        int bytesRead; 

        while ((bytesRead = sevenZFile.read(buffer)) != -1) { 
         contentBytes.write(buffer, 0, bytesRead); 
        } 


        if (processingFileName.endsWith("xls")) { 
         // Writing into xls 
         Workbook wb = new HSSFWorkbook(); 
         //String safeName = WorkbookUtil.createSafeSheetName(processingFileName); 
         //Sheet sheet = wb.createSheet(safeName); 
         FileOutputStream fileOut = new FileOutputStream(directory+processingFileName); 
         fileOut.write(contentBytes.toByteArray()); 
         fileOut.flush(); 
         wb.write(fileOut); 
         fileOut.close(); 
         wb.close(); 
        }else{ //regular file 
         System.out.println(contentBytes.toString("UTF-8")); 
        } 
        System.out.println(String.format("Unpacking finish %s ...", processingFileName)); 
       } 
      } 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       sevenZFile.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

    } 


    public static void main(String[] args) { 

     DecryptionUtil decrypt = new DecryptionUtil(); 
     decrypt.SevenZFile("H:\\archives\\", "StudentsWoPassword.7z", null); 
     decrypt.SevenZFile("H:\\archives\\", "StudentsWithPassAES256.7z", "test"); 

    } 

} 

StudentsWoPassword.7z成功解壓但StudentsWithPassAES256.7z拋出異常。

Unpacking start Students.xls ... 
Unpacking finish Students.xls ... 
org.tukaani.xz.CorruptedInputException: Compressed data is corrupt 
    at org.tukaani.xz.rangecoder.RangeDecoderFromStream.<init>(Unknown Source) 
    at org.tukaani.xz.LZMAInputStream.initialize(Unknown Source) 
    at org.tukaani.xz.LZMAInputStream.initialize(Unknown Source) 
    at org.tukaani.xz.LZMAInputStream.<init>(Unknown Source) 
    at org.apache.commons.compress.archivers.sevenz.LZMADecoder.decode(LZMADecoder.java:43) 
    at org.apache.commons.compress.archivers.sevenz.Coders.addDecoder(Coders.java:76) 
    at org.apache.commons.compress.archivers.sevenz.SevenZFile.buildDecoderStack(SevenZFile.java:933) 
    at org.apache.commons.compress.archivers.sevenz.SevenZFile.buildDecodingStream(SevenZFile.java:909) 
    at org.apache.commons.compress.archivers.sevenz.SevenZFile.getNextEntry(SevenZFile.java:222) 
    at com.concept.utilities.zip.DecryptionUtil.SevenZFile(DecryptionUtil.java:50) 
    at com.concept.utilities.zip.DecryptionUtil.main(DecryptionUtil.java:107) 

我錯過了什麼嗎?有沒有其他方法可以提取AES256 7z?

+0

如果您使用「UTF-16LE」作爲編碼,它會工作嗎?編碼時UTF16使用大端字節順序,'SevenZFile'預計小端。 –

+0

謝謝Stefan。更改爲「UTF-16LE」後。它的工作原理 – Raj

+0

所以讓我們來回答這個問題:-) –

回答

0

你的代碼很好,你只是在從密碼中提取字節時使用錯誤的字符集/編碼。 SevenZFile類預計UTF-16在little endian中,因此您必須使用UTF-16LE而不是UTF-16(在編碼數據時將使用big endian)。