【问题标题】:recieving error Warning: mcrypt_decrypt(): The IV parameter must be as long as the blocksize收到错误警告:mcrypt_decrypt():IV 参数必须与块大小一样长
【发布时间】:2023-03-26 06:11:02
【问题描述】:

我收到此错误:

Warning: mcrypt_decrypt(): The IV parameter must be as long as the blocksize

它来自使用与 php 手册站点 (http://php.net/manual/en/function.mcrypt-encrypt.php) 上的代码基本相同的代码加密变量。当它全部放在一起时它正在工作(我将它分成两个用作include() 文件并添加了方便的输入和输出变量)。它加密一个值,将它发布到一个 $_GET 变量上,然后在下一页加载它解密它。但是,在解密时,我得到了错误。我猜这可能与将加密信息保存在 $_GET 变量中,然后读取它有关。在一个实例中,URL 中的加密文本和 $_GET 标识符如下所示:Last_Song_ID=mIyFkMdMgVgSZU18wD/vJ3bI8qf++ea1/NtGrsajKd4=

在这个文件中(错误发生在靠近底部的$ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);

include('key.php');

$ciphertext_base64 = $de_in;

$ciphertext_dec = base64_decode($ciphertext_base64);

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
echo $iv_size . "<br>";

# 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
$plaintext_utf8_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key,
                                     $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);

$de_out = $plaintext_utf8_dec;

加密文本来自主文件中的 $_GET 变量,该变量来自以下内容:

<?php
    # --- ENCRYPTION ---

    # the key should be random binary, use scrypt, bcrypt or PBKDF2 to
    # convert a string into a key
    # key is specified using hexadecimal
    include('key.php');

    # show key size use either 16, 24 or 32 byte keys for AES-128, 192
    # and 256 respectively
    $key_size =  strlen($key);
    //echo "Key size: " . $key_size . "\n";

    if(!isset($en_in))
    $en_in = "No Input";

    # create a random IV to use with CBC encoding
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    echo $iv_size . "<br>";
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

    # use an explicit encoding for the plain text
    $plaintext_utf8 = utf8_encode($en_in);

    # creates a cipher text compatible with AES (Rijndael block size = 128)
    # to keep the text confidential 
    # only suitable for encoded input that never ends with value 00h
    # (because of default zero padding)
    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,
                                 $plaintext_utf8, MCRYPT_MODE_CBC, $iv);

    # prepend the IV for it to be available for decryption
    $ciphertext = $iv . $ciphertext;

    # encode the resulting cipher text so it can be represented by a string
    $ciphertext_base64 = base64_encode($ciphertext);

    $en_out = $ciphertext_base64;


?>

【问题讨论】:

  • 想一想,如果$ciphertext_dec(无论出于何种原因)小于$iv_size,会发生什么?您在任何时候都不会检查。你应该在这里做:$iv_dec = substr($ciphertext_dec, 0, $iv_size);
  • 另请注意,您有 $en_in$en_out,但随后有 $de_in$de_out,假设 $en$de 是语言名称,这是预期的还是它错字?
  • 我假设加密总是产生一个比 $iv_size 长的变量(在这种情况下是 '16')
  • @FranciscoPresencia 它只是意味着加密和解密

标签: php


【解决方案1】:

您不能传递 base 64 via GET parameter,因为这些是有效的 base64 字符,可能与 GET 参数冲突:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=

因此,您可能无法按预期检索整个 GET,而只是检索了一部分。您可能希望这样做以检查:

最后一行编码:

echo strlen($en_out);

编码开始处:

echo strlen($de_in);

如果大小不匹配,那就是你的问题,由于上面提到和链接的原因,整个事情没有被正确传递。

编辑:关于解决方案,链接问题中的第一个和第二个答案都很好。

【讨论】:

  • 绝对完美!正如我所怀疑的那样,我也不知道答案。谢谢!
  • 我自己一直在使用与您的非常相似的脚本(secretdiary.org 免责声明:我的页面)自己做一个加密系统。令人遗憾的是,大多数加密问题都来自这样的小事情,很难追踪,而且你学到的东西很少。很高兴为您提供帮助 (;
猜你喜欢
  • 2014-07-18
  • 1970-01-01
  • 2016-06-22
  • 2015-05-12
  • 2015-11-06
  • 2014-06-15
  • 2011-12-02
  • 2021-03-15
  • 2020-04-28
相关资源
最近更新 更多