mcrypt警告但仍可解密数据。

13

这个类里有一个有点奇怪的问题:

<?php
namespace lib;

/**
 * Short description of Crypt
 *
 * @author xxxx
 * @package
 */
class Encryption
{
    /**
     * Short description of _ch
     * handle to the mcrypt resource
     *
     * @access private
     * @var $_ch
     */
    private $_ch;

    /**
     * Short description of __construct
     *
     * @access public
     * @author xxxx
     * @param
     * @return void
     */
    public function __construct( $keyData = NULL, $algorithm = \MCRYPT_RIJNDAEL_256, $mode = MCRYPT_MODE_ECB, $encLibPath = '', $modeDir = '' )
    {
        $this->_ch = mcrypt_module_open( $algorithm, $encLibPath, $mode, $modeDir );

        $vector  = mcrypt_create_iv ( mcrypt_enc_get_iv_size( $this->_ch ), \MCRYPT_DEV_URANDOM );
        $keySize = mcrypt_enc_get_key_size( $this->_ch );

        $key = substr( hash( 'SHA512', $keyData . $keySize ), 0, $keySize );

        $x = mcrypt_generic_init( $this->_ch, $key, $vector );
    }

    /**
     * Short description of encrypt
     *
     * @access public
     * @author xxxx
     * @param String $str
     * @return String $res
     */
    public function encrypt( $str )
    {
        if( !is_string( $str ) )
        {
            throw new \InvalidArgumentException( 'Attemptig to encrypt data that is not a string' );
            return false;
        }
        $res = mcrypt_generic( $this->_ch, $str );

        mcrypt_generic_deinit( $this->_ch );
        mcrypt_module_close( $this->_ch );

        #var_dump($str,$res);
        return $res;
    }

    /**
     * Short description of decrypt
     *
     * @access public
     * @author xxxx
     * @param String $str
     * @return String $res
     */
    public function decrypt( $str )
    {
        if( !is_string( $str ) )
        {
            throw new \InvalidArgumentException( 'Attemptig to decrypt data that is not a string' );
            return false;
        }

82      $res = mdecrypt_generic( $this->_ch, $str );

84      mcrypt_generic_deinit( $this->_ch );
85      mcrypt_module_close( $this->_ch );

        #var_dump($str,$res);
        return trim( $res);
    }
}

当这样调用时:

<?php
$encryption    = new \lib\Encryption( 'somekey' );

echo $encryption->decrypt( $safeInfo );

strangle yields:

警告:mdecrypt_generic():位于E:\ htdocs \ site \ application \ lib \ encryption.cls.php的第82行的90不是有效的MCrypt资源

警告:mcrypt_generic_deinit():90不是E:\ htdocs \ site \ application \ lib \ encryption.cls.php的第84行中有效的MCrypt资源

警告:mcrypt_module_close():90不是E:\ htdocs \ site \ application \ lib \ encryption.cls.php的第85行中有效的MCrypt资源

(这些行出现在加密类中。)

预期解密的字符串(即成功解密的字符串)。

如果有人能指出为什么会出现这些警告,以及为什么似乎不影响结果,我将非常感激。

PS,对加密类的效果的任何评论都受欢迎。


我在 Linux 和 Windows 上尝试运行了您的脚本,没有收到任何警告。 我确保打开了所有错误提示。 我无法复现相同的结果。 如果我先调用 mycrypt_module_close,则会显示警告,但不会解密。 - Gohn67
我也尝试在构造函数中对 $this->_ch 运行 var_dump。我的结果与你的略有不同。我得到的是 resource(2) of type (mcrypt) - Gohn67
@Gohn67 - 这仍然是一个mcrypt资源 - 可能与版本或xdebug有关,输出var_dump的方式不同,但它表示它是一个mcrypt资源... - Ian Wood
@IanWood 也许这个警告是针对你的堆栈而言的?看起来你正在使用Windows。你具体运行的php版本是什么?似乎是>5.3,因为你在使用命名空间。我认为这意味着一个版本的mcrypt扩展会默认安装。另外,你是用WAMP或XAMPP安装的吗?我在Windows 7,PHP 5.3.2 TS版本,没有xdebug上运行了你的代码。 - Gohn67
我能够在另一台系统上测试您的脚本。该系统为Win7 Pro,PHP版本为5.3.4,mcrypt版本为2.5.8。没有收到任何警告。在我的Win7 Home上,也安装了mcrypt 2.5.8。也许是您的mcrypt版本有问题。不过,如果您的PHP版本是5.3+,那么mcrypt应该是2.5.8,而且不再需要dll文件,就像在PHP < 5.3中需要的那样。 - Gohn67
显示剩余4条评论
3个回答

5

看起来不错

<?php
$encryption = new \lib\Encryption( 'somekey' );
echo $encryption->decrypt(pack("H*", "4a4a564f26618d47536ff35b8a0af3212814a5f0ba635d2cf6f8cd31589042e2"));

_ch因为mcrypt_module_close($this->_ch);encrypt()方法中丢失。

也许您可以更改__construct并仅保存参数,每次加密或解密时只创建句柄(如_ch)。

我不擅长Mcrypt,所以可能有比我更好的方法,但“有效的MCrypt资源”问题的原因确实是mcrypt_module_close


仅仅是因为mcrypt_module_close存在吗?它只有在加密/解密完成后才被调用,而且它从未在同一对象上调用,因此您无法在同一实例中进行编码和解码... - Ian Wood
1
如果您先加密再解密,您将会收到警告,但不会打印出正确的结果。我认为它在解密之前停止了。到目前为止,我只能通过连续调用两次解密来复现警告和正确的结果。正确的字符串首先出现,然后是警告。 - Gohn67

3

看起来是命名空间问题,因为您在__construct()中没有使用前缀MCRYPT_MODE_ECB


这在这种情况下并不是问题,因为他没有使用 use some_namespace,所以该类仍然在全局命名空间中,这就是为什么 MCRYPT_MODE_ECB 可以在没有 \ 的情况下工作。但我可能是错的。我对 PHP 中的命名空间并不完全熟悉。 - Gohn67

2
这是需要检查的事情,但由于我无法复制,不确定它是否是答案。
您使用了SHA512(创建512长度的密钥),但算法期望256长度的密钥。如果您使用SHA256,会有什么区别吗?通常,密钥不匹配应该会产生垃圾数据,但在这种情况下,它可能仍然可以“带有副作用”地工作。

不用担心,在这种情况下并不重要,因为substr函数会处理它 - 它会确保密钥的长度是适当的。 - Ian Wood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接