首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java - AES加密压缩文件会导致其损坏。

Java - AES加密压缩文件会导致其损坏。
EN

Stack Overflow用户
提问于 2022-09-07 14:37:18
回答 2查看 98关注 1票数 0

我试图使用AES-256加密密码加密一个压缩文件.下面是我正在运行的代码。

代码语言:javascript
运行
复制
import java.io.*;
import java.security.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;


public class Main {
    public static void encryptAndClose(FileInputStream fis, FileOutputStream fos) 
            throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {

        // Length is 16 byte
        SecretKeySpec sks = new SecretKeySpec("1234567890123456".getBytes(), "AES");
        // Create cipher
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, sks);      

        // Wrap the output stream for encoding
        CipherOutputStream cos = new CipherOutputStream(fos, cipher);       

        //wrap output with buffer stream
        BufferedOutputStream bos = new BufferedOutputStream(cos);     

        //wrap input with buffer stream
        BufferedInputStream bis = new BufferedInputStream(fis); 

        // Write bytes
        int b;
        byte[] d = new byte[8];
        while((b = bis.read(d)) != -1) {
            bos.write(d, 0, b);
        }
        // Flush and close streams.
        bos.flush();
        bos.close();
        bis.close();
    }


    public static void decryptAndClose(FileInputStream fis, FileOutputStream fos) 
            throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {

        SecretKeySpec sks = new SecretKeySpec("1234567890123456".getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, sks);

        CipherInputStream cis = new CipherInputStream(fis, cipher);

        //wrap input with buffer stream
        BufferedInputStream bis = new BufferedInputStream(cis); 

        //wrap output with buffer stream
        BufferedOutputStream bos = new BufferedOutputStream(fos);       

        int b;
        byte[] d = new byte[8];
        while((b = bis.read(d)) != -1) {
            bos.write(d, 0, b);
        }
        bos.flush();
        bos.close();
        bis.close();
    }
    
    
    static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
        if (fileToZip.isHidden()) {
            return;
        }
        if (fileToZip.isDirectory()) {
            if (fileName.endsWith("/")) {
                zipOut.putNextEntry(new ZipEntry(fileName));
                zipOut.closeEntry();
            } else {
                zipOut.putNextEntry(new ZipEntry(fileName + "/"));
                zipOut.closeEntry();
            }
            File[] children = fileToZip.listFiles();
            for (File childFile : children) {
                zipFile(childFile, fileName + "/" + childFile.getName(), zipOut);
            }
            return;
        }
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileName);
        zipOut.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
        fis.close();
    }
    
    static void unZipFile(ZipEntry zipEntry,File destDir,ZipInputStream zis, byte[] buffer) throws IOException{
        while (zipEntry != null) {
            File newFile = newFile(destDir, zipEntry);
            if (zipEntry.isDirectory()) {
                if (!newFile.isDirectory() && !newFile.mkdirs()) {
                    throw new IOException("Failed to create directory " + newFile);
                }
            } else {
                // fix for Windows-created archives
                File parent = newFile.getParentFile();
                if (!parent.isDirectory() && !parent.mkdirs()) {
                    throw new IOException("Failed to create directory " + parent);
                }
                
                // write file content
                FileOutputStream fos = new FileOutputStream(newFile);
                int len;
                while ((len = zis.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
                fos.close();
            }
        zipEntry = zis.getNextEntry();
       }
    }
    public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
        File destFile = new File(destinationDir, zipEntry.getName());

        String destDirPath = destinationDir.getCanonicalPath();
        String destFilePath = destFile.getCanonicalPath();

        if (!destFilePath.startsWith(destDirPath + File.separator)) {
            throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
        }

        return destFile;
    }
    
    public static void main(String[]args) {
        
        //compress to zip.
        String sourceFile = "C:\\test";
        FileOutputStream fos;
        try {
            fos = new FileOutputStream("C:\\test\\test.zip");
            ZipOutputStream zipOut = new ZipOutputStream(fos);
            File fileToZip = new File(sourceFile);

            zipFile(fileToZip, fileToZip.getName(), zipOut);
            zipOut.close();
            fos.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //encrypt the zip.
        String outDir = "C:/test";
        String outFilename = "test-encrypt.zip";
        
        String inDir = "C:/test";
        String inFilename = "test.zip";
        
        File output= new File(outDir, outFilename);

        File input= new File(inDir, inFilename);

        if (input.exists()) {
            System.out.println("test");
            FileInputStream inStream;
            try {
                inStream = new FileInputStream(input);
                FileOutputStream outStream = new FileOutputStream(output);
    
                encryptAndClose(inStream, outStream);   
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

代码的目的是创建一个zip文件,然后用AES加密生成的zip文件。代码可以成功地生成一个可以用WinZip或7zip压缩和解压缩的zip文件。

但是,当它试图加密生成的zip文件时,代码反而会导致文件(例如the crypt.zip)被破坏,并且不能被WinZip或7zip之类的程序打开。

如果可能的话,我希望在不使用zip4j的情况下这样做。我的代码和对代码的理解有什么问题吗?

这是我第一次使用加密技术,任何帮助都将不胜感激!

EN

回答 2

Stack Overflow用户

发布于 2022-09-07 14:49:23

如果首先创建ZIP,然后使用AES算法或其他算法加密ZIP文件,则输出文件将不再是ZIP。它不会遵循ZIP标准格式。所以,解压缩是不可能的。

您需要首先解密文件并取回原始的ZIP,然后才能使用任何知名的zip处理软件打开/解压缩原始zip。

加密ZIP文件会导致文件内的字节发生变化,导致软件无法识别文件头、必要的ZipEntry记录结构等。

最好的选择是在创建zip时提供一个密码,这样如果没有密码就不能解压缩。或加密原始文件,然后将加密的文件放入Zip中。但是,不要加密ZIP文件。

票数 1
EN

Stack Overflow用户

发布于 2022-10-06 16:38:44

Java不支持压缩文件加密。无论如何,它支持非常有限的活动与zip文件。您必须设法使您使用zip文件要容易得多。你可以检查zip4jvm

创建(或打开现有的)压缩存档,并使用AES 256位加密添加一些常规文件和/或目录。

代码语言:javascript
运行
复制
Path zip = Paths.get("filename.zip");
Collection<Path> paths = Arrays.asList(
        Paths.get("/bikes/ducati-panigale-1199.jpg"),
        Paths.get("/bikes/honda-cbr600rr.jpg"),
        Paths.get("/cars"),
        Paths.get("/saint-petersburg.jpg"));
ZipEntrySettings settings = ZipEntrySettings.builder()
                                            .encryption(Encryption.AES_256, "password".toCharArray())
                                            .build();
ZipIt.zip(zip).entrySettings(settings).add(paths);

要获得更多关于zip中AES加密的详细信息,可以查看AesEncoder.java

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73637361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档