问题描述
PHP 和 ColdFusion9 中的 AES 加密产生不同的结果.有人可以帮帮我吗?
AES Encryption in PHP and ColdFusion9 is producing different results. Could somebody please help me?
以下 PHP 代码
$key = "12345678123456781234567812345678";
$iv = "1234567812345678";
$data = "This is a plain string.";
echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv));
给我 G+tdEOfQTtVCQGxW3N5uzkqN207OyfIPxS6zf2xrKKY=
gives me G+tdEOfQTtVCQGxW3N5uzkqN207OyfIPxS6zf2xrKKY=
下面的 ColdFusion 代码
While the below ColdFusion Code
<cfset thePlainData = "This is a plain string." />
<cfset theKey = "12345678123456781234567812345678" />
<cfset theAlgorithm = "AES/CBC/PKCS5Padding" />
<cfset theEncoding = "base64" />
<cfset theIV = "1234567812345678" />
<cfset encryptedString = encrypt(thePlainData, theKey, theAlgorithm, theEncoding, theIV) />
给我 KLt55n5/T3ee6xVq9VGFbyCacJznkHEqC/RDRhL+4nw=
gives me KLt55n5/T3ee6xVq9VGFbyCacJznkHEqC/RDRhL+4nw=
知道我哪里错了吗?提前致谢.
Any idea where I am wrong? Thanks in advance.
推荐答案
不幸的是,ColdFusion 和 PHP 实现之间在使用的明文填充样式方面存在轻微的不兼容.AES 要求明文块大小可被 128 整除.为了实现这一点,PHP 将使用 NULL 字符填充明文输入获得适当的块大小.ColdFusion 可以使用 Java 支持的各种 填充技术.不幸的是,ColdFusion 和 Java 都支持 NULL 填充模式,这使得互操作性更加困难.ColdFusion 的字符串处理不支持 NULL 字符,因此您需要在 PHP 中实现 PKCS5Padding 架构 而是让它们正确地互操作.
Unfortunately there is a slight incompatibility between the ColdFusion and PHP implementations regarding the plaintext padding style used. AES requires a plaintext block size divisible by 128. To achieve this, PHP will pad the plaintext input with NULL characters to get the proper block size. ColdFusion can use a variety of padding techniques that are supported by Java. Unfortunately, ColdFusion nor Java support a NULL padding schema which makes interoperability more difficult. ColdFusion's string handling does not support NULL characters, so you will need to implement a PKCS5Padding schema within PHP instead to get them to inter-operate properly.
此外,正如评论中提到的,ColdFusion 将期望密钥是 base64 编码的,因此您需要密钥设置如下所示:
Also, as mentioned in the comments, ColdFusion will expect the key to be base64 encoded, so you'd need the key setting to look like:
<cfset theKey = toBase64("12345678123456781234567812345678") />
此外,默认情况下 Java(以及扩展的 ColdFusion)仅支持最大 128 位的密钥大小.在这里,您使用的是 256 位密钥,这将 需要 Java 无限强度扩展(对于那些试图测试代码并得到非法密钥大小错误).
Further, Java by default (and ColdFusion by extension) only supports key sizes up to 128 bits. Here you're using a 256 bit key which would require the Java Unlimited Strength extension (for those trying to test the code and getting an illegal key size error).
生成的 PHP 代码如下所示:
The resulting PHP code looks like:
// Function from http://us3.php.net/manual/en/ref.mcrypt.php#69782
function pkcs5_pad ($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
$key = "12345678123456781234567812345678";
$iv = "1234567812345678";
// Pad data with PKCS #5 to prevent PHP from using NULL padding.
$data = pkcs5_pad("This is a plain string.", 16);
echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv));
生成的 ColdFusion 代码如下所示:
The resulting ColdFusion code looks like:
<cfset thePlainData = "This is a plain string." />
<cfset theKey = toBase64("12345678123456781234567812345678") />
<cfset theAlgorithm = "AES/CBC/PKCS5Padding" />
<cfset theEncoding = "base64" />
<cfset theIV = "1234567812345678" />
<cfset encryptedString = encrypt(thePlainData, theKey, theAlgorithm, theEncoding, theIV) />
<cfoutput>#encryptedString#</cfoutput>
两者都输出相同的base64编码字符串:
Both output the same base64 encoded string:
G+tdEOfQTtVCQGxW3N5uzlu0mGabRKNxuIdAXArQE80=
这篇关于PHP ColdFusion9 AES 加密 - 不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!