在php中解密aes密码的问题

时间:2013-01-27 23:00:11

标签: php encryption aes

我正在研究一些PHP代码来执行AES字符串加密和解密。加密工作正常但我似乎无法解密它。

以下是执行加密并添加所需填充的代码。

function encrypt($data) 
    { 
        $iv = "PRIVATE";
        $key = CIPHERKEY;

        return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, addpadding($data), MCRYPT_MODE_CBC, $iv));
    }

    function addpadding($string, $blocksize = 16)
    {
        $len = strlen($string);
        $pad = $blocksize - ($len % $blocksize);
        $string .= str_repeat(chr($pad), $pad);

        return $string;
    }

上面的代码工作正常,下面的代码解密仍然会失败。我尝试进行解密,然后剥离填充,但始终从填充函数返回false。

以下是执行解密和剥离的代码。

function strippadding($string)
{
    $slast = ord(substr($string, -1));
    $slastc = chr($slast);
    $pcheck = substr($string, -$slast);
    if(preg_match("/$slastc{".$slast."}/", $string)){
        $string = substr($string, 0, strlen($string)-$slast);
        return $string;
    } else {
        return "false";
    }
}

    function decrypt($data)
    {
        $iv = "PRIVATE";
        $key = CIPHERKEY;

        //$decoded = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
        $decrytped = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
        $base64Decoded = base64_decode($decrytped);
        return strippadding($base64Decoded);
    }

感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:3)

在您的解密方法中,decrypt和base64步骤是向后的。重要的是,无论您采取何种顺序进行加密操作,都要反过来解密。

在你的加密方法中,你是对密文进行base64编码:

base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, addpadding($data), MCRYPT_MODE_CBC, $iv));

解密时,需要撤消base64编码,然后解密该结果。

$base64Decoded = base64_decode($data);
$decrytped = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $base64Decoded, MCRYPT_MODE_CBC, $iv);

此外,看起来mcrypt会处理填充不均匀的块,因此你的addpadding()方法可能是多余的。

答案 1 :(得分:0)

你使用的是太短的IV,小于块大小。我认为这导致在解密时使用不同的IV。 Blocksize是16个字节,所以IV应该是16个字节,但你的固定字符串IV只有7个字节(如果计算底层C代码可能添加的终止零字节,则为8个字节)。

您应该使用由mcrypt_create_iv()生成的随机IV,而不是使用固定字符串。您可以使用mcrypt_get_iv_size()找出一个块的长度,如mcrypt_create_iv() PHP手册中的示例1所示。然后,您可以将随机IV发送/存储到密文之前,这样您就可以知道IV在解密时是什么。

此外,mcrypt也有自己的填充,所以你不需要。而且,正如mfanto指出的那样,你需要在解密之前解码Base64,而不是在解密之后。