Я пытаюсь написать простую функцию шифрования и дешифрования mcrypt tripledes (код ниже взят из http://php.net/manual/en/function.mcrypt-encrypt.php и доработано).
<?php
class Cipher {
private $securekey, $iv;
private $val;
function __construct($textkey) {
$this->securekey = $textkey;
$this->iv = mcrypt_create_iv(24);
}
function decrypt_hex($input){
$bin = hex2bin($input);
return trim(mcrypt_decrypt("tripledes", $this->securekey, $bin, MCRYPT_MODE_ECB, $this->iv));
}
function encrypt_hex($input){
$this->val = mcrypt_encrypt("tripledes", $this->securekey, $input, MCRYPT_MODE_ECB, $this->iv);
return strtoupper(bin2hex($this->val));
}
}
$cipher = new Cipher('123456789012345678901234');
$text = "2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D4B97BD1710125FFD";
echo "Decrypting ===== $text<br/>";
$dec = $cipher->decrypt_hex($text);
echo "Decrypted = $dec<br/>";
$text = "2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D72FD337F5B6B334B";
echo "Decrypting ===== $text<br/>";
$dec = $cipher->decrypt_hex($text);
echo "Decrypted = $dec<br/>";
?>
Тем не менее, я обнаружил, что одну и ту же строку можно расшифровать из двух разных зашифрованных шестнадцатеричных строк (случаи показаны в конце кода).
Это нормально?
Сколько таких строк существует? Как я могу найти?
Кажется, что в конце первой расшифрованной строки есть какие-то скрытые символы. Они не отображаются в HTML (видимо видимо в режиме редактирования текста, очищено с помощью html sanitizer :(). В этом ли разница?
Вывод вышеуказанного скрипта в PHP 5.6.8:
Decrypting ===== 2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D4B97BD1710125FFD
Decrypted = Beli IM3 085728317777 30000
Decrypting ===== 2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D72FD337F5B6B334B
Decrypted = Beli IM3 085728317777 30000
Вы изменили только конец зашифрованного текста. Это содержит последний блок зашифрованного открытого текста. Однако обычно открытый текст не заканчивается на границе блока. В этом случае PHP будет выполнять заполнение нулями, пока не будет достигнута граница блока. Эти нулевые байты удаляются trim
функция (вы должны использовать rtrim
и только удалить \0
байт).
Теперь, если вы измените байты последнего блока, то расшифровка приведет к случайным байтам. Этот блок может начинаться — случайно — с тех же символов, за которыми следуют любые другие — возможно, непечатные — символы. В этом случае строка, напечатанная на экране, может отображаться одинаково.
Вы должны действительно:
MCRYPT_RIJNDAEL_128
);Они разные, попробуйте это: var_dump($dec1 === $dec2);
который возвращается ложный.
Также echo strlen($dec1);
возвращается 32 а также echo strlen($dec2);
возвращается 27.
Обновить:
Выяснили, что у них разные кодировки. При этом они имеют разные размеры:
var_dump(mb_detect_encoding($dec1));
возвращает строку (5)UTF-8,«. Когда var_dump(mb_detect_encoding($dec2));
возвращает строку (5)ASCII».