PHP mcrypt 相同的密钥 + base64 + urlencode = 不同的值
PHP mcrypt same key + base64 + urlencode = different values
我正在尝试使用 mcrypt 加密一个 PHP 站点上的值并在另一个站点上解密它。有时它有效(大约 80% 的时间),有时它不起作用。
现在我发现用相同的密钥加密相同的值时,加密的文本是不同的。这怎么可能?
我错过了什么?
这里是加密代码:
# key is always the same
$key = "mysimplekey";
# text is always the same
$plaintext = "text_to_encrypt";
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
$ciphertext = $iv . $ciphertext;
$ciphertext_base64 = base64_encode($ciphertext);
$ciphertext_url = rawurlencode($ciphertext_base64);
# gives different values for the same key & encryption text:
echo $ciphertext_url;
解密代码:
$key = 'mysimplekey';
$ciphertext_dec = base64_decode($_REQUEST['u']);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
# retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
$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);
# may remove 00h valued characters from end of plain text
$ciphertext_dec = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec));
我怀疑 rawurlencode() 和由 PHP 完成的用于填充 $_REQUEST 数组的解码的组合正在破坏你的 ciphertext/iv。
更新:我测试了你的代码,它在我的实现中按预期工作。也许在您的实现中,编码文本正在客户端被修改。
太棒了。
这个问题显然不是我在问题本身中提到的。
对不起。
独立的这应该像@ChrisRibe 在他的回答中测试过的那样工作。
这个特殊情况下的问题——我在问题中没有提到——是,整个 URL 也被 url 编码,因为它作为参数传递给另一个 url(即 html2pdf.it 服务器)。因此,如果加密的 base64 编码文本中没有特殊的 url 保留字符,它就可以工作 - 但如果有任何 url 保留字符,它当然不起作用!
解决方案:
我不再对 base64 编码的加密文本使用 rawurlencode,而是用我自己的函数替换导致 urls 问题的 3 个符号,就像在这个 Whosebug 问题中回答的那样:
Passing base64 encoded strings in URL
function base64_url_encode($input) {
return strtr(base64_encode($input), '+/=', '-_~');
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_~', '+/='));
}
我正在尝试使用 mcrypt 加密一个 PHP 站点上的值并在另一个站点上解密它。有时它有效(大约 80% 的时间),有时它不起作用。 现在我发现用相同的密钥加密相同的值时,加密的文本是不同的。这怎么可能? 我错过了什么?
这里是加密代码:
# key is always the same
$key = "mysimplekey";
# text is always the same
$plaintext = "text_to_encrypt";
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
$ciphertext = $iv . $ciphertext;
$ciphertext_base64 = base64_encode($ciphertext);
$ciphertext_url = rawurlencode($ciphertext_base64);
# gives different values for the same key & encryption text:
echo $ciphertext_url;
解密代码:
$key = 'mysimplekey';
$ciphertext_dec = base64_decode($_REQUEST['u']);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
# retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
$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);
# may remove 00h valued characters from end of plain text
$ciphertext_dec = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec));
我怀疑 rawurlencode() 和由 PHP 完成的用于填充 $_REQUEST 数组的解码的组合正在破坏你的 ciphertext/iv。
更新:我测试了你的代码,它在我的实现中按预期工作。也许在您的实现中,编码文本正在客户端被修改。
太棒了。
这个问题显然不是我在问题本身中提到的。 对不起。
独立的这应该像@ChrisRibe 在他的回答中测试过的那样工作。
这个特殊情况下的问题——我在问题中没有提到——是,整个 URL 也被 url 编码,因为它作为参数传递给另一个 url(即 html2pdf.it 服务器)。因此,如果加密的 base64 编码文本中没有特殊的 url 保留字符,它就可以工作 - 但如果有任何 url 保留字符,它当然不起作用!
解决方案:
我不再对 base64 编码的加密文本使用 rawurlencode,而是用我自己的函数替换导致 urls 问题的 3 个符号,就像在这个 Whosebug 问题中回答的那样: Passing base64 encoded strings in URL
function base64_url_encode($input) {
return strtr(base64_encode($input), '+/=', '-_~');
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_~', '+/='));
}