Шифрование / Расшифровка с использованием mcrypt

Попытка добиться шифрования и дешифрования с использованием следующей стратегии, но в конечном итоге, в основном, с случайными символами.

class Crypt { public static function encrypt($string, $account) { // create a random initialization vector to use with CBC encoding $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $key = pack('H*', $account . $account); $output = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $iv); $output = $iv . $output; $output = base64_encode($output); $output = urlencode($output); return $output; } public static function decrypt($token, $account) { $ciphertext_dec = base64_decode($token); // retrieves the IV, iv_size should be created using mcrypt_get_iv_size() $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $iv_dec = substr($ciphertext_dec, 0, $iv_size); // retrieves the cipher text (everything except the $iv_size in the front) $ciphertext_dec = substr($ciphertext_dec, $iv_size); $key = pack('H*', $account . $account); $token = urldecode($token); $output = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec); $output = rtrim($output, ""); return $output; } } 

Невозможно получить точные значения, иногда он расшифровывается, но я вижу некоторые значения мусора, но в основном просто случайные символы.

 $a = \Crypt::encrypt("MyPassword", "1974246e"); echo \Crypt::decrypt($a, "1974246e"); 

Редактирование после обсуждения

 class Crypt { public static function encrypt($data, $passphrase) { $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); //create a random initialization vector to use with CBC encoding $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $key = pack('H*', $passphrase . $passphrase); return base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv)); } public static function decrypt($data, $passphrase) { $data = base64_decode($data); $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); //retrieves the IV, iv_size should be created using mcrypt_get_iv_size() $iv = substr($data, 0, $iv_size); $data = substr($data, $iv_size); //retrieves the cipher text (everything except the $iv_size in the front) $key = pack('H*', $passphrase . $passphrase); return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv), chr(0)); } } 

Применение:

 $pass = "MyPassword*&^*&^(*&^("; $token = \Crypt::encrypt($pass, "1974246e8e8a479bb0233495e8a3ed12"); $answer = \Crypt::decrypt($token, "1974246e8e8a479bb0233495e8a3ed12"); echo $answer == $pass ? "yes" : "no"; 

  1. Не urlencode. Ненужные.
  2. trim для NULL байт, а не пустые строки: rtrim($str, chr(0)); (Вместо этого вы можете также сохранить длину строки источника в зашифрованном результате, так что вы не будете rtrim() слишком много.)

Почему pack('H*', $account) для $key ? Также не нужно.

Rijndael 128 использует 16 байтовых ключей (128 бит), поэтому убедитесь, что ваш ключ по крайней мере такой:

 $key = $account . $account 

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

rtrim() с chr(0) отлично, очень вероятно, потому что ваша исходная строка не будет иметь завершающих байтов NUL.

Обычно я использую эти функции en / decrypt или аналогичные , но у них есть статический секрет / ключ, так что ваш лучше.

Чтобы отправить клиенту зашифрованный токен:

 $enc_token = Crypt::encrypt($token, $key); // $enc_token might contain `/` and `+` and `=` $url = 'page.php?token=' . urlencode($enc_token);