Java 如何对文件进行加密和解密?

Java 如何对文件进行加密和解密?,java,encryption,Java,Encryption,我使用CipherOutputStream对java中的文件进行加密和解密,但输入文件>117字节无法加密。 我使用RSA算法公钥长度为1024字节 cipher.init(Cipher.ENCRYPT_MODE, secKey); String cleartextFile = "cleartext.txt"; String ciphertextFile = "ciphertextSymm.txt"; FileInputStream fis = new FileInputStream(cle

我使用
CipherOutputStream
对java中的文件进行加密和解密,但输入文件>117字节无法加密。 我使用RSA算法公钥长度为1024字节

cipher.init(Cipher.ENCRYPT_MODE, secKey);

String cleartextFile = "cleartext.txt";
String ciphertextFile = "ciphertextSymm.txt";

FileInputStream fis = new FileInputStream(cleartextFile);
FileOutputStream fos = new FileOutputStream(ciphertextFile);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);

byte[] block = new byte[8];
int i;
while ((i = fis.read(block)) != -1) {
      cos.write(block, 0, i);
}
cos.close();

如何加密
输入
文件长度>117字节?

您不能使用RSA加密文件,因为RSA(更准确地说,RSA在Java中的实现)不允许您加密超过密钥长度的数据。对于1024位密钥,您只能加密1024位,也就是说128字节(由于填充原因,实际上要少一点)

在所有情况下,使用公钥算法(非对称加密)加密一大块数据都是不好的做法,主要原因有两个

  • 使用RSA加密大量数据没有实用、适当和安全的加密模式/填充(即这样做并不真正安全)

  • 公钥算法需要一个大密钥才能保证安全(1024位,2048位),因此比对称密钥算法(只需要128到256位密钥才能保证安全)慢得多

  • 如果您想了解为什么不应单独使用RSA加密大量数据的更多详细信息,请参阅以下两篇文章:

    如果要加密大量数据,标准的方法是生成会话密钥(一个以加密方式使用过的安全随机数)。您可以使用公钥加密会话密钥。然后使用未加密的会话密钥使用对称算法(如AES)加密文件(大量数据)。然后将加密会话密钥和加密数据一起存储在最终文件中。这就是PGP(或GnuPG)发送加密邮件的方式。SSL/TLS也以类似的方式工作

    最后,正确使用密码是复杂的(几乎任何东西都可能产生安全缺陷:加密模式、填充等),因此我建议您非常小心,确保您的代码将由精通密码的人员进行审查

    下面是一段代码,显示了一般过程:

    // 1. Generate a session key
    KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    keyGen.init(128)
    SecretKey sessionKey = keyGen.generateKey();
    
    // 2. Encrypt the session key with the RSA public key
    Cipher rsaCipher = Cipher.getInstance("RSA");
    rsaCipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey)
    byte[] encryptedSessionKey = rsaCipher.doFinal(sessionKey.getEncoded());
    
    // 3. Encrypt the data using the session key (unencrypted)
    Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    aesCipher.init(Cipher.ENCRYPT_MODE, sessionKey); <-- sessionKey is the unencrypted
    //                                                   session key.
    // ... use aesCipher to encrypt your data
    
    // 4. Save the encrypted data along with the encrypted 
    // session key (encryptedSessionKey).
    // PLEASE NOTE THAT BECAUSE OF THE ENCRYPTION MODE (CBC),
    // YOU ALSO NEED TO ALSO SAVE THE IV (INITIALIZATION VECTOR).
    // aesCipher.aesCipher.getParameters().
    //     getParametersSpec(IvParameters.class).getIV();
    
    //1。生成会话密钥
    KeyGenerator keyGen=KeyGenerator.getInstance(“AES”);
    keyGen.init(128)
    SecretKey sessionKey=keyGen.generateKey();
    // 2. 使用RSA公钥加密会话密钥
    Cipher rsapier=Cipher.getInstance(“RSA”);
    rsaciper.init(Cipher.ENCRYPT_模式,rsaPublicKey)
    字节[]encryptedSessionKey=rsaciper.doFinal(sessionKey.getEncoded());
    // 3. 使用会话密钥加密数据(未加密)
    Cipher AESChipher=Cipher.getInstance(“AES/CBC/PKCS5Padding”);
    
    aesciper.init(Cipher.ENCRYPT_模式,sessionKey);哇,太好了。问题是什么?RSA不是为加密文件而设计的。只要使用对称算法(AES、Blowfish等)加密您的文件,如果您需要对称加密,请仅在该对称密钥上使用RSA。这篇文章解释了为什么RSA不用于加密大数据(忽略效率原因):另一个相关问题:@nhahtdh:您认为您发现的两篇文章非常有趣,我将在我的帖子中链接它们(当然给你信用)。事实上,我链接到这两篇帖子是有原因的。我目前正在四处搜索,看看使用RSA加密大量数据是否存在任何安全漏洞。到目前为止,从我所发现的,这似乎不是一个问题,除了在第一个链接中的一些警告。“低效”的常见原因并不能真正让我相信这样做是不好的(除非应用程序要求速度快)。