【问题标题】:Encrypting in Coldfusion and then decrypting in PHP在 Coldfusion 中加密,然后在 PHP 中解密
【发布时间】:2015-05-09 00:33:52
【问题描述】:

我在重现 PHP 与 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 不同?

非常感谢

【问题讨论】:

    标签: php encryption coldfusion coldfusion-11


    【解决方案1】:

    (对于 cmets 来说太长了)

    Artjom B. already provided the answer aboveArtjom B. 写道

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

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

    更新: 由于CF encrypt()函数always interprets the plain text input as a UTF-8 string,还可以使用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;
    }
    

    【讨论】:

    • 个人,现在在初始测试中完美运行,我稍后会做几个测试,但我相信解决方案是一样的。感谢您的帮助和及时性。帮了我很多。谢谢
    • ArtjomB.找出了真正的问题,但很高兴以上有所帮助:)
    【解决方案2】:

    问题是填充。 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 = "$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 中解密,请不要忘记取消填充恢复的明文。

    【讨论】:

    • 如果未使用错误 Base64 对密钥进行编码,则尝试加密或解密您的输入字符串时出错:''无法解码字符串“$224455@”..
    • 我发现了问题。花了我足够长的时间。
    • (编辑)@ArtjomB。 - 纯文本字符串和密钥如何在 php 中解码? CFalways treats the plain as UTF8 encoded and the key as base64。所以提问者可能需要根据 php 函数如何解释值来调整键。
    • @Leigh PHP 使用二进制字符串。所以输入的编码取决于可能是UTF-8的php文件编码。输出是明确的 Base64 编码以匹配 ColdFusion 编码。我根本不知道 ColdFusion 说为什么需要 ToBase64(Key) 以及为什么它会产生与我的答案中的 php 代码相同的输出。
    • 为什么 ToBase64(Key) 是必要的 我对 php 不是很熟悉,但 CF 假设密钥已经是 base64 编码(见上面的链接)。因此它总是将密钥字符串解码为 base64 以获取密钥字节。假设与二进制 php 匹配,这可能就是它起作用的原因。 (编辑)关于填充 +1 的好发现
    猜你喜欢
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    相关资源
    最近更新 更多