Enkripsi dan dekripsi file tidak berfungsi di java [duplikat]

Dec 15 2020

Saya ingin mengenkripsi file video besar yang disebut largefile.mp4paling efisien dan kemudian mendekripsi lagi, tetapi tidak berfungsi seperti yang diharapkan.

sebenarnya tidak ada kesalahan apa pun, dan file dibuat. tetapi file yang baru dibuat terlalu kecil dari file utama.

di sini largefile.mp4adalah 100mb tetapi newEncryptedFile.txt107kb dan newDecryptedFile.mp4210 byte

Apa masalahnya ?

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");
        
        
    }
}

Jawaban

1 MichaelFehr Dec 15 2020 at 17:06

Saya minta maaf karena saya tidak memeriksa kode Anda karena Anda menggunakan mode ECB TIDAK AMAN yang seharusnya tidak lagi digunakan dalam proyek baru.

Di bawah ini Anda menemukan kode sampel untuk enkripsi & dekripsi file dengan AES dalam mode CBC. Program ini menghasilkan kunci acak untuk enkripsi dan dekripsi (dengan kunci keluar dalam pengkodean base64 untuk penyimpanan yang lebih baik), menghasilkan vektor inisialisasi acak (IV) yang ditulis di awal file yang dienkripsi.

Untuk dekripsi, 16 byte pertama dibaca sebagai data yang tidak dienkripsi, semua data lainnya melalui aliran dekripsi.

Enkripsi dilakukan dalam potongan 8192 byte dengan bantuan baik dari CipherOutput- / InputStream.

Peringatan keamanan : kode tidak memiliki penanganan pengecualian dan hanya untuk tujuan pendidikan. Mohon dicatat bahwa untuk keamanan yang lebih baik, Anda dapat mengubah ke enkripsi terotentikasi (misalnya diamankan dengan HMAC atau menggunakan mode GCM).

keluaran:

AES CBC 256 file encryption with CipherOutputStream
encryption key in base64 encoding: vTsd0E8MX3arfLRFjxZ58FSjkKxKYe32+rT5zCnJPVY=
result encryption: true
result decryption: true

kode:

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);
    }
}