我正在研究一些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);
}
感谢您提供的任何帮助。
答案 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,而不是在解密之后。