Значение шифрования Mcrypt js отличается от значения, полученного с помощью PHP mcrypt / Mcrypt JS decrypt, не работает для символов UTF-8

Я пытаюсь внедрить технологию шифрования / дешифрования mcrypt как на сервере, так и на PHP и на стороне клиента. Я пытаюсь использовать библиотеку mcrypt.js на данный момент как:

 <?php $key = 'testtesttesttesttesttesttesttest'; function string_encrypt($string, $key) { $crypted_text = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_ECB ); return base64_encode($crypted_text); } function string_decrypt($encrypted_string, $key) { $decrypted_text = mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, base64_decode($encrypted_string), MCRYPT_MODE_ECB ); return trim($decrypted_text); } echo 'Provided Text: '.$test_str = 'This is test message.'; echo '<br />'; echo 'Encyrpted Value: '.$enc_str = string_encrypt($test_str, $key); echo '<br />'; echo 'Decrypted Value: '.string_decrypt($enc_str, $key); echo '<br />'; ?> <script src='rijndael.js'></script> <script src='mcrypt.js'></script> <script src='base64v1_0.js'></script> <script lang='javascript'> var enc_str = mcrypt.Encrypt('<?php echo $test_str ?>',''); enc_str = B64.encode(enc_str); alert(enc_str); // I don't get this same as encypted PHP text. ie $enc_str var dec_str = B64.decode('<?php echo $enc_str ?>'); alert(mcrypt.Decrypt(dec_str,'')); // I don't get this same as decypted PHP text. // ie string_decrypt($enc_str) </script> 

Я использовал эти следующие частные vars в библиотеке mcrypt.js.

  var cMode='ecb'; var cCipher='rijndael-256'; var cKey='testtesttesttesttesttesttesttest'; //I am providing the same key 

Как я уже отмечал выше, почему enc_str не равен $enc_str и почему он является mcrypt.Decrypt('<?php echo $enc_str ?>', '') Не равным string_decrypt($enc_str, $key) ?



Обновленный вопрос:

Я попробовал кодирование / декодирование base64 и даже hex2bin / bin2hex для анализа этих строк, но эти два результата дали следующие результаты:


Использование Hex2bin / Bin2hex

Результат PHP:

 Provided Text: This is test message. Encyrpted Value: a51e970427ec8f666a5684cc1712ad03b29889cc10f4ccbf55733564d11c0386 Decrypted Value: This is test message. 

Результат JS:

 Provided Text:This is test message. Mcrypted value:¥'ìfjV̲ÌôÌ¿Us5dÑ Encyrpted Value:a51e970427ec8f666a5684cc1712ad03b29889cc10f4ccbf55733564d11c0386 After Hex to Bin Text:¥'ìfjV̲ÌôÌ¿Us5dÑ Decrypted Value:This is test message.            /*These diamond with question mark is produced while decypting the value.*/ 

Использование Base64 encode / decode:

Результат PHP:

 Provided Text: This is test message. Mcrypt encrypted value : ¥—'ìfjV„̲˜‰ÌôÌ¿Us5dц /* Here mcrypted value provided by JS and PHP is different That is causing to produce different value at two ends */ Encyrpted Value: pR6XBCfsj2ZqVoTMFxKtA7KYicwQ9My/VXM1ZNEcA4Y= Decrypted Value: This is test message. 

Результат JS:

 Provided Text:This is test message. Mcrypted value:¥'ìfjV̲ÌôÌ¿Us5dÑ Encyrpted Value:wqUewpcEJ8Oswo9malbChMOMFxLCrQPCssKYwonDjBDDtMOMwr9VczVkw5EcA8KG After Base64 Decode:¥'ìfjV̲ÌôÌ¿Us5dÑ    Decrypted Value:This is test message.           bFaêF«+JéÓ!ÆÖ 

И в обоих случаях содержимое UTf-8 не может быть расшифровано на конце JS.


* Ссылки: *

Библиотека Mcrypt JS

Библиотека базы Base64

Related of "Значение шифрования Mcrypt js отличается от значения, полученного с помощью PHP mcrypt / Mcrypt JS decrypt, не работает для символов UTF-8"

Основная проблема заключается в том, что ваши функции string_encrypt и string_decrypt PHP не имеют доступа к переменной $key , поэтому для ключа шифрования mcrypt_encrypt используется \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 . См. Этот вопрос для объяснения. PHP должен сообщить уведомление о том, что key не определен, возможно, вы отключили отчет об ошибках? Выполните эхо-ключ изнутри функции шифрования, чтобы подтвердить это.

Другая проблема – ошибка в библиотеке JS Mcrypt. Эта библиотека заполняет ключ шифрования с помощью \0 если длина ключа меньше 32 байт, проблема в том, что это не так, как функция PHP mcrypt_encrypt ключ. Функция mcrypt_encrypt ключ до ближайшей допустимой длины ключа (16, 24 или 32 байта). Проблема в mcrypt.js находится в строках 63 и 64, измените это:

 if(key.length<32) key+=Array(33-key.length).join(String.fromCharCode(0)); 

к этому:

 if(key.length<16) key+=Array(17-key.length).join(String.fromCharCode(0)); else if(key.length<24 && key.length>16) key+=Array(25-key.length).join(String.fromCharCode(0)); else if(key.length<32 && key.length>24) key+=Array(33-key.length).join(String.fromCharCode(0)); 

Теперь мы можем подтвердить исправление …

PHP:

 function string_encrypt($string) { $crypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, "", $string, MCRYPT_MODE_ECB); return $crypted_text; } $test_str = "This is test message to be encrypted."; $enc_str = string_encrypt($test_str); echo bin2hex($enc_str); Output: f98fca4ddc4c10d6cd47df56b081b78566ee4facbcf2254b46f7809d9b255529d2078f28b150e802d72818be1888536fac6219f6ce7b9d9332a24afa09288f0e 

Javascript:

 function toHex(str) { var hex = ''; for(var i=0;i<str.length;i++) { var val = ''+str.charCodeAt(i).toString(16); if(val.length == 1) hex += '0'+val; else hex += val; } return hex; } var enc_str = mcrypt.Encrypt("This is test message to be encrypted.", "", "", "rijndael-256", "ecb"); alert(toHex(enc_str)); Output: f98fca4ddc4c10d6cd47df56b081b78566ee4facbcf2254b46f7809d9b255529d2078f28b150e802d72818be1888536fac6219f6ce7b9d9332a24afa09288f0e 

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

Итак, чтобы все работало …

 <?php $key = 'testtesttesttesttesttesttesttest'; function string_encrypt($string, $key) { $crypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_ECB); return $crypted_text; } function string_decrypt($encrypted_string, $key) { $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted_string, MCRYPT_MODE_ECB); return trim($decrypted_text); } echo $test_str = 'This is test message to be encrypted.'; echo '<br />'; $enc_str = string_encrypt($test_str, $key); echo bin2hex($enc_str); echo '<br />'; echo string_decrypt($enc_str, $key); echo '<br />'; ?> <script src='rijndael.js'></script> <script src='mcrypt.js'></script> <script lang='javascript'> function toHex(str) { var hex = ''; for(var i=0;i<str.length;i++) { var val = ''+str.charCodeAt(i).toString(16); if(val.length == 1) hex += '0'+val; else hex += val; } return hex; } function hexToString (hex) { var str = ''; for (var i=0; i<hex.length; i+=2) { str += ''+String.fromCharCode(parseInt(hex.charAt(i)+hex.charAt(i+1), 16)); } return str; } var enc_str = mcrypt.Encrypt('<?php echo $test_str ?>', '', 'testtesttesttesttesttesttesttest', 'rijndael-256', 'ecb'); alert(toHex(enc_str)); alert(mcrypt.Decrypt(hexToString('<?php echo bin2Hex($enc_str) ?>'), '', 'testtesttesttesttesttesttesttest', 'rijndael-256', 'ecb').replace(/\x00+$/g, '')); </script> 

Еще несколько заметок …

  1. Вы не можете trim вывод функции string_encrypt . Это приведет к удалению ведущих или завершающих нулей, которые сделают так, что вы не сможете расшифровать вывод.
  2. Режим ECB небезопасен, и вы действительно не должны его использовать. CBC – это путь. CBC требует IV, а IV должен быть одинаковым как для шифрования, так и для дешифрования.
  3. Шифрование Javascript не безопасно по разным причинам, учитывая ваше использование, каждый может просто просмотреть источник страниц или отладить запущенный javascript, чтобы получить ключ шифрования. Прочтите ссылку, размещенную ntoskrnl в комментариях к вашему вопросу.

Обновить:

Проблема с кодировкой Base64 возникает из-за того, что используемая библиотека не работает с двоичными данными. Это довольно распространенная проблема для JavaScript-библиотек Base64. Вместо этого я бы рекомендовал использовать эту библиотеку .

Что касается конечных символов при расшифровке с помощью javascript, вам нужно обрезать дешифрованный вывод. Вы делаете это в своем методе PHP string_decrypt , но не в своем javascript. Вы можете обрезать дешифрованный вывод, заменив регулярное выражение на все символы \0 в конце строки.

Пример:

 mcrypt.Decrypt(dec_str,'').replace(/\x00+$/g, '') 

Я должен был включить это в свое первоначальное сообщение, но я не заметил символов \0 в выходе, потому что поле предупреждения FF не отображает их. Извини за это.

Наконец, я заметил еще одну ошибку в JS-библиотеке Mcrypt. Строки с 41 по 47:

 var ciphers={ // block size, key size "rijndael-128" :[ 16, 32], "rijndael-192" :[ 24, 32], "rijndael-256" :[ 32, 32], "serpent" :[ 16, 32], "twofish" :[ 16, 32], } 

Обратите внимание на запятую в конце строки «twofish». Firefox и Chrome, похоже, не возражают против этого, но IE8 сообщит об ошибке и не сможет загрузить библиотеку mcrypt из-за этого. Чтобы исправить проблему, выполните следующие действия:

 "twofish" :[ 16, 32], 

чтобы:

 "twofish" :[ 16, 32] 

Что я сделал:

 <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <?php $key = '12345678911234567892123456789312'; function string_encrypt($string, $key) { $crypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_ECB); return base64_encode($crypted_text); } function string_decrypt($encrypted_string, $key) { return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($encrypted_string), MCRYPT_MODE_ECB); } echo 'Provided Text: <br />' . $test_str = 'this is test काठमाडौं - राष्ट्रिय सुरक्षा परिषद्ले आसन्न संविधानसभा चुनावको सुरक्षामा नेपाली सेना खटाउने निर्णय गरेको छ। मंगलबार साँझ बसेको परिषद् बैठकले सुरक्षा अवस्था संवेदनशील भएको कारण देखाउँदै सात वर्षपछि सेना परिचालनका लागि मन्त्रिपरिषदसमक्ष सिफारिस गर्ने निर्णय गरेको हो। this is test'; echo '<br />';echo '<br />'; echo 'Encrypted Value: <br />' . $enc_str = string_encrypt($test_str, $key); echo '<br />';echo '<br />'; echo 'Decrypted Value: <br />' . string_decrypt($enc_str, $key); echo '<br />';echo '<br />'; ?> <script src='stringcoders.base64.js'></script> <script src='rijndael.js'></script> <script src='mcrypt.js'></script> <script lang='javascript' charset="utf-8"> var is_IE = /*@cc_on!@*/false; var message = ''; var str = '<?php echo $test_str ?>'; (is_IE) ? (message+= 'Provided Text:' + str) : console.log('Provided Text: \n' + str); str = unescape(encodeURIComponent(str)); /* I added this. Converted to ISO Latin before encryting and vice versa on decryption. Though don't know how this made work. */ var enc_str = mcrypt.Encrypt(str, ''); enc_str = base64.encode(enc_str); (is_IE) ? (message+= 'Encrypted Value:' + enc_str) : console.log('\nEncyrpted Value:\n' + enc_str); var dec_str = base64.decode(enc_str); dec_str = mcrypt.Decrypt(dec_str, '').replace(/\x00+$/g, ''); dec_str = decodeURIComponent(escape(dec_str)); (is_IE) ? (message+= 'Decrypted Value:' + dec_str) : console.log('\nDecrypted Value:\n' + dec_str); (is_IE) ? alert(message) : ''; </script>