El cifrado y descifrado de archivos no funciona en Java [duplicado]
Quiero encriptar un archivo de video grande llamado de la manera largefile.mp4
más eficiente y luego desencriptarlo nuevamente, pero no funciona como se esperaba.
de hecho, no hay ningún error y los archivos se generan. pero el nuevo archivo generado es demasiado pequeño que el archivo principal.
aquí largefile.mp4
son 100mb pero newEncryptedFile.txt
son 107kb y newDecryptedFile.mp4
son 210 bytes
Cuál es el problema ?
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");
}
}
Respuestas
Lamento no haber inspeccionado su código porque está utilizando el ECB en modo NO SEGURO que ya no debería usarse en nuevos proyectos.
A continuación, encontrará un código de muestra para el cifrado y descifrado de archivos con AES en modo CBC. El programa genera una clave aleatoria para el cifrado y descifrado (con una clave fuera de la clave en codificación base64 para un mejor almacenamiento), genera un vector de inicialización aleatoria (IV) que se escribe al principio del archivo cifrado.
Para el descifrado, los primeros 16 bytes se leen como datos no cifrados, todos los demás datos pasan por el flujo de descifrado.
El cifrado se realiza en trozos de 8192 bytes con la amable ayuda de CipherOutput- / InputStream.
Advertencia de seguridad : el código no tiene ningún manejo de excepción y es solo para fines educativos. Tenga en cuenta que, para mayor seguridad, puede cambiar a un cifrado autenticado (por ejemplo, protegido con un HMAC o utilizando el modo GCM).
salida:
AES CBC 256 file encryption with CipherOutputStream
encryption key in base64 encoding: vTsd0E8MX3arfLRFjxZ58FSjkKxKYe32+rT5zCnJPVY=
result encryption: true
result decryption: true
código:
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);
}
}