javascript CryptoJS 中的 AES 加密和 Coldfusion 中的解密
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16600509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AES Encrypt in CryptoJS and decrypt in Coldfusion
提问by Phil Rasmussen
We've got a Silent Login service written in Coldfusion9 that accepts encrypted strings from external systems and then decrypts based on an agreed Algorithm/Encoding setup. This has worked without issue for years now from systems running ASP/JAVA/PHP, but we now have a client who has no choice but to use CryptoJS to perform the encryption and for the life of me I cannot work out why this won't decrypt in Coldfusion.
我们有一个用 Coldfusion9 编写的静默登录服务,它接受来自外部系统的加密字符串,然后根据商定的算法/编码设置进行解密。这在运行 ASP/JAVA/PHP 的系统中多年来一直没有问题,但我们现在有一个客户别无选择,只能使用 CryptoJS 来执行加密,我一生都无法弄清楚为什么这不会在 Coldfusion 中解密。
My knowledge of encryption isn't brilliant but the thing I am noticing is the CryptoJS encrypted ciphertext for the exact same string/key differs every time i perform the encryption whereas in Coldfusion/Java i can always expect the exact same encrypted string. I'm not sure if this is encoding related or not but i've never run into this issue accepting encrypted strings from any other system before, so I am hoping it's the way I am encrypting in CryptoJS that is incorrect.
我的加密知识并不出色,但我注意到的是,每次执行加密时,完全相同的字符串/密钥的 CryptoJS 加密密文都不同,而在 Coldfusion/Java 中,我总是可以期待完全相同的加密字符串。我不确定这是否与编码相关,但我以前从未遇到过从任何其他系统接受加密字符串的问题,所以我希望这是我在 CryptoJS 中加密的方式不正确。
<cfoutput>
<!--- Set String and Key --->
<cfset theKey = toBase64("1234567812345678")>
<cfset string = "[email protected]">
<!--- CryptoJS AES Libraries --->
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/enc-base64-min.js"></script>
<script>
// Encrypt String using CryptoJS AES
var encrypted = CryptoJS.AES.encrypt("#string#", "#theKey#");
console.log(encrypted.toString());
// Decrypt String using CryptoJS AES
var decrypted = CryptoJS.AES.decrypt(encrypted, "#theKey#");
console.log(decrypted.toString(CryptoJS.enc.Utf8));
</script>
<!--- Coldfusion Decrypt String / FAILS --->
Decrypted: #decrypt(encryptedEmail, "#theKey#", "AES", "BASE64")#
</cfoutput>
回答by Leigh
There seem to be two issues:
好像有两个问题:
CryptoJS is not using your variable as the
key
. As @Miguel-F mentioned, when you pass in a string, "it's treated as a passphrase and used to derive [the] actual key and IV". Both are randomly generated, which is why your encrypted result keeps changing. But more importantly, this means that CryptoJS is using a completely differentkey
than the one in your CF code and that is why decrypt() fails. (At least it is part of the reason ...)The second problem is that in addition to the algorithm "AES", there are two other encryption settings which must match: modeand padding scheme. While CryptoJS and ColdFusion use the same defaults for padding scheme, the "modes" are different:
- ColdFusion uses "ECB". "AES" is actually short for
"AES/ECB/PKCS5Padding"
- CryptoJS uses "CBC", which requires an additional
iv
(initialization vector) value.
- ColdFusion uses "ECB". "AES" is actually short for
CryptoJS 没有使用您的变量作为
key
. 正如@Miguel-F 所提到的,当您传入一个字符串时,“它被视为密码短语并用于派生 [the] 实际密钥和 IV”。两者都是随机生成的,这就是您的加密结果不断变化的原因。但更重要的是,这意味着 CryptoJS 使用的key
代码与您的 CF 代码中的代码完全不同,这就是decrypt() 失败的原因。(至少是部分原因……)第二个问题是除了算法“AES”之外,还有两个其他的加密设置必须匹配:mode和padding scheme。虽然 CryptoJS 和 ColdFusion 使用相同的默认填充方案,但“模式”是不同的:
- ColdFusion 使用“ECB”。“AES”实际上是缩写
"AES/ECB/PKCS5Padding"
- CryptoJS 使用“CBC”,它需要一个额外的
iv
(初始化向量)值。
- ColdFusion 使用“ECB”。“AES”实际上是缩写
You need to ensure all three settings are the same on both sides. Try using CBC mode in CF, since it is more secure than ECB anyway. Note: It requires adding an IV value.
您需要确保两侧的所有三个设置都相同。尝试在 CF 中使用 CBC 模式,因为它无论如何都比 ECB 更安全。注意:它需要添加一个 IV 值。
CF Code:
CF代码:
<!--- this is the base64 encrypted value from CryptoJS --->
<cfset encrypted = "J2f66oiDpZkFlQu26BDKL6ZwgNwN7T3ixst4JtMyNIY=">
<cfset rawString = "[email protected]">
<cfset base64Key = "MTIzNDU2NzgxMjM0NTY3OA==">
<cfset base64IV = "EBESExQVFhcYGRobHB0eHw==">
<cfset ivBytes = binaryDecode(base64IV, "base64")>
<cfoutput>
#decrypt(encrypted, base64Key, "AES/CBC/PKCS5Padding", "base64", ivBytes)#
</cfoutput>
CryptoJS: (Adjusted Original Example)
CryptoJS:(调整后的原始示例)
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/enc-base64-min.js"></script>
<script>
var text = "#rawString#";
var key = CryptoJS.enc.Base64.parse("#base64Key#");
var iv = CryptoJS.enc.Base64.parse("#base64IV#");
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv});
console.log(encrypted.toString());
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {iv: iv});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
</script>
Edit:
编辑:
All that said, what do you mean by the client "has no choice but to use CryptoJS to perform the encryption"? Why cannot they use server side encryption? I am not an encryption expert, but doing encryption in javascript, and exposing the key on the client, does not sound wildly secure to begin with ...
说了这么多,客户“别无选择,只能使用 CryptoJS 来执行加密”是什么意思?为什么他们不能使用服务器端加密?我不是加密专家,但是在 javascript 中进行加密,并在客户端上公开密钥,从一开始听起来并不安全......