我们有一个用 Coldfusion9 编写的静默登录服务,它接受来自外部系统的加密字符串,然后根据商定的算法/编码设置进行解密。多年来,这在运行 ASP/JAVA/PHP 的系统上一直没有问题,但我们现在有一个客户别无选择,只能使用 CryptoJS 来执行加密,我一生都无法弄清楚为什么这不起作用在 Coldfusion 中解密。
我对加密的了解并不出色,但我注意到的是,每次执行加密时,完全相同的字符串/密钥的 CryptoJS 加密密文都会有所不同,而在 Coldfusion/Java 中,我总是可以期望完全相同的加密字符串。我不确定这是否与编码相关,但我以前从未遇到过从任何其他系统接受加密字符串的问题,所以我希望这是我在 CryptoJS 中加密的方式不正确。
<cfoutput>
<!--- Set String and Key --->
<cfset theKey = toBase64("1234567812345678")>
<cfset string = "[email protected] /cdn-cgi/l/email-protection">
<!--- 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>
似乎有两个问题:
CryptoJS 没有使用你的变量作为key
。正如@Miguel-F 提到的,当你传入一个字符串时,“它被视为密码并用于派生实际密钥和 IV” https://code.google.com/p/crypto-js/#The_Cipher_Input。两者都是随机生成的,这就是您的加密结果不断变化的原因。但更重要的是,这意味着 CryptoJS 使用的是完全不同的key
比你的CF代码中的那个要大,这就是decrypt()失败的原因。 (至少是部分原因……)
-
第二个问题是,除了算法“AES”之外,还有两个其他加密设置必须匹配:mode http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation and 填充方案 http://en.wikipedia.org/wiki/Padding_%28cryptography%29。虽然 CryptoJS 和 ColdFusion 使用相同的默认填充方案,但“模式”不同:
-
ColdFusion 使用“ECB” http://helpx.adobe.com/coldfusion/kb/strong-encryption-coldfusion-mx-7.html。 “AES”实际上是缩写
"AES/ECB/PKCS5Padding"
- CryptoJS 使用“CBC”,这需要额外的
iv
(初始化向量 http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29) value.
您需要确保两侧的所有三个设置都相同。尝试在 CF 中使用 CBC 模式,因为无论如何它比 ECB 更安全。注意:需要添加IV值。
CF Code:
<!--- this is the base64 encrypted value from CryptoJS --->
<cfset encrypted = "J2f66oiDpZkFlQu26BDKL6ZwgNwN7T3ixst4JtMyNIY=">
<cfset rawString = "[email protected] /cdn-cgi/l/email-protection">
<cfset base64Key = "MTIzNDU2NzgxMjM0NTY3OA==">
<cfset base64IV = "EBESExQVFhcYGRobHB0eHw==">
<cfset ivBytes = binaryDecode(base64IV, "base64")>
<cfoutput>
#decrypt(encrypted, base64Key, "AES/CBC/PKCS5Padding", "base64", ivBytes)#
</cfoutput>
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:
综上所述,您所说的客户是什么意思“别无选择,只能使用 CryptoJS 来执行加密”?为什么他们不能使用服务器端加密?我不是加密专家,但在javascript中进行加密,并且在客户端公开密钥,一开始听起来不太安全......
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)