PHP ColdFusion9 AES 加密 - 不同的结果

2022-01-09 00:00:00 encryption aes php coldfusion

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=

相关文章