2017-07-19 262 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)。