【问题标题】:PHP mcrypt same key + base64 + urlencode = different valuesPHP mcrypt 相同的密钥 + base64 + urlencode = 不同的值
【发布时间】:2016-02-03 21:18:21
【问题描述】:

我正在尝试使用 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));

【问题讨论】:

  • URL 有一个最大输入(我相信是 2048),这可能是原因吗?
  • $iv - 你每次都在生成新的初始化向量
  • 是的,但是向量被附加到字符串中,这不应该是解密的问题吗?但是,从技术上讲,你是对的,我的问题是以错误的方式提出的。
  • 解密器如何知道最终 url 的哪一部分是 iv 以及什么是文本?
  • 你是如何构造 URL 以发送到解密脚本的?如果您是在 javascript 中执行此操作,则可能会添加额外的编码层。

标签: php encryption base64 urlencode


【解决方案1】:

我怀疑 rawurlencode() 和 PHP 为填充 $_REQUEST 数组所做的解码的组合正在破坏您的密文/iv。

更新:我测试了您的代码,它在我的实现中按预期工作。在您的实现中,可能正在客户端修改编码文本。

【讨论】:

  • 我在 OP 的代码中没有看到 rawurldecode,所以可能就是这样。
  • 我之前在解码中有 rawurldecode() ,它没有任何区别。文本不会在客户端被修改,因为它只是作为 url 参数嵌入到页面的链接中。然后此链接链接到进行解密的页面。这只是因为在第一页我有一个用户登录值,而我在第二页没有,但需要传递给它以确保用户有权访问内容。
【解决方案2】:

太好了。

这个问题显然不是我在问题本身中提到的。 对不起。

独立的这应该像@ChrisRibe 在他的回答中测试出来的那样工作。

这个特殊情况下的问题 - 我在我的问题中没有提到 - 整个 URL 也被 urlencoded 因为它作为参数传递到另一个 url(即 html2pdf.it 服务器)。如果加密的、base64 编码的文本中没有特殊的 url 保留字符,它就可以工作 - 但如果有任何 url 保留字符,它当然不起作用!

解决方案:

我现在用我自己的函数替换导致 url 出现问题的 3 个符号,而不是使用 rawurlencode 作为 base64 编码的加密文本,就像在这个 stackoverflow 问题中回答的那样: 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, '-_~', '+/='));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-14
    • 2014-01-29
    • 2018-11-28
    • 2019-10-03
    • 2014-02-01
    • 1970-01-01
    • 2013-12-01
    • 2013-04-01
    相关资源
    最近更新 更多