7

我在重现 PHP vs Coldfusion 中生成的相同结果时遇到问题。

在 PHP 中以这种方式加密:

<?php
    $key = "$224455@";
    $Valor = "TESTE";

    $base = chop(base64_encode(mcrypt_encrypt(MCRYPT_DES, $key, $Valor, MCRYPT_MODE_ECB)));     
?>

我有结果:

tzwRx5Bxoa0=

在 Coldfusion 中这样做了:

<cfset Valor = "TESTE">
<cfset Key = "$224455@">
<cfset base = Encrypt(Valor,ToBase64(Key),"DES/ECB/PKCS5Padding","BASE64")>

结果:

qOQnhdxiIKs=

什么不是 ColdFusion 产生与 PHP 相同的价值?

非常感谢

4

2 回答 2

5

问题是填充。PHP 的 mcrypt 扩展只使用 ZeroPadding。这意味着明文被 0x00 字节填充,直到达到块大小的倍数。

另一方面,PKCS#5/PKCS#7 填充用字节填充它,这些字节表示在块大小的下一个倍数之前丢失的字节数。DES 的块大小为 8 个字节。

因此,您要么需要在 php 中填充明文(请参阅此插入代码:A:如何从 AES 加密字符串中添加/删除 PKCS7 填充?)或在 ColdFusion 中使用不同的密码,例如"DES/ECB/NoPadding". 我推荐前者,因为如果你使用 NoPadding,明文必须已经是块大小的倍数。

$key = "$224455@";
$Valor = "TESTE";
function pkcs7pad($plaintext, $blocksize)
{
    $padsize = $blocksize - (strlen($plaintext) % $blocksize);
    return $plaintext . str_repeat(chr($padsize), $padsize);
}

$base = chop(base64_encode(mcrypt_encrypt(MCRYPT_DES, $key, pkcs7pad($Valor, 8), MCRYPT_MODE_ECB)));

结果:

qOQnhdxiIKs=

如果您在 PHP 中解密,请不要忘记取消填充恢复的明文。

于 2015-03-07T17:35:59.250 回答
5

(评论太长了)

Artjom B. 已经在上面提供了答案Artjom B.写道

问题是填充。PHP 的 mcrypt 扩展只使用 ZeroPadding [...] 您要么需要在 php [...] 中填充明文,要么在 ColdFusion 中使用不同的密码,例如“DES/ECB/NoPadding”。我推荐前者,因为如果你使用 NoPadding,明文必须已经是块大小的倍数。

不幸的是,在 CF中很难产生空字符。AFAIK,唯一有效的技术是使用URLDecode("%00"). 如果您无法按照@Artjom B. 的建议修改 PHP 代码,您可以尝试使用下面的函数来填充 CF 中的文本。免责声明:它只是经过轻微测试(CF10),但似乎产生与上述相同的结果。

更新:由于 CF encrypt() 函数始终将纯文本输入解释为 UTF-8 字符串,您还可以使用charsetEncode(bytes, "utf-8")从单个元素字节数组创建空字符,即 charsetEncode( javacast("byte[]", [0] ), "utf-8")


例子:

Valor = nullPad("TESTE", 8);
Key = "$224455@";
result = Encrypt(Valor, ToBase64(Key), "DES/ECB/NoPadding", "BASE64");
// Result: TzwRx5Bxoa0=
WriteDump( "Encrypted Text = "& Result ); 

功能:

/*
   Pads a string, with null bytes, to a multiple of the given block size

   @param plainText - string to pad
   @param blockSize - pad string so it is a multiple of this size
   @param encoding - charset encoding of text
*/
string function nullPad( string plainText, numeric blockSize, string encoding="UTF-8")
{
    local.newText = arguments.plainText;
    local.bytes = charsetDecode(arguments.plainText, arguments.encoding);
    local.remain = arrayLen( local.bytes ) % arguments.blockSize;

    if (local.remain neq 0) 
    {
        local.padSize = arguments.blockSize - local.remain;
        local.newText &= repeatString( urlDecode("%00"), local.padSize );
    }

    return local.newText;
}
于 2015-03-08T04:39:31.353 回答