2015-06-17 3 views
1

Я понимаю, что шифрование AES должно быть в блоках по 16, но у меня создалось впечатление, что с помощью Cipher.getInstance("AES/ECB/PKCS5PADDING"); для заполнения этого байта использовался массив байтов. Мой код ниже:IllegalBlockSizeException при использовании aes/ecb/pkcs5padding для расшифровки массива байтов

CipherUtils.java

private static byte[] key = { 
     0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 
};//"thisIsASecretKey"; 

public static byte[] EncryptByteArray(byte[] array) 
{ 
    try 
    { 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); 
     SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKey); 

     return (cipher.doFinal(array)); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 

    } 
    return null; 
} 

public static byte[] DecryptByteArray(byte[] array) 
{ 
    try 
    { 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); 
     SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
     cipher.init(Cipher.DECRYPT_MODE, secretKey); 

     return cipher.doFinal(array); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 

    } 
    return null; 
} 

Основная программа

 fis = new FileInputStream(path); 

     toDecrypt = new byte[fis.available()+1]; 

     int content; 
     int i = 0; 
     while ((content = fis.read()) != -1) { 

      // convert to byte and display it 
      toDecrypt[i] = (byte)content; 
      i += 1; 
     } 

     byte[] decryptedStr = CipherUtils.DecryptByteArray(toDecrypt); 

     FileOutputStream decryptedStream = new FileOutputStream(path); 
     decryptedStream.write (decryptedStr); 
     decryptedStream.close(); 

Файл в path был зашифрован с помощью функции в cipherutils.java и записываются в файл с использованием FileOutputStream.write

U pdate- Я создаю для Android с помощью Gradle.

+1

Начните с модульного тестирования ваших методов с помощью жестко закодированного ввода: шифрование и дешифрование результата должны привести к выходу, равному входу. После этого вы поймете, что шифрование и дешифрование работают нормально, и проблема в том, как вы пишете и читаете ваши файлы. Функция available() не возвращает длину файла. И даже если бы это было так, в массиве содержится дополнительный байт. Так что это не имеет смысла. –

+2

Пожалуйста, не используйте режим ECB. Это не семантически безопасно. Вы должны использовать по крайней мере режим CBC со случайным IV. В лучшем случае вы должны аутентифицировать зашифрованные тексты. Обычно это делается либо с использованием аутентифицированного режима, как GCM, либо с запуском зашифрованного текста через HMAC (encrypt-then-MAC). –

+0

... или работает * IV * и зашифрованный текст, хотя HMAC ... –

ответ

0

Успели что-то придумаем с помощью @ JonSkeet в ответ (спасибо!):

 File file = new File(path); 
     fis = new FileInputStream(file); 

     toDecrypt = new byte[(int)file.length()]; 
     fis.read(toDecrypt); 

     byte[] decrypted = CipherUtils.DecryptByteArray(toDecrypt); 
     FileOutputStream decryptedStream = new FileOutputStream(bookPath); 
     decryptedStream.write (decrypted); 
     decryptedStream.close(); 

Как он отметил, мне не следовало использовать метод available(). Также был намного лучший способ записи в файл быстрее, чем повторение каждого байта! Согласно комментариям, я также изменил шифрование на режим CBC со случайным IV.

3

Это проблема:

toDecrypt = new byte[fis.available()+1]; 

Во-первых, вы используете available() метод, который никогда не хорошей идеей. Далее, даже если предположить, что - это, возвращая длину файла, вы добавляете 1 к нему - почему? Конечно, вы хотите просто байты в файле.

Самый простой способ сделать это просто использовать Files.readAllBytes:

byte[] toDecrypt = Files.readAllBytes(Paths.get(path)); 
// TODO: Change the method name to follow Java conventions 
byte[] decrypted = CipherUtils.DecryptByteArray(toDecrypt); 
Files.write(Paths.get(path), decrypted); 

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

Я также настоятельно рекомендую пересматривают ваше исключение «обработки»:.

  • Catchi нг Exception почти всегда плохая идея
  • Вызов e.printStackTrace() и затем продолжается, как будто ничего не произошло почти всегда плохая идея
+0

Спасибо за это! Я получаю "ошибку: пакет java.nio.file не существует", но я на последней версии Java. Я использую Gradle 2.4 и плагин Android Tools версии 1.2.0. Извините, я на самом деле новичок в этом, и большая часть кода не моя - мой босс хочет, чтобы кто-то из сотрудников мог работать с Java! –

+0

@ DomHarris: Вы используете Android? Вы никогда не упоминали об этом нигде в вопросе - это определенно влияет на то, что доступно ... * пожалуйста * включайте важную информацию, например, при публикации. –

Смежные вопросы