使用 RSA 加密 - ZipException:条目大小无效

Encrypt with RSA - ZipException: invalid entry size

我正在编写一个程序,它接受来自控制台的输入——一个 zip 文件的名称、一个要制作的包含从第一个 zip 生成的加密文件的 zip 文件的名称和一个包含 public 键。每次流关闭时我都会遇到异常:

Exception in thread "main" java.util.zip.ZipException: invalid entry size (expected 11 but got 128 bytes)
at java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:288)
at java.util.zip.ZipOutputStream.finish(ZipOutputStream.java:361)
at java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:238)
at java.util.zip.ZipOutputStream.close(ZipOutputStream.java:378)
at javax.crypto.CipherOutputStream.close(CipherOutputStream.java:217)
at com.Main.main(Main.java:107)

我该如何解决这个问题?代码如下:

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;

public class Main {

public final static int BUFFER_SIZE = 1024;

public static String getPublicKeyString(String fileName){

    String key = new String();
    try {
        BufferedReader buf = new BufferedReader(new FileReader(fileName));
        key = buf.readLine();       
    } catch ( IOException e) {
        e.printStackTrace();
    }   

    return key.trim();
}

public static PublicKey makePublicKey(String stored) throws GeneralSecurityException {
    byte[] data = Base64.getDecoder().decode(stored);//Base64.decode(keyBytes, Base64.DEFAULT);
    X509EncodedKeySpec spec = new  X509EncodedKeySpec(data);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    return fact.generatePublic(spec);
}

public static void main(String[] args) throws Exception {

    Scanner scan = new Scanner(System.in);

    System.out.println("Enter type of operation:");
    String line = scan.nextLine();

    if(line.equals("encrypt")){
        // Reading from console
        System.out.println("Enter name of original ZIP file:");
        String originalZipFileName = scan.nextLine();

        System.out.println("Enter name of new ZIP file:");
        String newZipFileName = scan.nextLine();

        System.out.println("Enter name of file containg public key:");
        String publicKeyFileName = scan.nextLine();

        String publicKey = getPublicKeyString(publicKeyFileName);

        // Declaration

        ZipFile originalZipFile = new ZipFile(originalZipFileName);

        byte[] buffer = new byte[BUFFER_SIZE];

        ZipOutputStream newZipFile = new ZipOutputStream(new FileOutputStream(newZipFileName));

        Enumeration<? extends ZipEntry> zipEntries = originalZipFile.entries();

        //

        PublicKey key = makePublicKey(publicKey);
        //System.out.println(key.toString());
        //

        Cipher cipher = Cipher.getInstance("RSA");

        cipher.init(Cipher.ENCRYPT_MODE, key);

        while(zipEntries.hasMoreElements()){

            ZipEntry entry = zipEntries.nextElement();
            ZipEntry copy = new ZipEntry(entry);

            newZipFile.putNextEntry(copy);

            int read;

            InputStream input = originalZipFile.getInputStream(entry);

            CipherOutputStream cos = new CipherOutputStream(newZipFile, cipher);

            while((read = input.read(buffer)) != -1){
                cos.write(buffer, 0, read);
            }
            input.close();
            cos.close();
            newZipFile.closeEntry();

        }


    }
  }
}

RSA 只能用于加密相对少量的数据,小于 RSA 模数的字节大小。当您执行 cos.close() 时,包装的密码对象会调用其 doFinal() 方法,该方法会生成一个 IllegalBlockSizeException,它会被 CipherOutputStream 悄悄吞噬。然而,由于没有数据通过密码对象,ZipOutputStream 被搞砸了,所以它在关闭时抛出异常。

您不能按照您尝试的方式使用 RSA。