在 Coldfusion 中加密,然后在 PHP 中解密
Encrypting in Coldfusion and then decrypting in PHP
我在重现 PHP 与 Coldfusion 中生成的相同结果时遇到问题。
在PHP中以这种方式加密:
<?php
$key = "4455@";
$Valor = "TESTE";
$base = chop(base64_encode(mcrypt_encrypt(MCRYPT_DES, $key, $Valor, MCRYPT_MODE_ECB)));
?>
我有结果:
TzwRx5Bxoa0=
在 Coldfusion 中这样做:
<cfset Valor = "TESTE">
<cfset Key = "4455@">
<cfset base = Encrypt(Valor,ToBase64(Key),"DES/ECB/PKCS5Padding","BASE64")>
结果:
qOQnhdxiIKs=
ColdFusion 产生的值与 PHP 不同的是什么?
非常感谢
问题是填充。 PHP 的 mcrypt 扩展仅使用 ZeroPadding。意思是明文用0x00字节填充,直到达到块大小的倍数。
另一方面,PKCS#5/PKCS#7 填充用字节填充它,这些字节表示在块大小的下一个倍数之前丢失的字节数。 DES 的块大小为 8 个字节。
因此您要么需要在 php 中填充明文(请参阅此插入代码:A: How to add/remove PKCS7 padding from an AES encrypted string?),要么在 ColdFusion 中使用不同的密码,例如 "DES/ECB/NoPadding"
。我推荐前者,因为如果你使用NoPadding,明文必须已经是块大小的倍数。
$key = "4455@";
$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 中解密,请不要忘记取消填充恢复的明文。
(评论太长)
。 Artjom B. 写道
The problem is the padding. The mcrypt extension of PHP only uses
ZeroPadding [...] you either need to pad the plaintext in php [...] or
use a different cipher in ColdFusion such as "DES/ECB/NoPadding". I
recommend the former, because if you use NoPadding, the plaintext must
already be a multiple of the block size.
不幸的是,很难产生null character in CF. AFAIK, the only technique that works is to use URLDecode("%00")
。如果您不能按照@Artjom B. 的建议修改 PHP 代码,您可以尝试使用下面的函数来填充 CF 中的文本。免责声明:它仅经过轻微测试 (CF10),但似乎产生与上述相同的结果。
更新:
由于CF encrypt()函数always interprets the plain text input as a UTF-8 string, you can also use charsetEncode(bytes, "utf-8")从单元素字节数组创建一个空字符,即charsetEncode( javacast("byte[]", [0] ), "utf-8")
示例:
Valor = nullPad("TESTE", 8);
Key = "4455@";
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;
}
我在重现 PHP 与 Coldfusion 中生成的相同结果时遇到问题。
在PHP中以这种方式加密:
<?php
$key = "4455@";
$Valor = "TESTE";
$base = chop(base64_encode(mcrypt_encrypt(MCRYPT_DES, $key, $Valor, MCRYPT_MODE_ECB)));
?>
我有结果:
TzwRx5Bxoa0=
在 Coldfusion 中这样做:
<cfset Valor = "TESTE">
<cfset Key = "4455@">
<cfset base = Encrypt(Valor,ToBase64(Key),"DES/ECB/PKCS5Padding","BASE64")>
结果:
qOQnhdxiIKs=
ColdFusion 产生的值与 PHP 不同的是什么?
非常感谢
问题是填充。 PHP 的 mcrypt 扩展仅使用 ZeroPadding。意思是明文用0x00字节填充,直到达到块大小的倍数。
另一方面,PKCS#5/PKCS#7 填充用字节填充它,这些字节表示在块大小的下一个倍数之前丢失的字节数。 DES 的块大小为 8 个字节。
因此您要么需要在 php 中填充明文(请参阅此插入代码:A: How to add/remove PKCS7 padding from an AES encrypted string?),要么在 ColdFusion 中使用不同的密码,例如 "DES/ECB/NoPadding"
。我推荐前者,因为如果你使用NoPadding,明文必须已经是块大小的倍数。
$key = "4455@";
$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 中解密,请不要忘记取消填充恢复的明文。
(评论太长)
The problem is the padding. The mcrypt extension of PHP only uses ZeroPadding [...] you either need to pad the plaintext in php [...] or use a different cipher in ColdFusion such as "DES/ECB/NoPadding". I recommend the former, because if you use NoPadding, the plaintext must already be a multiple of the block size.
不幸的是,很难产生null character in CF. AFAIK, the only technique that works is to use URLDecode("%00")
。如果您不能按照@Artjom B. 的建议修改 PHP 代码,您可以尝试使用下面的函数来填充 CF 中的文本。免责声明:它仅经过轻微测试 (CF10),但似乎产生与上述相同的结果。
更新:
由于CF encrypt()函数always interprets the plain text input as a UTF-8 string, you can also use charsetEncode(bytes, "utf-8")从单元素字节数组创建一个空字符,即charsetEncode( javacast("byte[]", [0] ), "utf-8")
示例:
Valor = nullPad("TESTE", 8);
Key = "4455@";
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;
}