6

我们有一个用 Coldfusion9 编写的静默登录服务,它接受来自外部系统的加密字符串,然后根据商定的算法/编码设置解密。多年来,这在运行 ASP/JAVA/PHP 的系统上一直没有问题,但是我们现在有一个客户别无选择,只能使用 CryptoJS 来执行加密,而在我的一生中,我无法弄清楚为什么这不会在 Coldfusion 中解密。

我的加密知识并不出色,但我注意到的是,每次我执行加密时,完全相同的字符串/密钥的 CryptoJS 加密密文都会有所不同,而在 Coldfusion/Java 中,我总是可以期待完全相同的加密字符串。我不确定这是否与编码相关,但我之前从未遇到过从任何其他系统接受加密字符串的问题,所以我希望这是我在 CryptoJS 中加密的方式不正确。

<cfoutput>

<!--- Set String and Key --->
<cfset theKey = toBase64("1234567812345678")>
<cfset string = "max.brenner@google.com.au">

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

1 回答 1

13

似乎有两个问题:

  1. CryptoJS 没有使用您的变量作为key. 正如@Miguel-F 提到的,当您传入一个字符串时,“它被视为密码短语并用于派生 [the] 实际密钥和 IV”。两者都是随机生成的,这就是您的加密结果不断变化的原因。但更重要的是,这意味着 CryptoJS 使用的key与您的 CF 代码中的完全不同,这就是 decrypt() 失败的原因。(至少这是部分原因......)

  2. 第二个问题是除了算法“AES”之外,还有另外两个必须匹配的加密设置:模式填充方案。虽然 CryptoJS 和 ColdFusion 使用相同的填充方案默认值,但“模式”不同:

您需要确保两侧的所有三个设置都相同。尝试在 CF 中使用 CBC 模式,因为无论如何它比 ECB 更安全。注意:它需要添加一个 IV 值。

CF 代码:

<!--- this is the base64 encrypted value from CryptoJS ---> 
<cfset encrypted = "J2f66oiDpZkFlQu26BDKL6ZwgNwN7T3ixst4JtMyNIY=">
<cfset rawString = "max.brenner@google.com.au">
<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>


编辑:

说了这么多,客户端“别无选择,只能使用 CryptoJS 执行加密”是什么意思?为什么他们不能使用服务器端加密?我不是加密专家,但在 javascript 中进行加密,并在客户端上公开密钥,一开始听起来并不安全......

于 2013-05-17T17:57:31.743 回答