对于我在做错事情而不是关键任务而言,这已经成为一种练习,但我仍然希望看到我所犯的错误(简单可能)。
我正在使用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。
答案 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(仅一次)的符号链接