简体   繁体   English

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

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

I have following code that decrypts a file. 我有以下代码解密文件。

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();
    }

}

My question is what am I doing wrong? 我的问题是我做错了什么? Why doesn't RC4 decrypt a block of size more than 512 bytes. RC4为什么不解密一个大小超过512字节的块。

RC4 is a stream cipher, so it can decode any amount of data. RC4是流密码,因此它可以解码任意数量的数据。 Your issue is that InputStreams are not read in massive chunks. 您的问题是InputStreams不会大量读取。 Normally you loop around the read call until there is no more data left to read and use a small buffer. 通常,您会遍历read调用,直到没有更多数据可读取并使用一个小缓冲区为止。 See the documentation of read() . 请参阅read()文档

This could be implemented as 这可以实现为

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

@Michael Lowman has the correct answer, but I'd thought I'd show another way just to advertise a feature of the DataInputStream class. @Michael Lowman有正确的答案,但我想我会展示另一种方法来宣传DataInputStream类的功能。

You can the read-it-all-in-one-go behavior, like a perl slurp, by using the DataInputStream.readFully() method. 您可以使用DataInputStream.readFully()方法来读取所有内容,就像perl slurp一样。 In your example, you can read in the bytes with this method, then write them out and decrypt by using as CipherOutputStream instead of a CipherInputStream. 在您的示例中,您可以使用此方法读入字节,然后将其写出并使用CipherOutputStream而不是CipherInputStream进行解密。

Consider the following fragment as an example: 考虑以下片段作为示例:

    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 only returns a certain amount of data, you are supposed to loop until the stream is empty. InputStream.read仅返回一定数量的数据,应该循环播放直到流为空。 However I suggest you use commons-io's org.apache.commons.io.FileUtils.copyInputStreamToFile(InputStream, File) to copy the streams rather than rolling your own... 但是我建议您使用commons-io的org.apache.commons.io.FileUtils.copyInputStreamToFile(InputStream, File)复制流,而不要自己滚动...

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

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