Проблема с шифрованием/кодированием переменной URL

У меня есть класс, который принимает строку в таком формате:

000067000000000012620060324b38e2cab3353

, шифрует строку, а затем добавляет ее как переменную get в URL.

Класс, выполняющий шифрование, имеет функцию, которая выглядит следующим образом:

private function _code_encryption($enc_type,$a_string){
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);                          

    if($enc_type == self::ENCRYPT_STRING){
       //encrypt then return base64 encoded
       $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, $a_string, MCRYPT_MODE_CBC, $iv);
       return base64_encode($encrypted);
    }elseif($enc_type == self::DECRYPT_STRING){
       $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, base64_decode($a_string), MCRYPT_MODE_CBC, $iv);
        return trim($decrypted);
    }
}

Когда строка зашифрована, я кодирую значение urlencode и добавляю его к URL-адресу, как если бы URL-адрес выглядел как «https://secure.mysite.com/index.php?action=someaction&transfer_code=XXXXX, где XXXX – зашифрованная строка с URL-адресом.

Теперь, когда URL-адрес анализируется и обрабатывается, значение $_GET['transfer_code'] передается в вышеупомянутую функцию _code_encryption, но не возвращает правильно расшифрованное значение, а вместо этого возвращает искаженные символы, которые мой браузер не отображает. Есть ли требования к длине ключа, который я использую для шифрования/дешифрования? Я пробовал что-то вроде

$key = hash('sha256',self::AUTH_ENCRYPTION_KEY,true);

но и это не сработало...

Кроме того, я не декодирую переменную $_GET['transfer_code'], потому что в справочных страницах php указано, что переменные get уже закодированы в urlencoded...

Должен ли я кодировать буквенно-цифровую строку UTF-8 ПЕРЕД шифрованием / base64_encoding, или это вообще будет иметь значение?


person eCaroth    schedule 28.12.2009    source источник


Ответы (1)


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

У меня нет синтаксического анализатора, чтобы проверить это, но это должно быть что-то вроде:

private function _code_encryption($enc_type,$a_string){
 $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
 if($enc_type == self::ENCRYPT_STRING){
  //encrypt then return base64 encoded
  $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, $a_string, MCRYPT_MODE_CBC, $iv);
  return base64_encode($iv.$encrypted);
 } elseif ($enc_type == self::DECRYPT_STRING){
  $decoded = base64_decode($a_string);
  $iv = substr($decoded,0,$iv_size);
  $cipher = substr($decoded,$iv_size);
  $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, $cipher, MCRYPT_MODE_CBC, $iv);
  return trim($decrypted);
 }
}
person Remus Rusanu    schedule 28.12.2009
comment
Вы намеренно пропускаете 1-й символ iv ( substr($decoded,1,$iv_size) )? Я думал, что все работает правильно (извлечение IV из символа 0, а не 1), но я получаю смешанные результаты. Например, шифрование/кодирование этой строки 67:1262031751:4b38e2cab2353 прекрасно работает, но вот эта 24:1262031777:4b38e2cab2353 вообще не работает и возвращает 64-символьную строку фиктивных символов. - person eCaroth; 28.12.2009
comment
Нет, id не пропустил 1-й символ намеренно. Я просто не помнил, основано ли оно на 0 или на 1. - person Remus Rusanu; 28.12.2009
comment
Если некоторые строки работают, некоторые из них не гарантируют правильность кодирования/декодирования base64. base64 дополняет вывод «=», и если urlencode/decode удаляет «=», то кодирование/декодирование base64 повреждено, и в результате поврежден шифр. вы будете выполнять это один за другим и проверять на каждом этапе, что обратная операция работает (расшифровать вывод после шифрования и проверки, декодировать после кодирования и проверить и т. д.). - person Remus Rusanu; 28.12.2009
comment
Оказывается, urlencoding прекрасно сохранял знаки =, но пробелы преобразовывались в %2B, а не в +. Задача решена. - person eCaroth; 29.12.2009
comment
У меня может быть такая же проблема. Как вы решили вопрос с плюсами и пробелами? Я пробовал использовать как realurlencode, так и urlencode, и ни один из них не работал. - person user1149499; 25.08.2014