2016-10-04 8 views
1

Используя множество разных примеров на Stackoverflow и других сайтах, мне удалось создать рабочий класс Java для шифрования и дешифрования строк с использованием AES-128. Мне нужно расшифровать и зашифровать эти же строки в PHP, чтобы разрешить двухстороннюю связь, но используя mcrypt PHP, я получаю скремблированные и сломанные строки, которые не приближаются к тому, чего я пытаюсь достичь.Расшифровка AES-128 в PHP из данных, сгенерированных в Java

Вот источник Java (который завернут в функции):

 MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
     byte[] keyBytes = password.getBytes("UTF-8"); 
     digest.update(keyBytes); 
     keyBytes = Arrays.copyOf(digest.digest(), 16); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); 
     byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; 
     IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); 

     cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec); 
     byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText)); 

     return new String(decryptedBytes); 

Например, это будет возвращать dyHuhcYI3JIQ4BssSyJ3bjE/sQCOH+fWq2EujW579BU= с помощью ключа/пароля [email protected]~Dyd, и может быть расшифрован в Dit bericht is versleuteld! с тем же ключом.

В PHP я использую намного меньше кода, и я не уверен, где все идет не так. Я использую V1gbTVCCbQK7cknbbir5Gg== в качестве ключа для его дешифрования, который является кодировкой base64 для переменной keyBytes выше.

$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, base64_decode("V1gbTVCCbQK7cknbbir5Gg=="), base64_decode("vdyHuhcYI3JIQ4BssSyJ3bjE/sQCOH+fWq2EujW579BU="), MCRYPT_MODE_CBC, "0000000000000000"); 
var_dump($decrypted); 

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

+1

Трюк с криптографией заключается в том, что вы не хотите, чтобы он работал, вы хотите, чтобы он был безопасным. Вышеприведенный код или код в вашем ответе небезопасны; он не использует правильный вывод ключа, а нулевой IV не должен использоваться. Также отсутствует защита от целостности и аутентичности и - при использовании для одноранговой связи - она ​​также не будет конфиденциальной. –

+1

Лучше не использовать mcrypt, он является отказом, не обновлялся годами и не поддерживает стандартное дополнение PKCS # 7 (née PKCS # 5), только нестандартное нулевое заполнение, которое нельзя даже использовать с двоичным данные. В mcrypt есть много выдающихся [ошибок] (https://sourceforge.net/p/mcrypt/bugs/), относящихся к 2003 году. Вместо этого подумайте об использовании [defuse] (https://github.com/defuse/php-encryption) или [RNCryptor] (https://github.com/RNCryptor), они обеспечивают полное решение и поддерживаются и верны. – zaph

+0

@zaph Хорошее примечание. Я буду изучать эти библиотеки, поэтому я не должен это использовать. –

ответ

0

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

function hexToStr($hex) 
{ 
    $string = ''; 
    for ($i = 0; $i < strlen($hex) - 1; $i += 2) { 
     $string .= chr(hexdec($hex[$i] . $hex[$i + 1])); 
    } 
    return $string; 
} 
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, base64_decode($key), base64_decode($encrypted), MCRYPT_MODE_CBC, hexToStr('00000000000000000000000000000000')); 

Обратите внимание, что IV теперь, используя эту функцию вместо значения «0000000000000000».

+1

Ваш код по-прежнему небезопасен. Это вас не беспокоит? –

+0

Это действительно беспокоит меня @ luke. Я все еще думаю о том, как сделать связь между Java и PHP максимально безопасной и простой, используя сокеты. Он также должен быть простым для конечных пользователей; получение сертификатов не так просто. –

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

  • Нет связанных вопросов^_^