我需要使用RC4算法逐行加密文件,而无需对加密后得到的字节数组进行编码。我在这里看到了有关如何逐行加密的文章,它工作正常,但是当我尝试跳过编码步骤时,只有第一行被成功解密。是否可以仅将字节数组写入文件而不进行编码,并且能够成功解密该文件?
这是我尝试过的:
while ((line = br.readLine()) != null)
{
Cipher rc4 = Cipher.getInstance("RC4");
SecretKeySpec rc4Key = new SecretKeySpec(pwd.getBytes(), "RC4");
rc4.init(Cipher.ENCRYPT_MODE, rc4Key);
byte [] cipherText = rc4.doFinal(line.getBytes());
fos.write(cipherText);
fos.flush();
}
//decrypt file
byte [] decrypt = Files.readAllBytes(Paths.get(outputFile));
Cipher rc4d = Cipher.getInstance("RC4");
SecretKeySpec rc4dKey = new SecretKeySpec(pwd.getBytes(), "RC4");
rc4d.init(Cipher.DECRYPT_MODE, rc4dKey);
byte [] decrypted = rc4d.doFinal(decrypt);
String results = new String(decrypted);
System.out.println("Decrypted : " + results);
答案 0 :(得分:0)
是的,当然可以,但是在这种情况下,您需要保持行尾。然后,您可以创建方法decryptLine
,该方法将在明文由行尾组成时结束。但这可能需要您逐字节解密。
如果像现在对纯文本消息所做的那样删除行的任何指示,则将无法再看到行。流密码将对行进行加密,但是由于流密码不会填充或以其他方式更改明文,因此行尾也消失了,并且没有其他指示符指示行的位置。
RC4是旧的不安全密码。更糟糕的是,通过在明文上重用doFinal
来使用RC4的方法是如此不安全,以至于任何人都应该能够检索明文。基本上,您将从与RC4生成的密钥流进行XOR的加密阶段开始,这将允许像在重复使用的一次性键盘上那样进行攻击。
此外,如果仅使用update
对使用行编码的行进行RC4加密,而不是使用doFinal
重新启动,则文件将与文件的二进制编码相同。换句话说,您也可以简单地加密整个文件。
因此,无论是谁要求您执行任务 ,撰写此示例示例的人似乎都不了解加密技术。
但是,是的,有时您只是想看一些代码以供学习。以下代码使用Java流API中的功能来读取和写入行,同时使用CipherOutputStream
和CipherInputStream
并加密和解密二进制数据。
请注意:
BufferedReader
,您可以在解密后从密文中提取行,但是请注意,读取者可以解密不仅仅是对基础缓冲区中的行; "%n"
格式的字符串-应该确实存储在常量中,但可以); package com.stackexchange.so;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class LineStreamRC4 {
private SecretKey rc4Key;
public LineStreamRC4(SecretKey rc4Key) {
this.rc4Key = rc4Key;
}
public void encryptLineByLine(File in, File out) throws Exception {
Cipher c = Cipher.getInstance("RC4");
c.init(Cipher.ENCRYPT_MODE, rc4Key);
try (BufferedReader reader = new BufferedReader(
new FileReader(in, UTF_8));
CipherOutputStream cryptWriter = new CipherOutputStream(
new FileOutputStream(out), c)) {
String line;
while ((line = reader.readLine()) != null) {
line += String.format("%n");
cryptWriter.write(line.getBytes(UTF_8));
}
}
}
public void decryptLineByLine(File in, File out) throws Exception {
Cipher c = Cipher.getInstance("RC4");
c.init(Cipher.DECRYPT_MODE, rc4Key);
try (BufferedReader cryptReader = new BufferedReader(
new InputStreamReader(
new CipherInputStream(new FileInputStream(in), c), UTF_8));
FileWriter writer = new FileWriter(out, UTF_8)) {
String line;
while ((line = cryptReader.readLine()) != null) {
line += String.format("%n");
writer.write(line);
}
}
}
public static void main(String[] args) throws Exception {
File pt = new File("src/com/stackexchange/so/LineStreamRC4.java");
File ct = new File("bla.ct");
LineStreamRC4 rc4LineStream = new LineStreamRC4(new SecretKeySpec(new byte[16], "RC4"));
rc4LineStream.encryptLineByLine(pt, ct);
File pt2 = new File("bla.pt");
rc4LineStream.decryptLineByLine(ct, pt2);
}
}