Почему мои две зашифрованные шестнадцатеричные строки расшифровываются в одну и ту же строку?

Я пытаюсь написать простую функцию шифрования и дешифрования 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/>";

?>

Тем не менее, я обнаружил, что одну и ту же строку можно расшифровать из двух разных зашифрованных шестнадцатеричных строк (случаи показаны в конце кода).

  1. Это нормально?

  2. Сколько таких строк существует? Как я могу найти?

  3. Кажется, что в конце первой расшифрованной строки есть какие-то скрытые символы. Они не отображаются в HTML (видимо видимо в режиме редактирования текста, очищено с помощью html sanitizer :(). В этом ли разница?

Вывод вышеуказанного скрипта в PHP 5.6.8:

Decrypting ===== 2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D4B97BD1710125FFD
Decrypted = Beli IM3 085728317777 30000
Decrypting ===== 2BF8F771E6FAE998AAE0C126B3FDD1994046C0498645E35D72FD337F5B6B334B
Decrypted = Beli IM3 085728317777 30000

1

Решение

Вы изменили только конец зашифрованного текста. Это содержит последний блок зашифрованного открытого текста. Однако обычно открытый текст не заканчивается на границе блока. В этом случае PHP будет выполнять заполнение нулями, пока не будет достигнута граница блока. Эти нулевые байты удаляются trim функция (вы должны использовать rtrim и только удалить \0 байт).

Теперь, если вы измените байты последнего блока, то расшифровка приведет к случайным байтам. Этот блок может начинаться — случайно — с тех же символов, за которыми следуют любые другие — возможно, непечатные — символы. В этом случае строка, напечатанная на экране, может отображаться одинаково.

Вы должны действительно:

  • использовать AES (MCRYPT_RIJNDAEL_128);
  • выполнить заполнение, совместимое с PKCS # 7;
  • использовать шифрование в режиме CBC со случайным IV;
  • добавьте этот IV к зашифрованному тексту;
  • добавить тег аутентификации (используя HMAC-SHA-1);
  • возможно закодируйте тег IV + шифротекст +.
3

Другие решения

Они разные, попробуйте это: 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».

1

По вопросам рекламы [email protected]