簡體   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