2014-11-05 3 views
1

Я много искал, но я не нашел хорошего решения, как решить эту проблему. У меня есть приложение, которое должно расшифровать длинную шестнадцатеричную строку с помощью AES 256.Шифровать и расшифровывать с помощью шестнадцатеричной строки

Чтобы проверить это, я создал тестовый метод, который шифрует длинный текст в шестнадцатеричный код, а затем преобразовывает его и расшифровывает.

Если я запустил этот метод, я всегда получаю следующую ошибку: Учитывая, что последний блок неправильно заполнен. Я получаю эту ошибку в методе дешифрования.

Метод испытания выглядит так:

@Test 
public void testEncAndDecRequestWithHexString() throws UnsupportedEncodingException { 
    CryptoHelper cryptoHelper = new CryptoHelper("AES256"); 
    String paramStr = "ABCB28BCEE5947B8AECE3386871EC0DF&{D5CA99D2-506B-4864-8971-E87821D6B105}&7523429"; 

    //encrypt the param string 
    byte[] paramByteEnc = cryptoHelper.encryptBytesToBytes(paramStr.getBytes("ASCII"), PARAM_KEY, PARAM_IV); 

    //convert it to hex 
    String encryptedHexStr = cryptoHelper.byteArrayToHexStr(paramByteEnc); 

    //convert it back to a byte array 
    byte[] encryptedHexBytes = cryptoHelper.hexStrToByteArray(encryptedHexStr); 

    // decrypt it 
    byte[] paramByteDecrypted = cryptoHelper.decryptBytesToBytes(encryptedHexBytes, encryptedHexBytes.length, PARAM_KEY, PARAM_IV); 

    String decryptedStr = new String(paramByteDecrypted); 

    assertEquals("ABCB28BCEE5947B8AECE3386871EC0DF&{D5CA99D2-506B-4864-8971-E87821D6B105}&7523429", decryptedStr); 
} 

CryptHelper класс имеет следующие методы:

@Override 
public byte[] encryptBytesToBytes(byte[] plainData, byte[] key, byte[] iv) { 
    try { 
     initCipher(Cipher.ENCRYPT_MODE, key, iv); 
     return aesCipher.doFinal(plainData); 

    } catch (IllegalBlockSizeException | BadPaddingException e) { 
     log.severe(e.getMessage()); 
    } 

    return null; 
}  

@Override 
public byte[] decryptBytesToBytes(byte[] encryptedBytes, int length, 
     byte[] key, byte[] iv) { 
    try { 
     initCipher(Cipher.DECRYPT_MODE, key, iv); 
     return aesCipher.doFinal(encryptedBytes, 0, length); 
    } catch (IllegalBlockSizeException | BadPaddingException e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

private void initCipher(int mode, byte[] keyBytes, byte[] ivBytes) { 
    try { 

     // create shared secret and init cipher mode 
     SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); 
     aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     aesCipher.init(mode == Cipher.ENCRYPT_MODE ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(ivBytes)); 
    } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) { 
     e.printStackTrace(); 
    } 
} 

public String byteArrayToHexStr(byte[] encrypted) { 
    StringBuilder hex = new StringBuilder(); 
    for (byte b : encrypted) { 
     hex.append(String.format("%02X", b)); 
    } 
    return new String(hex.toString()); 
} 

public byte[] hexStrToByteArray(String hex) { 
    StringBuilder sb = new StringBuilder(); 

    for (int i = 0; i < hex.length() - 1; i += 2) { 
     String output = hex.substring(i, (i + 2)); 
     int decimal = Integer.parseInt(output, 16); 
     sb.append((char) decimal); 
    } 

    String temp = sb.toString(); 
    return temp.getBytes(); 
} 

Я использовал тот же ключ и вектор инициализации для процесса расшифровки так что проблема не неправильный ключ или вектор инициализации. Я также уверен, что каждая функция здесь выполняет свою работу правильно. Если вы не используете функции hexStrToByteArray() и byteArrayToHexStr() и просто используете зашифрованный байт для дешифрования, это не проблема. Я думаю, что есть проблема с кодировкой/декодированием, но я понятия не имею, как обрабатывать ее в java. Если я использую getBytes («UTF-8») и новую String (byte [], «UTF-8»), я получаю исключение IllegalBlockSizeException.

Надеюсь, вы поможете мне узнать, правильно ли я нахожусь и что я сделал неправильно.

+0

'hexString.append (Integer.toHexString (0xFF & digestBytes [я]));' Это, как я скрытый байт до шестнадцатеричного. –

+1

Не знаете, есть ли проблема ** ** **, но ваш 'byteArrayToHexStr/hexStrToByteArray' неправильно обрабатывает отрицательные значения. –

+0

@DavidSoroko: byteArrayToHexStr выглядит корректно, другой метод выглядит неправильно. –

ответ

3

Это ясное указание, что вы не должны писать библиотечные функции, если они уже определены. Вместо этого используйте шестнадцатеричный кодек из Bouncy Castle, Guava или Apache codec (пока Oracle, наконец, не увидит свет и не предоставит его в пакете java.util).

Если вы осуществить это самостоятельно, пожалуйста, не путайте символов для байтов:

public byte[] hexStrToByteArray(String hex) { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(hex.length()/2); 

    for (int i = 0; i < hex.length(); i += 2) { 
     String output = hex.substring(i, i + 2); 
     int decimal = Integer.parseInt(output, 16); 
     baos.write(decimal); 
    } 
    return baos.toByteArray(); 
} 
+0

Вы что, шутите? Просто заменил StringBuilder ByteArrayOutputStream, и тогда все работает нормально? Хорошо спасибо большое! : D – user1885888