小编典典

RSA逐块加密对大于1kb的文件产生空白输出

java

我不会为AES或其他加密方式打开该线程,因为这是我将用于加密AES和其他加密方式的密钥的内容。我已经从StackOverflow和其他一些站点收集了一些代码,并对其进行了编辑,以使其适合我的程序。但是,在尝试使用RSA问题逐块加密时,我只能加密大小为1
KB的小型文本文件。文本文件的加密和解密工作正常。然而,加密图片和的任何文件 较大 超过1千字节会产生一个 空白的 加密文件。

我想问一下是否有人可以帮助我指出代码段导致大于1
KB的文件导致空白输出文件/加密文件的问题。这段代码适用于AES,但是我不确定为什么它不适用于RSA加密。问题开始于Encrypt_File它读取循环的某个地方。

码:

public static final String ALGORITHM = "RSA";
private static final short KEY_LENGTH = 1024;
private static final short KEY_BYTES = 32;
private static final String CIPHER_EXTENSION = ".cgfile";

public void Encrypt_File(Path path_fileToEncrypt) {
    //get file name and the new file name
    String fileName = path_fileToEncrypt.getFileName().toString();
    String encryptedFileName = fileName+CIPHER_EXTENSION;
    String pathToEncryptedFile = path_fileToEncrypt.getParent()+File.separator+encryptedFileName;

    //attempt to open the public key
    try (ObjectInputStream publicKeyFile = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE))) {
        //load the key
        PublicKey publicKey = (PublicKey) publicKeyFile.readObject();

        // load file to encrypt and inputstream
        FileInputStream fileInputStream = new FileInputStream(new File(path_fileToEncrypt.toString()));

        // init the cipher
        final Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        CipherOutputStream cos = new CipherOutputStream(new FileOutputStream(pathToEncryptedFile),cipher);
        byte[] buffer = new byte[KEY_BYTES];
        int count;
        while((count = fileInputStream.read(buffer))>0){
            cos.write(buffer, 0, count);
        }

        //close
        fileInputStream.close();
        cos.close();
        //delete fileToEncrypt since we have the encrypted file now
        DeleteFile(new File(path_fileToEncrypt.toString()));
        System.out.println("Finished encrypting "+ fileName +" It's new file name is "+ encryptedFileName);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public static void main(String[] args) {
    try {

        CGcipher rsaencrypt = new CGcipher();
        Path pathTosecret = Paths.get(System.getProperty("user.dir"), "pic.png");
        // Encrypt the string using the public key
        rsaencrypt.Encrypt_File(pathTosecret);
        //rsaencrypt.Decrypt_File(pathTosecret);

    } catch (Exception e) {
        System.out.println(e.toString());
    }
}

阅读 397

收藏
2020-11-26

共1个答案

小编典典

尽管RSA算法在内部已扩展"RSA/ECB/PKCS1Padding"为由Sun提供程序使用。但是,实际上并未使用ECB模式。它应该已经命名"RSA/None/PKCS1Padding"。因此RSA无法实现更大的数据,CipherOutputStream因为它未实现任何分组密码模式。

不幸的是CipherOutputStream有“吃”异常的讨厌习惯。这就是为什么您得到一个空字符串而不是一个清晰的警告的原因。


Java的问题之一是检查异常。尽管它们肯定有其好处,但特殊情况不应成为函数定义的一部分。检查异常是产生可靠/无错误代码的一种很好的方法,但却是错误的方法。

IOException流可能抛出的,这使它非常清楚。并非所有流实际上都执行I / O,因此异常是错误的。但是因为IOException是一个
检查异常, 所以它 必须write方法定义的一部分。另一方面,安全性例外具有称为的已 检查
基类GeneralSecurityException。这些异常 不能 由流抛出,因为它们没有在方法定义中定义。


现在可以解决此问题,例如创建一个secureWrite确实引发异常的其他方法。通常的write方法可能会抛出RuntimeException带有原始的新派生异常GeneralSecurityException。不过,这些解决方案似乎已经使密码流的设计者逃脱了。相反,他们选择完全删除这些异常,或者可能会IOException在预期出现其他异常的地方抛出该异常。

因此,应非常谨慎地使用密码流。用专有实现替换它们似乎是最好的。

2020-11-26