Die Ver- und Entschlüsselung von Dateien funktioniert in Java nicht [doppelt]
Ich möchte eine große Videodatei verschlüsseln, die largefile.mp4
am effizientesten aufgerufen wird, und sie dann erneut entschlüsseln, aber dort funktioniert sie nicht wie erwartet.
Eigentlich gibt es keinen Fehler und die Dateien werden generiert. Die neu generierte Datei ist jedoch zu klein als die Hauptdatei.
Hier largefile.mp4
ist 100 MB, aber newEncryptedFile.txt
107 KB und das newDecryptedFile.mp4
ist 210 Bytes
Worin besteht das Problem ?
package fileenc;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
public class FileEncrypterDecrypter {
SecretKey key;
Cipher cipher;
public FileEncrypterDecrypter() {
try {
KeyGenerator keygen = KeyGenerator.getInstance("AES");
key = keygen.generateKey();
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
System.out.println(e);
}
}
public boolean fileEncrypt(String plainFile) {
try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(plainFile))){
cipher.init(Cipher.ENCRYPT_MODE, key);
FileOutputStream fs = new FileOutputStream("newEncryptedFile.txt");
CipherOutputStream out = new CipherOutputStream(fs, cipher);
byte[] byteSize = new byte[1024];
int numberOfBytedRead;
while ( (numberOfBytedRead = fis.read(byteSize)) != -1 ) {
out.write(numberOfBytedRead);
}
fis.close();
out.flush();
out.close();
System.out.println("Encryption done...");
return true;
} catch (IOException | InvalidKeyException e) {
}
return false;
}
public boolean fileDecrypt(String encryptedFile) {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("newDecryptedFile.mp4"))){
cipher.init(Cipher.DECRYPT_MODE, key);
FileInputStream fis = new FileInputStream(encryptedFile);
CipherInputStream in = new CipherInputStream(fis, cipher);
byte[] byteSize = new byte[1024];
int numberOfBytedRead;
while ( (numberOfBytedRead = in.read(byteSize)) != -1) {
bos.write(numberOfBytedRead);
}
System.out.println("Decryption done...");
bos.flush();
bos.close();
in.close();
return true;
} catch (IOException | InvalidKeyException e) {
}
return false;
}
public static void main(String[] args) throws FileNotFoundException, IOException {
FileEncrypterDecrypter fed = new FileEncrypterDecrypter();
fed.fileEncrypt("largefile.mp4"); // about 100 mb
fed.fileDecrypt("newEncryptedFile.txt");
}
}
Antworten
Es tut mir leid, dass ich Ihren Code nicht überprüft habe, da Sie die EZB im UNSECURE-Modus verwenden, die in neuen Projekten nicht mehr verwendet werden sollte.
Unten finden Sie einen Beispielcode für die Ver- und Entschlüsselung von Dateien mit AES im CBC-Modus. Das Programm generiert einen zufälligen Schlüssel zum Ver- und Entschlüsseln (mit einem Out-of-the-Key in der Base64-Codierung zur besseren Speicherung) und generiert einen zufälligen Initialisierungsvektor (IV), der am Anfang der verschlüsselten Datei geschrieben wird.
Bei der Entschlüsselung werden die ersten 16 Bytes als unverschlüsselte Daten gelesen, alle anderen Daten durchlaufen den Entschlüsselungsstrom.
Die Verschlüsselung erfolgt in Blöcken von 8192 Bytes mit freundlicher Genehmigung eines CipherOutput- / InputStream.
Sicherheitswarnung : Der Code hat keine Ausnahmebehandlung und dient nur zu Ausbildungszwecken. Bitte beachten Sie, dass Sie zur besseren Sicherheit möglicherweise zu einer authentifizierten Verschlüsselung wechseln (z. B. mit einem HMAC oder im GCM-Modus gesichert).
Ausgabe:
AES CBC 256 file encryption with CipherOutputStream
encryption key in base64 encoding: vTsd0E8MX3arfLRFjxZ58FSjkKxKYe32+rT5zCnJPVY=
result encryption: true
result decryption: true
Code:
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class AesCbcEncryptionWithRandomKeyCipherOutputStreamSoExample {
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException,
InvalidKeyException, InvalidAlgorithmParameterException {
System.out.println("AES CBC 256 file encryption with CipherOutputStream");
String uncryptedFilename = "plaintext.txt";
String encryptedFilename = "encrypted.enc";
String decryptedFilename = "decrypted.txt";
// generate random aes 256 key
byte[] encryptionKey = new byte[32];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(encryptionKey);
System.out.println("encryption key in base64 encoding: " + base64Encoding(encryptionKey));
boolean result;
// encryption
result = encryptCbcFileBufferedCipherOutputStream(uncryptedFilename, encryptedFilename, encryptionKey);
System.out.println("result encryption: " + result);
// decryption
result = decryptCbcFileBufferedCipherInputStream(encryptedFilename, decryptedFilename, encryptionKey);
System.out.println("result decryption: " + result);
}
public static boolean encryptCbcFileBufferedCipherOutputStream(String inputFilename, String outputFilename, byte[] key)
throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
// generate random iv
SecureRandom secureRandom = new SecureRandom();
byte[] iv = new byte[16];
secureRandom.nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFilename);
FileOutputStream out = new FileOutputStream(outputFilename);
CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
out.write(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] buffer = new byte[8096];
int nread;
while ((nread = in.read(buffer)) > 0) {
encryptedOutputStream.write(buffer, 0, nread);
}
encryptedOutputStream.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
public static boolean decryptCbcFileBufferedCipherInputStream(String inputFilename, String outputFilename, byte[] key) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
byte[] iv = new byte[16];
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFilename);
CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
FileOutputStream out = new FileOutputStream(outputFilename))
{
byte[] buffer = new byte[8192];
in.read(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
int nread;
while ((nread = cipherInputStream.read(buffer)) > 0) {
out.write(buffer, 0, nread);
}
out.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
private static String base64Encoding(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
}