我不会为AES或其他加密方式打开该线程,因为这是我将用于加密AES和其他加密方式的密钥的内容。我已经从StackOverflow和其他一些站点收集了一些代码,并对其进行了编辑,以使其适合我的程序。但是,在尝试使用RSA问题逐块加密时,我只能加密大小为1 KB的小型文本文件。文本文件的加密和解密工作正常。然而,加密图片和的任何文件 较大 超过1千字节会产生一个 空白的 加密文件。
我想问一下是否有人可以帮助我指出代码段导致大于1 KB的文件导致空白输出文件/加密文件的问题。这段代码适用于AES,但是我不确定为什么它不适用于RSA加密。问题开始于Encrypt_File它读取循环的某个地方。
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()); } }
尽管RSA算法在内部已扩展"RSA/ECB/PKCS1Padding"为由Sun提供程序使用。但是,实际上并未使用ECB模式。它应该已经命名"RSA/None/PKCS1Padding"。因此RSA无法实现更大的数据,CipherOutputStream因为它未实现任何分组密码模式。
"RSA/ECB/PKCS1Padding"
"RSA/None/PKCS1Padding"
CipherOutputStream
不幸的是CipherOutputStream有“吃”异常的讨厌习惯。这就是为什么您得到一个空字符串而不是一个清晰的警告的原因。
Java的问题之一是检查异常。尽管它们肯定有其好处,但特殊情况不应成为函数定义的一部分。检查异常是产生可靠/无错误代码的一种很好的方法,但却是错误的方法。
IOException流可能抛出的,这使它非常清楚。并非所有流实际上都执行I / O,因此异常是错误的。但是因为IOException是一个 检查异常, 所以它 必须 是write方法定义的一部分。另一方面,安全性例外具有称为的已 检查 基类GeneralSecurityException。这些异常 不能 由流抛出,因为它们没有在方法定义中定义。
IOException
write
GeneralSecurityException
现在可以解决此问题,例如创建一个secureWrite确实引发异常的其他方法。通常的write方法可能会抛出RuntimeException带有原始的新派生异常GeneralSecurityException。不过,这些解决方案似乎已经使密码流的设计者逃脱了。相反,他们选择完全删除这些异常,或者可能会IOException在预期出现其他异常的地方抛出该异常。
secureWrite
RuntimeException
因此,应非常谨慎地使用密码流。用专有实现替换它们似乎是最好的。