繁体   English   中英

为什么RC4无法处理大量加密数据?

[英]Why is RC4 not able to handle large amount of encrypted data?

我有以下代码解密文件。

package encryption;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class Decrypter {

    private static final String PASSWORD = "t_9Y#i@eT[h3}-7!";
    private static final String KEY_ALGORITHM = "PBEWithMD5AndDES";
    private static final String CIPHER_ALGORITHM = "RC4"; //Using Salsa20 or HC256 solves the problem
    private static final String PROVIDER = "BC";

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        File inputFile = new File(args[0]);
        File outputFile = new File(args[1]);

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD.toCharArray()));

        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);

        InputStream inputStream = new FileInputStream(inputFile);
        OutputStream outputStream = new FileOutputStream(outputFile);

        CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);

        byte []byteBuffer = new byte[(int)inputFile.length()]; 
        cipherInputStream.read(byteBuffer);
        outputStream.write(byteBuffer); //Only 512bytes of decrypted data is written to file, the rest becomes null
        outputStream.close();
    }

}

我的问题是我做错了什么? RC4为什么不解密一个大小超过512字节的块。

RC4是流密码,因此它可以解码任意数量的数据。 您的问题是InputStreams不会大量读取。 通常,您会遍历read调用,直到没有更多数据可读取并使用一个小缓冲区为止。 请参阅read()文档

这可以实现为

while(true) {
    int numRead = cipherInputStream.read(byteBuffer);
    if(numRead == -1)
        break;
    outputStream.write(byteBuffer, 0, numRead);
}

@Michael Lowman有正确的答案,但我想我会展示另一种方法来宣传DataInputStream类的功能。

您可以使用DataInputStream.readFully()方法来读取所有内容,就像perl slurp一样。 在您的示例中,您可以使用此方法读入字节,然后将其写出并使用CipherOutputStream而不是CipherInputStream进行解密。

考虑以下片段作为示例:

    byte[] byteBuffer = new byte[(int) inputFile.length()];
    DataInputStream dis = new DataInputStream(inputStream);
    dis.readFully(byteBuffer);
    dis.close();
    CipherOutputStream cos = new CipherOutputStream(outputStream, cipher);
    cos.write(byteBuffer);
    cos.close();

InputStream.read仅返回一定数量的数据,应该循环播放直到流为空。 但是我建议您使用commons-io的org.apache.commons.io.FileUtils.copyInputStreamToFile(InputStream, File)复制流,而不要自己滚动...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM