Php 执行签名cookie时序列化/取消序列化和mcrypt出现问题

Php 执行签名cookie时序列化/取消序列化和mcrypt出现问题,php,cookies,mcrypt,Php,Cookies,Mcrypt,我和一个朋友一起在一个网站上获取签名cookies,但是当我尝试用mcrypt和mcrypt_RIJNDAEL_256对其进行加密时,遇到了很多问题。我的cookie工作正常,所以问题只出现在对cookie的值进行加密/解密时 以下是尝试解密cookie时显示的错误: Notice: unserialize(): Error at offset 0 of 93 bytes in /var/samba/www/xxx/src/data/include/yyy/Cookie.php on line

我和一个朋友一起在一个网站上获取签名cookies,但是当我尝试用mcrypt和mcrypt_RIJNDAEL_256对其进行加密时,遇到了很多问题。我的cookie工作正常,所以问题只出现在对cookie的值进行加密/解密时

以下是尝试解密cookie时显示的错误:

Notice: unserialize(): Error at offset 0 of 93 bytes in /var/samba/www/xxx/src/data/include/yyy/Cookie.php on line 94
这条直线对应于:

$this->_cookie["value"] =  unserialize(mdecrypt_generic($tv, $cookie_value));
下面是我如何加密/解密的

首先,发送cookie

    $tv = mcrypt_module_open(MCRYPT_RIJNDAEL_256, null, "ctr", null);
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($tv), MCRYPT_RAND);
    mcrypt_generic_init($tv, "t3stp4ssw0rd", $iv);

    $this->_cookie["value"] =  base64_encode(mcrypt_generic($tv, serialize($this->_cookie["value"])));

    mcrypt_generic_deinit($tv);
    mcrypt_module_close($tv);

    setrawcookie($this->_cookie["name"],
                 $this->_cookie["value"],
                 $this->_cookie["expire"],
                 $this->_cookie["path"],
                 $this->_cookie["domain"],
                 $this->_cookie["secure"],
                 $this->_cookie["httponly"]);
是的,可爱的测试密码;-)

我在firebug上看到的cookie值是:

oKWdbVLX9T+mbOut4swo/aXr0g5O/3ApqfWZ1GZlrwwMSTa+M4n8Uey0UQs827HB7tilc/OzUPWQxoNvnAIkP5CFGkvgn+j+I36qN6dB0HmOUPlkNXJlz8Tfqxrjf8Gx
我的get cookie需要解密的值是:

    $this->_cookie["name"] = $cookie_name;
    $this->_cookie["value"] = $_COOKIE[$cookie_name];

    $cookie_value = base64_decode($this->_cookie["value"]);

    $tv = mcrypt_module_open(MCRYPT_RIJNDAEL_256, null, "ctr", null);
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($tv), MCRYPT_RAND);
    mcrypt_generic_init($tv, "t3stp4ssw0rd", $iv);

    $this->_cookie["value"] =  unserialize(mdecrypt_generic($tv, $cookie_value));

    mcrypt_generic_deinit($tv);
    mcrypt_module_close($tv);

    return $_COOKIE[$cookie_name];
问题是当我尝试取消序列化解密数据的值时。有人知道问题出在哪里吗

提前谢谢你

更新:

    $cookie_value = base64_decode($this->_cookie["value"]);

    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, "", "cfb", "");
    $ks = mcrypt_enc_get_key_size($td);
    $key = substr(sha1("t3stp4ssw0rd"), 0, $ks);

    $ivs = mcrypt_enc_get_iv_size($td);
    $iv = substr($cookie_value, 0, $ivs);

    $cookie_value = substr($cookie_value, $ivs);

    mcrypt_generic_init($td, $key, $iv);

    $cookie_value = mdecrypt_generic($td, $cookie_value);

    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

    $this->_cookie["value"] =  unserialize($cookie_value);

返回错误
警告:mcrypt_generic_init():Iv大小不正确;提供的长度:0,需要的长度:32确保引号
cookie中的信息不会使用反斜杠转义。如果它们是转义的,请在加密之前删除它们。请参见此线程->

,偏移错误通常意味着其中一个值的长度与序列化数据表示的指定长度不对应。根据我的经验,这通常归结为:

  • 正如前面的海报所说,插入反斜杠是为了转义字符
  • 编码问题。这通常发生在某些字符在序列化时被计算为有一个字节,但在取消序列化时,它们突然有两个字节。例如,当您拥有一个ISO-8859-1字符集时,可能会发生这种情况,但随后一些操作会将其更改为UTF-8
如果我猜的话,我会说第二点可能是你的问题所在。您在第一个实例中的过程是serialize->encrypt->base64_encode,然后颠倒顺序,但我怀疑,您的字符编码在某个地方出错了

编辑:好的,我查看了您的代码,您的加密/解密有问题。您的解密没有返回解密后的值。不久前,我遇到了这个函数(希望我能记住它的位置,以便正确地对其进行属性设置),这就是我用于Mcrypt的函数。它对编码和解码都有效。尝试一下,看看它是否解决了您的问题(它唯一没有做的就是base64_编码)。我认为你的问题是你错过了一些必要的步骤

function encDec( $data, $key, $encrypt=true, $cypher='rijndael-128') {

    if (function_exists('mcrypt_module_open')) {

        # Serialize, if encrypting
        if ( $encrypt ) { $data = serialize($data); } 

        # Open cipher module
        if ( ! $td = mcrypt_module_open($cypher, '', 'cfb', '') )
            return false;

        $ks = mcrypt_enc_get_key_size($td);     # Required key size
        $key = substr(sha1($key), 0, $ks);      # Harden / adjust length

        $ivs = mcrypt_enc_get_iv_size($td);     # IV size

        $iv = $encrypt ?
            mcrypt_create_iv($ivs, MCRYPT_RAND) :   # Create IV, if encrypting
            substr($data, 0, $ivs);                 # Extract IV, if decrypting

        # Extract data, if decrypting
        if ( ! $encrypt ) $data = substr($data, $ivs);

        if ( mcrypt_generic_init($td, $key, $iv) !== 0 ) # Initialize buffers
            return false;

        $data = $encrypt ?
            mcrypt_generic($td, $data) :    # Perform encryption
            mdecrypt_generic($td, $data);   # Perform decryption

        if ( $encrypt ) $data = $iv . $data;    # Prepend IV, if encrypting

        mcrypt_generic_deinit($td);             # Clear buffers
        mcrypt_module_close($td);               # Close cipher module

        # Unserialize, if decrypting
        if ( ! $encrypt ) $data = unserialize($data);

    }

    return $data;
}

这是
serialize($This->\u cookie[“value”])的变量转储
string(96)”s:88:“YTOZONTZOJM6INVPZCI7CZOXOIIXIJTZOJY6IMXVZ2DLZCI7YJOXO3M6NTOIBGV2ZWWIO3M6NTOIWRTAW4IO30=“;”
。似乎“不是转义的,不是吗?而且最奇怪的是……这是未序列化:
string(96)”之前的
var\u dump()�?“五�\�Ns=q�}T��2.��我��,�F$R���L����6Z� �v\���ͥ)��	9~�P�c$�(����J��x�܁c�它^�K��"   ` 如果我刷新,要取消序列化的值会更改。
get\u magic\u quotes\u gpc()
返回什么?如果
true
,在对cookie执行任何操作之前,是否将cookie传递给
stripslashes()
因此它返回
false
@Craig Sefton:谢谢。当取消对值字符的序列化时,请查看另一个答案的注释,如:
�?"v�\�Ns=q� }T��2
…这可能就是您所说的?如果我刷新页面,其中值的
var\u dump
在每次刷新时都会更改以取消序列化值。@udexter:这正是我所指的。如果您在不同操作之间没有正确的编码,那么在serialize/unserialize尝试完成他们的工作。顺便说一句,unserialize的值将始终更改,因为Mcrypt Mcrypt_RIJNDAEL_256(加密值从不相同)。您只需刷新一个页面,在该页面上加密一个值并将其输出到屏幕即可显示这一点。@udexter:事实上,我认为您遇到了另一个问题。我只是在不使用序列化/非序列化的情况下运行了代码,而据我所知,解密并没有返回解密后的值。我将尝试更仔细地查看它,但有定义这部分代码有问题。@Craig:谢谢!如果您需要什么,请告诉我,但我认为不再需要发送/获取cookie。谢谢!@udexter:刚刚发布了一个功能,您可能会发现它很有用。请欣赏。