Зашифруйте и расшифруйте большой файл с AES - PullRequest
1 голос
/ 16 апреля 2020

Я пытаюсь зашифровать большой файл с помощью AES , затем расшифровать его и сравнить с оригиналом.

Этот класс суммирует работа. Он работает нормально для файлов .txt, , но НЕ для .mp3, .pdf и т. Д.

Помощь будет очень полезна.

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class LargeFileEncryptionTest7 {

    protected static String FOLDER_PATH = "C:/temp/";
    protected static String FILE = "some-large-file";
    protected static String EXT = ".mp3"; //Works for .txt, but not for .mp3 or .pdf

    public static void main(String[] args) throws Exception {

        //Load file to encrypt
        byte[] largeFileBytes = loadFile(FOLDER_PATH + FILE + EXT);
        String largeFileString = new String(largeFileBytes);

        //Encrypt file with AES
        AESUtils aesUtils = new AESUtils();
        byte[] secretKey = aesUtils.generateSecretKey();
        aesUtils.setSecretKey(secretKey);
        byte[] largeFileEncBytes = aesUtils.encrypt(largeFileString);

        //Save encrypted file
        saveFile(largeFileEncBytes, FOLDER_PATH + FILE + "-encrypted" + EXT);

        //Load encrypted file
        byte[] largeFileEncBytesToCheck = loadFile(FOLDER_PATH + FILE + "-encrypted" + EXT);

        //Decrypt file      
        byte[] largeFileBytesToCheck = aesUtils.decrypt(largeFileEncBytesToCheck);
        String largeFileStringToCheck = new String(largeFileBytesToCheck);

        //Save decrypted file
        saveFile(largeFileBytesToCheck, FOLDER_PATH + FILE + "-decrypted" + EXT);

        //Check strings
        //System.out.println("Original content: " + largeFileStringToCheck);
        if (largeFileStringToCheck.equals(largeFileString)) {
            System.out.println("OK  :-) ");
        } else {
            System.out.println("KO  :-( ");
        }                       
    }

    private static void saveFile(byte[] bytes, String fileName) throws Exception {
        FileOutputStream fos = new FileOutputStream(fileName);
        fos.write(bytes);
        fos.close();
    }

    private static byte[] loadFile(String fileName) throws Exception {
        FileInputStream fis = new FileInputStream(fileName);
        int numBtyes = fis.available();
        byte[] bytes = new byte[numBtyes];
        fis.read(bytes);
        fis.close();
        return bytes;
    }

}

Ответы [ 2 ]

3 голосов
/ 16 апреля 2020

Я вижу 2 проблемы с вашим решением:

Ваш код:

   int numBtyes = fis.available();
    byte[] bytes = new byte[numBtyes];
    fis.read(bytes);

Это на самом деле не гарантирует, что весь контент будет прочитан. Кроме того, при шифровании больших файлов (когда нет гарантии, что они поместятся в память), вы можете не захотеть читать весь контент в память.

При шифровании / дешифровании большого контента (без ограничений) вы можете захотеть использовать что-то вроде:

byte[] buff = new byte[BUFFERSIZE];
for(int readBytes=in.read(buff); readBytes>-1;readBytes=in.read(buff)) {
  out.write(cipher.update(buff,0, readBytes);
}
out.write(cipher.doFinal());

или взглянуть на CipherOutputStream и CipherInputStream

Сравнение другой проблемы:

String largeFileStringToCheck = new String(largeFileBytesToCheck);

Как уже отмечалось, это ужасный способ сравнения контента. В Java строка предназначена только для печатных символов, при попытке «зачеркнуть» любой байтовый массив применяется кодировка, а непечатные символы могут быть «выброшены».

для простого сравнения (с байтом) массивов), вы можете использовать Arrays.equals метод

При сравнении ДЕЙСТВИТЕЛЬНО большого контента (если вы не уверены, что он уместится в вашей памяти RAM), обычно это хорошая идея создайте сообщение ha sh и сравните хэши

Редактировать: если вы действительно хотите увидеть / распечатать / сравнить зашифрованный текст как строку, вы можете закодировать двоичные данные, вы можете иметь взглянем на кодировку Base64 .

0 голосов
/ 17 апреля 2020

Если кто-то заинтересован, я поставлю здесь окончательное решение.

Это вдохновлено некоторыми комментариями, которые сделали люди. В основном избегайте использования строк и работайте с байтом []:

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class LargeFileEncryptionTest11 {

    private static final String FOLDER_PATH = "C:/temp/";
    private static final String FILE = "some-large-file";
    private static final String EXT = ".pdf";

    private static final String ENCRYPTION_ALGORITHM = "AES";
    private static final int KEY_SIZE = 128; // 192 and 256 bits may not be available

    public static void main(String[] args) throws Exception {
        //Common stuff to encrypt/decrypt
        KeyGenerator kgen = KeyGenerator.getInstance(ENCRYPTION_ALGORITHM);
        kgen.init(KEY_SIZE); 
        SecretKey skey = kgen.generateKey();
        byte[] secretKey = skey.getEncoded();
        SecretKeySpec skeySpec = new SecretKeySpec(secretKey, ENCRYPTION_ALGORITHM);
        Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);

        //Load file to encrypt
        byte[] largeFileBytes = Files.readAllBytes(Paths.get(FOLDER_PATH + FILE + EXT));

        //Encrypt file
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] largeFileEncBytes = cipher.doFinal(largeFileBytes);

        //Save encrypted file
        Files.write(Paths.get(FOLDER_PATH + FILE + "-encrypted" + EXT), largeFileEncBytes);

        //Load encrypted file
        byte[] largeFileEncBytesToCheck = Files.readAllBytes(Paths.get(FOLDER_PATH + FILE + "-encrypted" + EXT));

        //Decrypt file      
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] largeFileBytesToCheck = cipher.doFinal(largeFileEncBytesToCheck);

        //Save decrypted file
        Files.write(Paths.get(FOLDER_PATH + FILE + "-decrypted" + EXT), largeFileBytesToCheck);

        //Compare results
        if (Arrays.equals(largeFileBytes, largeFileBytesToCheck)) {
            System.out.println("OK  :-) ");
        } else {
            System.out.println("KO  :-( ");
        }                       
    }

}
...