Симметричное шифрование в режиме CBC с использованием AES в Java - PullRequest
0 голосов
/ 05 декабря 2018

Я пытаюсь зашифровать и расшифровать данные в режиме CBC.Здесь я сначала читаю данные из файла plaintext.txt и записываю вывод, который является данными из plaintext.txt, в другой файл ciphertext.txt.При попытке расшифровки я зашифровал данные из файла в байты, но по какой-то причине он выдает ошибку.Может кто-нибудь помочь мне решить это?

Вот моя функция шифрования

  // The encryption Function CBC MODE

public static byte[] encrypt(String plainText, String key) throws Exception
{

    // Loading the secret key from the Key.txt file
    String fileName="../data/key.txt";
    try
    {
        BufferedReader in = new BufferedReader(new FileReader(fileName));         // Initialize a Buffer reader
        key = in.readLine();                                                     // Reading the data from txt file

    }
    //error message if the file is not found
    catch(FileNotFoundException ex)
    {
        System.out.println("Unable to open file '" + fileName + "'");
    }
    catch(IOException ex)
    {
        System.out.println("Error reading file '" + fileName + "'");
    }

    byte[] clean = plainText.getBytes();                                     //Getting the data in bytes from the plain text

    // Generating IV.
    //From the initialization vector, we create an IvParameterSpec which is required when creating the Cipher.
    int ivSize = 16;
    byte[] iv = new byte[ivSize];
    SecureRandom random = new SecureRandom();
    random.nextBytes(iv);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
    //System.out.println("The Iv is = "+ivParameterSpec);


    // Hashing key.
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.update(key.getBytes("UTF-8"));
    byte[] keyBytes = new byte[32];
    System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");


    // Encrypt.
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] encrypted = cipher.doFinal(clean);


    // Combine IV and encrypted part.
    byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
    System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
    System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);

    try
    {
       PrintWriter writer = new PrintWriter("../data/ciphertext.txt");
       writer.println(encryptedIVAndText);
       writer.close();
    }
    catch(Exception ex)
    {
        System.out.println(ex);
        System.out.println("File is not there");
    }

    return encryptedIVAndText;
}

А вот моя функция дешифрования.

// Decrypting fucntion CBC mode
public static String decrypt(byte[] encryptedIvTextBytes, String key) throws Exception
{

        FileInputStream encryptedTextFis = new FileInputStream("../data/ciphertext.txt");
    byte[] encText = new byte[encryptedTextFis.available()];
        int lol = encryptedTextFis.available();
        System.out.println("lol "+ lol);
    encryptedTextFis.read(encText);
    encryptedTextFis.close();
    //  encrypted = readFile("../data/ciphertext.txt", StandardCharsets.UTF_8).getBytes();
        encryptedIvTextBytes =  encText;
        //System.out.println("..........??????");
    String fileName="../data/key.txt";
    String fileName2="../data/ciphertext.txt";
    try
    {
        BufferedReader in = new BufferedReader(new FileReader(fileName));
        BufferedReader in2 = new BufferedReader(new FileReader(fileName2));
        key = in.readLine();
       // byte[] array = Files.readAllBytes(new File("/path/to/file").toPath());

    }
  //error message if the file is not found
    catch(FileNotFoundException ex)
    {
        System.out.println("Unable to open file '" + fileName + "'");
    }
    catch(IOException ex)
    {
        System.out.println("Error reading file '" + fileName + "'");
    }

    int ivSize = 16;
    int keySize = 32;
            //System.out.println("..........??????");
    // Extract IV.
    byte[] iv = new byte[ivSize];
    System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            System.out.println("..........??????");
    // Extract encrypted part.
    int encryptedSize = encryptedIvTextBytes.length - ivSize;
    byte[] encryptedBytes = new byte[encryptedSize];
    System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
            System.out.println("..........??????");
    // Hash key.
    byte[] keyBytes = new byte[keySize];
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(key.getBytes());
    System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

    // Decrypt.
    Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);              //Decrypting the encrypted data to a cipherblock data
    byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);                            // Decrypting the cipher dadat to Plaintext

    //Writing the output to a txt file
    try
    {
       PrintWriter writer = new PrintWriter("../data/result.txt");
       writer.println(new String(decrypted));
       writer.close();
    }
    catch(Exception ex)
    {
        System.out.println(ex);
        System.out.println("File is not there");
    }

    return new String(decrypted);                   //Returning the decrypted data to main function
}

Выход зашифрованного текстового файла имеет вид [B @ 3159c4b8.Я получаю ошибку ниже.enter image description here

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Вот код, который соответствует вашим потребностям:

/**
 * @param args the command line arguments
 */
public static void main(String[] args) throws Exception {
    String key = "abcdefghijklmop";// you could store it somewhere ...
    justToMakePlainTextFile();
    byte[] encrypted = encrypt("plaintext",key);
    decrypt(encrypted, key);

}


public static void justToMakePlainTextFile() {
    try {
        RandomAccessFile randomAccessFile = new RandomAccessFile("plaintext", "rw");
        FileChannel fileChannel = randomAccessFile.getChannel();
        String randomText = "Ho-ho-ho-ho! This is going to be a nice weekend and I am going to swim soon.";
        byte[] bytes = randomText.getBytes();
        ByteBuffer byteBuffer = ByteBuffer.allocate(randomText.length());//alocate new ByteBuffer of size randomeText.length
        byteBuffer.put(bytes);
        byteBuffer.flip();
        fileChannel.write(byteBuffer);
        randomAccessFile.close();
        fileChannel.close();

    } catch (IOException ioE) {
        System.err.println("JVM reported an error! Take a look: " + ioE);
    }
}


public static byte[] encrypt(String file, String key) throws Exception {

    RandomAccessFile reader = new RandomAccessFile(file, "r");
    FileChannel channel = reader.getChannel();

    int bufferSize = 1024;
    if (bufferSize > channel.size()) {
        bufferSize = (int) channel.size();
    }
    ByteBuffer buff = ByteBuffer.allocate(bufferSize);
    channel.read(buff);
    buff.flip();
    byte[] clean = buff.array();
    channel.close();
    reader.close();

    // Generating IV.
    int ivSize = 16;
    byte[] iv = new byte[ivSize];
    SecureRandom random = new SecureRandom();
    random.nextBytes(iv);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

    // Hashing key.
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.update(key.getBytes("UTF-8"));
    byte[] keyBytes = new byte[16];
    System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

    // Encrypt.
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] encrypted = cipher.doFinal(clean);

    // Combine IV and encrypted part.
    byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
    System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
    System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);

    return encryptedIVAndText;
}

public static void decrypt(byte[] encryptedIvTextBytes, String key) throws Exception {
    int ivSize = 16;
    int keySize = 16;

    // Extract IV.
    byte[] iv = new byte[ivSize];
    System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

    // Extract encrypted part.
    int encryptedSize = encryptedIvTextBytes.length - ivSize;
    byte[] encryptedBytes = new byte[encryptedSize];
    System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);

    // Hash key.
    byte[] keyBytes = new byte[keySize];
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(key.getBytes());
    System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

    // Decrypt.
    Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);

      try {
        RandomAccessFile randomAccessFile = new RandomAccessFile("ciphertext", "rw");
        FileChannel fileChannel = randomAccessFile.getChannel();
        byte[] bytes = decrypted;
        ByteBuffer byteBuffer = ByteBuffer.allocate(decrypted.length);//alocate new ByteBuffer of size randomeText.length
        byteBuffer.put(bytes);
        byteBuffer.flip();
        fileChannel.write(byteBuffer);
        randomAccessFile.close();
        fileChannel.close();

    } catch (IOException ioE) {
        System.err.println("JVM reported an error! Take a look: " + ioE);
    }

}

Файлы зашифрованного и открытого текста находятся в вашей домашней папке проектов.

0 голосов
/ 05 декабря 2018

Кажется, что исключение здесь:

System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);

Длина массива encryptedIvTextBytes равна 11 (как вы говорите, и результат показан также).Теперь вы хотите скопировать 16 (как длина iv) байтов из encryptedIvTextBytes.

Но основная причина заключается в том, что ваш метод сохранения зашифрованных данных недопустим.Зашифрованные данные могут содержать некоторые байты, которые не являются читаемым символом.При сохранении зашифрованных данных в виде строки такие байты удаляются.Чтобы решить эту проблему, смотрите комментарии @Maarten и @ MS90.

...