Intereting Posts
войти в wordpress Потерянное соединение с сервером MySQL при «считывании исходного пакета связи», системная ошибка: 0 при подключении к Mysql в cpanel Apache 2.4 с PHP 5.4: нет доступных mysql ODBC и SQL Server 2008: не можете использовать подготовленные заявления? $ stmt-> execute (): как узнать, была ли вставка db успешной? Передача необязательного параметра в PHP Функция Модель класса не найдена в Doctrine 2.2 + CodeIgniter 2.1 Рекомендация для пакетных запросов mysqli Измените файл конфигурации в скомпилированном установщике Inno Setup (пользовательский файл конфигурации для каждого загружаемого исполняемого файла) Уничтожить сеансы PHP на вкладке «Браузеры» Закрыть Коррекция печенья Если таблица mysql db не содержит строку с определенным идентификатором, добавьте данные в таблицу Закрытие сеанса после выполнения запроса к базе данных Можно ли использовать mixins в php Загрузка нескольких файлов в PHP с использованием HTML-формы или cURL

Шифрование в JavaScript и дешифрование с помощью PHP

Я шифрую свой пароль пользователя в JavaScript следующим образом:

var encryptedPassword = CryptoJS.AES.encrypt(password, "Secret Passphrase"); 

Он отлично работает, но теперь я пытаюсь расшифровать PHP на стороне сервера следующим образом:

  $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND); $decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, "Secret Passphrase", base64_decode($password), MCRYPT_MODE_CBC, $iv); 

он вообще не работает, расшифрованная строка пароля выглядит очень странно:

  string(64) "> OX2MS  댗v <$ ʕ  i ̄  _  P   \ կ= _6( m    ,4WT7  a" 

Вот текущее состояние моего кода в JavaScript после полезных комментариев:

  var encryptedPassword = CryptoJS.AES.encrypt(password, "Secret Passphrase"); var ivHex = encryptedPassword.iv.toString(); var ivSize = encryptedPassword.algorithm.ivSize; // same as blockSize var keySize = encryptedPassword.algorithm.keySize; var keyHex = encryptedPassword.key.toString(); var saltHex = encryptedPassword.salt.toString(); // must be sent var openSslFormattedCipherTextString = encryptedPassword.toString(); // not used var cipherTextHex = encryptedPassword.ciphertext.toString(); // must be sent 

Я посылаю saltHex и CipherTextHex на сервер PHP, и я использую mcrypt_decrypt () следующим образом:

  $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), $saltHex); $decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, "Secret Passphrase", base64_decode($cipherTextHex), MCRYPT_MODE_CBC, $iv); 

Он по-прежнему не работает с этим обновленным кодом.

Может ли кто-нибудь помочь мне правильно расшифровать функцию mcrypt_decrypt () PHP для простого метода шифрования AES? Я уверен, что я делаю что-то неправильно с шифрованием, режимом mcrypt и параметрами IV внутри моего метода mcrypt_decrypt (). Спасибо, если вы знаете.

Проблема в том, что в коде CryptoJS используется пароль для получения ключа и IV, который будет использоваться для шифрования AES, но mcrypt использует только ключ для шифрования / дешифрования. Эта информация должна быть передана php. Поскольку вы не хотите передавать пароль, вы должны вывести ключ и IV таким же образом в php.

Следующий код выводит ключ и IV из пароля и соли. Он смоделирован после кода в моем ответе здесь (для получения дополнительной информации).

 function evpKDF($password, $salt, $keySize = 8, $ivSize = 4, $iterations = 1, $hashAlgorithm = "md5") { $targetKeySize = $keySize + $ivSize; $derivedBytes = ""; $numberOfDerivedWords = 0; $block = NULL; $hasher = hash_init($hashAlgorithm); while ($numberOfDerivedWords < $targetKeySize) { if ($block != NULL) { hash_update($hasher, $block); } hash_update($hasher, $password); hash_update($hasher, $salt); $block = hash_final($hasher, TRUE); $hasher = hash_init($hashAlgorithm); // Iterations for ($i = 1; $i < $iterations; $i++) { hash_update($hasher, $block); $block = hash_final($hasher, TRUE); $hasher = hash_init($hashAlgorithm); } $derivedBytes .= substr($block, 0, min(strlen($block), ($targetKeySize - $numberOfDerivedWords) * 4)); $numberOfDerivedWords += strlen($block)/4; } return array( "key" => substr($derivedBytes, 0, $keySize * 4), "iv" => substr($derivedBytes, $keySize * 4, $ivSize * 4) ); } 

Соль генерируется во время шифрования в CryptoJS и должна быть отправлена ​​на php с зашифрованным текстом. Перед evpKDF соль должна быть преобразована в двоичную строку из шестнадцатеричной.

 $keyAndIV = evpKDF("Secret Passphrase", hex2bin($saltHex)); $decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $keyAndIV["key"], hex2bin($cipherTextHex), MCRYPT_MODE_CBC, $keyAndIV["iv"]); 

Если только сервер encryptedPassword.toString() был отправлен на сервер, то перед использованием необходимо разделить соль и фактический зашифрованный текст. Формат представляет собой проприетарный формат, совместимый с OpenSSL, причем первые 8 байтов являются «Salted__», а следующие 8 байтов – случайной солью, а остальные – фактическим зашифрованным текстом. Все вместе кодируется Base64.

 function decrypt($ciphertext, $password) { $ciphertext = base64_decode($ciphertext); if (substr($ciphertext, 0, 8) != "Salted__") { return false; } $salt = substr($ciphertext, 8, 8); $keyAndIV = evpKDF($password, $salt); $decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $keyAndIV["key"], substr($ciphertext, 16), MCRYPT_MODE_CBC, $keyAndIV["iv"]); // unpad (PKCS#7) return substr($decryptPassword, 0, strlen($decryptPassword) - ord($decryptPassword[strlen($decryptPassword)-1])); } 

То же самое можно сделать с расширением OpenSSL вместо Mcrypt:

 function decrypt($ciphertext, $password) { $ciphertext = base64_decode($ciphertext); if (substr($ciphertext, 0, 8) != "Salted__") { return false; } $salt = substr($ciphertext, 8, 8); $keyAndIV = evpKDF($password, $salt); $decryptPassword = openssl_decrypt( substr($ciphertext, 16), "aes-256-cbc", $keyAndIV["key"], OPENSSL_RAW_DATA, // base64 was already decoded $keyAndIV["iv"]); return $decryptPassword; } 

Вы не можете расшифровать со случайным вектором инициализации – вам нужно использовать тот же IV, за который были зашифрованы данные. Кроме того, IIRC, AES по умолчанию имеет 8-битное представление зашифрованных данных, которые необходимо будет тщательно обрабатывать при передаче по HTTP.