CF8和AES解密MySQL AES:编码不一样

时间:2012-06-07 00:53:37

标签: mysql encryption coldfusion aes coldfusion-8

对于我在做错事情而不是关键任务而言,这已经成为一种练习,但我仍然希望看到我所犯的错误(简单可能)。

我正在使用mysql(5.1.x)AES_ENCRYPT来加密字符串。我正在使用CF的generateSecretKey('AES')来创建一个密钥(我已经在defaul和128和256位长度上尝试过它。)

所以让我们说我的代码如下:

    <cfset key = 'qLHVTZL9zF81kiTnNnK0Vg=='/>
    <cfset strToEncrypt = '4111111111111111'/>
    <cfquery name="i" datasource="#dsn#">
        INSERT INTO table(str) 
            VALUES AES_ENCRYPT(strToEncrypt,'#key#');
    </cfquery>

按预期工作正常,我可以使用SELECT AES_DECRYPT(str,'#key#')AS来选择它......完全没有任何问题。

我似乎无法做到的是让CF使用类似的东西解密它:

    <cfquery name="s" datasource="#dsn#">
        SELECT str
          FROM table
    </cfquery>
    <cfoutput>#Decrypt(s.str,key,'AES')#</cfoutput>

    <cfoutput>#Decrypt(toString(s.str),key,'AES')#</cfoutput>

我一直得到“输入和输出编码不一样”(包括toString() - 没有我得到二进制数据错误)。 db中加密字符串的字段类型为blob。

1 个答案:

答案 0 :(得分:5)

This entry解释说mySQL处理AES-128键的方式与您预期的有所不同:

  

.. MySQL算法只是或者是给定密码的字节   如果密码超过16个字符,则与前一个字节相对   当密码短于16个字符时,只留下0。

未经过高度测试,但这似乎产生相同的结果(十六进制)。

<cfscript>
    function getMySQLAES128Key( key ) {
        var keyBytes   = charsetDecode( arguments.key, "utf-8" );
        var finalBytes = listToArray( repeatString("0,", 16) );

        for (var i = 1; i <= arrayLen(keyBytes); i++) {
            // adjust for base 0 vs 1 index
            var pos = ((i-1) % 16) + 1;
            finalBytes[ pos ] = bitXOR(finalBytes[ pos ], keyBytes[ i ]);
        }

        return binaryEncode( javacast("byte[]", finalBytes ), "base64" );
    }

    key     = "qLHVTZL9zF81kiTnNnK0Vg==";
    input   = "4111111111111111";

    encrypted = encrypt(input, getMySQLAES128Key(key), "AES", "hex");
    WriteDump("encrypted="& encrypted);

    // note: assumes input is in "hex". either convert the bytes 
    // to hex in mySQL first or use binaryEncode
    decrypted = decrypt(encrypted, getMySQLAES128Key(key), "AES", "hex");
    WriteDump("decrypted="& decrypted);
</cfscript>

注意:如果您使用mySQL进行加密,请务必查看其提及the plain text may end up in various logs(复制,历史记录,etectera)的文档,并且“任何有读取权限的人都可以阅读那个信息“。


更新:事情可能已发生变化,但根据this 2004 bug report.mysql_history文件仅在Unix上。 (请记住可能有其他日志文件)清除.mysql_history的详细说明可以是found in the manual,但总结如下:

  
      
  • MYSQL_HISTFILE变量设置为/ dev / null(在每次登录时)
  •   
  • 创建.mysql_history作为/ dev / null(仅一次)的符号链接
  •