mcrypt_decrypt() 错误更改密钥大小

Posted

技术标签:

【中文标题】mcrypt_decrypt() 错误更改密钥大小【英文标题】:mcrypt_decrypt() error change key size 【发布时间】:2015-01-30 23:53:31 【问题描述】:

mcrypt_decrypt():此算法不支持大小为 15 的密钥。仅支持大小为 16、24 或 32 的键

我该如何解决这个问题?我的密钥已设置 - 无法更改。 它必须是本地更改,我认为我本地的 php 版本对于我加载的项目来说太高级了。 我该如何解决这个问题?

【问题讨论】:

您没有给我们足够的信息。您是否使用正确的密码来解密字符串(加密时使用的密码)?不同的密码支持不同的密钥大小。 php.net/manual/en/function.mcrypt-decrypt.php 项目文件可以在其他机器上运行,所以密码很好——更进一步——在重新安装我的 xampp 之前一切正常 请注意:如果您通过 $key = 0x12345679ABCDEF 创建足够的 int,则传入的值是作为字符数组 -1234567 的 12-19 位(十进制)字符串,而不是32 位二进制值。 (它通过标准方法将 int 转换为字符串)。密钥必须通过“\xab\xcd\xef\x01\x02”定义为字符串(又名:数组/缓冲区)。但是在更新到 5.6 版之前,您不会意识到这已被破坏。您实际上一直在传递一个短数字字符串,该字符串填充为空 最好不要使用 PHP mcrypt,它是废弃软件,多年未更新,不支持标准 PKCS#7(née PKCS#5)填充,仅支持非标准空填充甚至不能用于二进制数据。 mcrypt 有许多出色的 bugs 可以追溯到 2003 年。mcrypt-extension is deprecated 在 PHP 7.2 中被删除。而是考虑使用defuse 或RNCryptor,它们提供了一个完整的解决方案并且正在维护并且是正确的。 【参考方案1】:

你更新到 5.6 了吗?它说

不再接受无效的密钥和 iv 大小。如果输入无效,mcrypt_decrypt() 现在将抛出警告并返回 FALSE。以前键和 IV 用 '\0' 字节填充到下一个有效大小。

Reference

阅读该引文的最后一行,您将在那里找到您的解决方案:)

mcrypt_decrypt():此算法不支持大小为 15 的密钥。仅支持大小为 16、24 或 32 的键

这意味着您需要用\0 填充您的密钥(这是以前的版本为您做的)

$key=$key."\0";

【讨论】:

那么我该如何解决这个问题? Previously keys and IVs were padded with '\0' bytes to the next valid size. 你也这样做:) 请注意,进行此更改是因为密钥应该由n / 8 字节组成,与随机无法区分,其中n 是密钥大小(以位为单位) .如果您的密钥较小,则很可能您正在为密钥使用密码。您不应该这样做,而是使用 password_hash 从密码创建密钥(如果密钥太大,可能使用最左边的字节)。 Hanky웃Panky,这是一个不向后兼容的 API 更改。 正是我需要的。谢谢【参考方案2】:

我继续创建了一个基于Hanky 웃 Panky's answer 的函数。

这可以与任何密钥长度一起使用,以确保其大小正确。

function pad_key($key)
    // key is too large
    if(strlen($key) > 32) return false;

    // set sizes
    $sizes = array(16,24,32);

    // loop through sizes and pad key
    foreach($sizes as $s)
        while(strlen($key) < $s) $key = $key."\0";
        if(strlen($key) == $s) break; // finish if the key matches a size
    

    // return
    return $key;

【讨论】:

这对我很有用。我有一个网站在旧版本的 php 上运行,我必须转移到我们的新服务器上。这让它再次工作。 循环中的循环效率低下。只需使用str_pad() 而不是while 并将&lt; 更改为&lt;= 并返回密钥【参考方案3】:

对于 Laravel 5

只需运行php artisan key:generate

Application key [EaaJgaD0uFDEg7tpvMOqKfAQ46Bqi8Va] set successfully.

如果您的密钥未更新,只需将其粘贴到您的 .env 文件中即可。

APP_KEY=EaaJgaD0uFDEg7tpvMOqKfAQ46Bqi8Va

刷新你的页面

【讨论】:

这不会破坏所有当前的加密数据,例如密码吗?【参考方案4】:

我在使用 OSTicket 1.6 ST(是的旧版本,我知道)时遇到了这个问题。托管公司刚刚使用 PHP 5.6,它破坏了 cron.php 的 Mail Fetch。我发布这个希望它可以帮助其他人更快地解决这个问题。

您必须编辑文件“include/class.misc.php”。

将@troskater 编写的答案中提供的函数“pad_key”添加到“include/class.misc.php”文件中,然后在函数“解密”更改中的第 51 行添加

return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $salt,...

改为使用

return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, pad_key($salt),...

【讨论】:

【参考方案5】:

您可以只使用 str_pad() 来实现这一点。最简单的形式就足够了。

function padKey($key) 

    // Get the current key size
    $keySize = strlen($key);

    // Set an array containing the valid sizes
    $validSizes = [16,24,32];

    // Loop through sizes and return correct padded $key
    foreach($validSizes as $validSize) 
        if ($keySize <= $validSize) return str_pad($key, $validSize, "\0");
    

    // Throw an exception if the key is greater than the max size
    throw new Exception("Key size is too large"); 


其他答案就可以了。我只是在这里利用内置的 PHP 函数 str_pad 而不是在循环中附加“\0”。

【讨论】:

【参考方案6】:

您不需要用“\0”填充键。

我在迁移到新的 PHP 7 服务器时遇到了同样的问题,我收到了消息:

mcrypt_decrypt():此算法不支持大小为 19 的密钥。仅有的 支持大小为 16、24 或 32 的键。

我在代码中的键是一个 19 个字符的字符串,我只是将它更改为一个 32 个字符的字符串,一切都很好了。

因此,如错误消息所示,请使用有效的大小键。

【讨论】:

我的密钥已设置 - 无法更改。它必须是本地更改 对。就我而言,我可以更改密钥。 我很感激你。但有一些困惑。这是个好主意吗?如果是这样,那么 DB 的变化呢?【参考方案7】:

我遇到了同样的问题,但是用这个解决了它

public function setKey($key) 
    $len = strlen($key);
    if($len < 24 && $len != 16)
        $key = str_pad($key, 24, "\0", STR_PAD_RIGHT); 
     elseif ($len > 24 && $len < 32) 
        $key = str_pad($key, 32, "\0", STR_PAD_RIGHT);       
    elseif ($len > 32)
        $key = substr($key, 0, 32);
    
    $this->key = $key;
 

【讨论】:

【参考方案8】:

如果您的加密代码如下所示:

<?php
  function encryptCookie($value)
    if(!$value)return false;
    $key = 'aNdRgUkXp2s5v8y/B?E(H+MbQeShVmYq';
    $text = $value;
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv);
    return trim(base64_encode($crypttext)); //encode for cookie
   
 function decryptCookie($value)
    if(!$value)return false;
    $key = 'aNdRgUkXp2s5v8y/B?E(H+MbQeShVmYq';
    $crypttext = base64_decode($value); //decode cookie
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $crypttext, MCRYPT_MODE_ECB, $iv);
    return trim($decrypttext);
   
?>

您需要将 $key 更改为 128 或 256 位加密代码。我只是复制了从这里生成的代码:Generate Code

我为我创建了一个由 32 个字符组成的 256 位代码,从而解决了无效密钥大小为 15 或任何导致错误的数字的问题。因此,无论为 $key 设置什么,您都需要将其更改为有效代码,然后它应该可以正常工作。

【讨论】:

以上是关于mcrypt_decrypt() 错误更改密钥大小的主要内容,如果未能解决你的问题,请参考以下文章

更新到 php 5.6.2 时的 mcrypt 警告;不支持大小为 x 的密钥

php使用内置的mcrypt_encrypt和mcrypt_decrypt进行字符串加密解密

有啥方法可以创建密钥大小为 512 的 JWT 令牌?并更改 AsymmetricSignatureProvider 的默认最小尺寸要求

调用未定义的函数 mcrypt_decrypt() - 即使安装了 php5-mcrypt

加密导致无效密钥大小错误[重复]

更改了 Firebase 项目,它给了我错误 [ API 密钥无效。请传递有效的 API 密钥。 ] 身份验证期间