Да, конечно, это возможно, но в этом случае вам нужно сохранить наличие концов строки. Затем вы можете создать метод decryptLine
, который будет заканчиваться, когда открытый текст состоит из окончания строки. Это, вероятно, потребует от вас расшифровки байта за байтом.
Если вы удалите любое указание строк, как вы в настоящее время делаете для открытого текста, то больше нет возможности видеть строки. Потоковый шифр зашифрует строки, но поскольку потоковый шифр не дополняет или не изменяет открытый текст другим способом, окончания строк исчезают, и нет других индикаторов, показывающих, где должны быть строки.
RC4 - старый небезопасный шифр. Гораздо хуже, использование RC4 путем повторного использования doFinal
поверх открытого текста настолько небезопасно, что любой сможет получить открытый текст. По сути, вы начинаете с фазы шифрования, которая представляет собой просто XOR с потоком ключей, генерируемым RC4, что позволяет проводить подобные атаки на повторно используемую временную панель.
Кроме того, если шифрование RC4 по строкам с линейным кодированием просто расширено с использованием update
, а не перезапущено с использованием doFinal
, тогда файл будет точно таким же, как двоичное кодирование файла. Другими словами, вы можете просто зашифровать весь файл.
Так что, кто бы ни попросил вас выполнить задачу и человек, который написал этот конкретный пример, похоже, не имеет ни малейшего представления о крипто.
Но да, иногда вы просто хотите увидеть какой-то код в учебных целях. В следующем коде функции API потока Java используются для чтения и записи строк, при этом используются CipherOutputStream
и CipherInputStream
, а также для шифрования и дешифрования двоичных данных.
Обратите внимание:
- вам понадобится один экземпляр класса для каждого файла, повторное использование экземпляра класса (или ключа) сделает код небезопасным, поскольку RC4 не использует IV;
- с помощью
BufferedReader
вы можете извлечь строки из зашифрованного текста после дешифрования, но учтите, что считыватель может расшифровать больше, чем просто строка в базовом буфере ;
- этот код плохо обрабатывает исключения (см. здесь о том, как правильно обрабатывать исключения крипто);
- это преобразует окончания строк в кодировку платформы по умолчанию (
"%n"
строка формата - которая действительно должна храниться в константе, но да);
- предполагается, что UTF-8 / совместимая кодировка для файлов.
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);
}
}