Всем привет!. Столкнулся с проблемой. Взял 2 функции шифрования и дешифрования с одного сайта. Код ниже.
define('ENCRYPTION_KEY', 'ab86d144e3f080b61c7c2e43');
// Encrypt
$plaintext = "Тестируем обратимое шифрование на php 7";
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, ENCRYPTION_KEY, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, ENCRYPTION_KEY, $as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
echo $ciphertext.'<br>';
// Decrypt
$c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$plaintext = openssl_decrypt($ciphertext_raw, $cipher, ENCRYPTION_KEY, $options=OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, ENCRYPTION_KEY, $as_binary=true);
if (hash_equals($hmac, $calcmac))
{
echo $plaintext;
}
Далее привёл их к виду
// Encrypt
function encrypt($text,$key)
{
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($text, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
$input = array("=", "b", "c", "d", "e", "f", "g", "j", "k", "y", "a");
$output = array("!№", "#", "|", "%", "+", "-", "_", ")", "$", "^", "&:&");
$ciphertext = str_replace($input, $output, $ciphertext);
return $ciphertext;
}
// Decrypt
function decrypt($hash,$key)
{
$input = array("=", "b", "c", "d", "e", "f", "g", "j", "k", "y", "a");
$output = array("!№", "#", "|", "%", "+", "-", "_", ")", "$", "^", "&:&");
$hash = str_replace($output, $input, $hash);
$c = base64_decode($hash);
var_dump($c);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
var_dump(hash_equals($hmac, $calcmac));
if (hash_equals($hmac, $calcmac))
{
return $plaintext;
}
}
Ключ генерирую следующим образом:
function generate()
{
$chars="0123456789ABCDEF";
$max=32;
$size=StrLen($chars)-1;
$password=null;
while($max--)
$password.=$chars[rand(0,$size)];
return $password;
}
Собственно в чем вопрос, в функции дешифрования строки есть условие ( hash_equals($hmac, $calcmac) ) , так вот, это условие в моём случае всегда возвращает False. Из-за этого функция ничего не возвращает, но в переменной $plaintext содержится уже расшифрованная строка и расшифрована она верно, но из-за этого условия она не возвращается. И теперь вопрос, почему условие возвращает false и можно ли убрать это условие и продолжить использовать функцию в таком виде?
Очевидно, что в процессе дополнительного кодирования/раскодирования зашифрованного сообщения Вы его изменяете. Дело в том, что RFC 4648 Base64 кодирования определяет такие символы:
Table 1: The Base 64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
А Ваш дополнительный кодировщик тоже использует замену на +. Отсюда и проблема, причем она плавающая, зависящая был ли в Base64 тексте + или нет.
Исправьте, например так:
// vvv
$output = array("!№", "#", "|", "%", "@", "-", "_", ")", "$", "^", "&:&");
Вот рабочий пример на ideone
Сборка персонального компьютера от Artline: умный выбор для современных пользователей