Created
October 23, 2020 13:33
-
-
Save XOlegator/6a193bb9c8a93a9c15b1bc800e9a541b to your computer and use it in GitHub Desktop.
Обратимое шифрование: пример функции шифрования и расшифровки
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Utils | |
{ | |
/** | |
* Метод шифрует обратимым методом данные массива. | |
* Получившаяся строка пригодна для отправки в GET запросе. | |
* | |
* @param array $arData Массив данных, который нужно зашифровать | |
* @param string $encKey Секретный ключ (строка со случайными символами). | |
* | |
* @return string Шифрованая строка | |
*/ | |
public static function encryptArray(array $arData, string $encKey): string | |
{ | |
$result = ''; | |
if (!empty($arData)) { | |
// Сериализуем массив | |
$plaintext = serialize($arData); | |
$cipher = 'AES-128-CBC'; | |
$ivlen = openssl_cipher_iv_length($cipher); | |
if (false !== ($iv = openssl_random_pseudo_bytes($ivlen, $isCryptoStrong)) | |
&& false !== $isCryptoStrong | |
&& $encKey | |
) { | |
$ciphertext_raw = openssl_encrypt( | |
$plaintext, | |
$cipher, | |
$encKey, | |
$options = OPENSSL_RAW_DATA, | |
$iv | |
); | |
$hmac = hash_hmac( | |
'sha256', | |
$ciphertext_raw, | |
$encKey, | |
$as_binary = true | |
); | |
$result = urlencode( | |
base64_encode($iv . $hmac . $ciphertext_raw) | |
); | |
} | |
} | |
return $result; | |
} | |
/** | |
* Метод расшифровывает строку | |
* обратным образом для метода encryptArray() | |
* | |
* @param string $str Шифрованая строка | |
* @param string $encKey Секретный ключ (строка со случайными символами). | |
* | |
* @return array Массив данных, который получен при дешифрации | |
*/ | |
public static function decryptArray(string $str, string $encKey): array | |
{ | |
$result = []; | |
if ($str && $encKey) { | |
$str = urldecode($str); | |
$c = base64_decode($str); | |
$cipher = 'AES-128-CBC'; | |
$ivlen = openssl_cipher_iv_length($cipher); | |
if (function_exists('mb_substr')) { | |
$iv = mb_substr($c, 0, $ivlen, '8bit'); | |
$hmac = mb_substr($c, $ivlen, $sha2len = 32, '8bit'); | |
$ciphertext_raw = mb_substr($c, $ivlen + $sha2len, mb_strlen($c, '8bit'), '8bit'); | |
} else { | |
$iv = substr($c, 0, $ivlen); | |
$hmac = substr($c, $ivlen, $sha2len = 32); | |
$ciphertext_raw = substr($c, $ivlen + $sha2len); | |
} | |
$plaintext = openssl_decrypt( | |
$ciphertext_raw, | |
$cipher, | |
$encKey, | |
$options = OPENSSL_RAW_DATA, | |
$iv | |
); | |
$calcmac = hash_hmac( | |
'sha256', | |
$ciphertext_raw, | |
$encKey, | |
$as_binary = true | |
); | |
if (hash_equals($hmac, $calcmac)) { | |
$tmp = unserialize( | |
$plaintext, | |
['allowed_classes' => false] | |
); | |
if (false !== $tmp) { | |
$result = $tmp; | |
} | |
} | |
} | |
return $result; | |
} | |
} | |
// Данные пользователя, которые нужно зашифрованным сообщением переслать на сайт | |
$arParams = [ | |
'name' => '[email protected]', | |
'password' => '123456789', | |
'time' => time(), // Подмешиваем что-то, что всегда меняется | |
]; | |
// Секретный ключ, прописанный в приложении и в настройках сайта | |
$encKey = '15dbe906c75862983ea410aba4d14c47'; | |
$encString = Utils::encryptArray($arParams, $encKey); | |
// lx4RMo9MkMbZtgtb7W3C7ka1YKtKfY0t0uIxIeWJCgKkaZZpzinNGBIWmx61airdJlbELKlZSpzlq3Lcyw59b4Bkw8j5QW1JBxq7jNRF2G2z%2Faas4VOLc%2BxLA50E0QU6dViiSsypI20yxJ0UmUYDh2WuBmzt%2BTUwy1yVCI7%2FwOm6N%2FYczsTig63aOQ8jL9dl | |
echo '<pre>$encString = '; | |
print_r($encString); | |
echo '</pre>'; | |
// Расшифруем полученную пользовательскую нагрузку | |
$arDecryptParams = Utils::decryptArray($encString, $encKey); | |
// Array | |
//( | |
// [name] => [email protected] | |
// [password] => 123456789 | |
// [time] => 1603459617 | |
//) | |
echo '<pre>1. $arDecryptParams = '; | |
print_r($arDecryptParams); | |
echo '</pre>'; | |
if (empty($arDecryptParams)) { | |
// Параметры могут приходить по-разному: | |
// url-кодированые или не кодированые. | |
// Проверяем оба варианта | |
$arDecryptParams = Utils::decryptArray( | |
urlencode($arDecryptParams), | |
$encKey | |
); | |
echo '<pre>2. $arDecryptParams = '; | |
print_r($arDecryptParams); | |
echo '</pre>'; | |
} | |
if (!empty($arParams['name']) && !empty($arParams['password'])) { | |
echo '<pre>Удалось расшифровать нагрузку: это запрос от разрешённого приложения</pre>'; | |
} else { | |
echo '<pre>Не удалось расшифровать нагрузку: это недопустимое обращение к API</pre>'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment