CF8和AES解密MySQL AES:编码不一样 [英] CF8 and AES decrypting MySQL AES: encodings are not same

查看:177
本文介绍了CF8和AES解密MySQL AES:编码不一样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个比我关键任务更糟糕的行为,但是我仍然希望看到我所犯的错误(简单大概)。


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



所以让我们说代码如下:

 < cfset key ='qLHVTZL9zF81kiTnNnK0Vg =='/> 
< cfset strToEncrypt ='4111111111111111'/>
< cfquery name =idatasource =#dsn#>
INSERT INTO表(str)
VALUES AES_ENCRYPT(strToEncrypt,'#key#');
< / cfquery>

正常工作正常,我可以使用SELECT AES_DECRYPT(str,'#key# )AS ...没有任何问题。



我似乎不能做,但是使用以下方式使CF解密:

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

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

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

解决方案

此条目解释说,mySQL处理AES-128密钥有点不同于你可能会期望:


.. MySQL算法只是或是给定密码短语
的字节与以前的字节相比,如果密码长度超过16个字符,
只有在密码短于16个字符时才将其保留为0。


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

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

for(var i = 1; i< = arrayLen(keyBytes); i ++){
//调整基数0与1索引
var pos =((i -1)%16)+ 1;
finalBytes [pos] = bitXOR(finalBytes [pos],keyBytes [i]);
}

返回binaryEncode(javacast(byte [],finalBytes),base64);
}

key =qLHVTZL9zF81kiTnNnK0Vg ==;
input =4111111111111111;

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

//注意:假设输入是十六进制。或者将mySQL中的字节
//转换为hex,或者使用binaryEncode
decryptpted = decrypt(encrypted,getMySQLAES128Key(key),AES,hex);
WriteDump(decryptpted =&解密);
< / cfscript>

注意:如果您使用mySQL进行加密,一定要看到提及明文可能会出现在各种日志中的文档(复制,历史,etectera)和可以读取访问该信息的任何人。






更新:事情可能已更改,但根据此2004错误报告 .mysql_history 文件仅在Unix上。 (请记住可能有其他日志文件)清除.mysql_history的详细说明可以是在手册中找到,但总结如下:



  • 设置$ / code $ MYSQL_HISTFILE 变量到/ dev / null(在每个登录时)

  • 创建.mysql_history作为/ dev / null的符号链接只有一次)



This has become more of an exercise in what am I doing wrong than mission critical, but I'd still like to see what (simple probably) mistake I'm making.

I'm using mysql (5.1.x) AES_ENCRYPT to encrypt a string. I'm using CF's generateSecretKey('AES') to make a key (I've tried it at defaul and 128 and 256 bit lengths).

So let's say my code looks like this:

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

That works fine as expected and I can select it using SELECT AES_DECRYPT(str,'#key#') AS... with no problems at all.

What I can't seem to do though is get CF to decrypt it using something like:

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

or

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

I keep getting "The input and output encodings are not same" (including the toString() - without that I get a binary data error). The field type for the encrypted string in the db is blob.

解决方案

This entry explains that mySQL handles AES-128 keys a bit differently than you might expect:

.. the MySQL algorithm just or’s the bytes of a given passphrase against the previous bytes if the password is longer than 16 chars and just leaves them 0 when the password is shorter than 16 chars.

Not highly tested, but this seems to yield the same results (in hex).

<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>

Note: If you are using mySQL for encryption be sure to see its documentation which mentions the plain text may end up in various logs (replication, history, etectera) and "may be read by anyone having read access to that information".


Update: Things may have changed, but according to this 2004 bug report the .mysql_history file is only on Unix. (Keep in mind there may be other log files) Detailed instructions for clearing .mysql_history can be found in the manual, but in summary:

  • Set the MYSQL_HISTFILE variable to /dev/null (on each log in)
  • Create .mysql_history as a symbolic link to /dev/null (only once)

这篇关于CF8和AES解密MySQL AES:编码不一样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆