【问题标题】:AES Encrypt in CryptoJS and decrypt in ColdfusionCryptoJS 中的 AES 加密和 Coldfusion 中的解密
【发布时间】:2016-02-19 14:37:37
【问题描述】:

我们有一个用 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>

【问题讨论】:

  • 您的示例代码无法运行,因为您不能像现在这样将 JavaScript 和 ColdFusion 变量混合在一起。 JavaScript 是客户端,ColdFusion 是服务器端,它们无法说明你是如何让它们工作的。
  • Matt 当此脚本作为 CFM 运行并由 Coldfusion 解析/编译时,将在运行 javascript 之前评估这些变量。多年来,我从事过很多 Coldfusion 和 javascript 交换数据的项目,我认为这里的问题与 CryptoJS 中的编码有关,我从简单的角度来处理这个问题。
  • 加密电子邮件未在任何地方定义。这不是您的整体问题,但示例代码没有给出您所说的错误
  • "我注意到的是,每次我执行加密时,完全相同的字符串/密钥的 CryptoJS 加密密文都会不同"我认为这是因为你没有通过密钥作为 CryptoJS 的 WordArray,因此每次调用它时它都会为您构建一个。 CryptoJS Custom Key and IVanother reference for you
  • 抱歉,Miguel 的回复很晚,这是有道理的,在阅读了下面 Leigh 的完整回复后,我现在对加密有了更多的了解,谢谢大家。

标签: javascript encryption coldfusion aes cryptojs


【解决方案1】:

似乎有两个问题:

  1. CryptoJS 没有使用你的变量作为key。正如@Miguel-F 提到的,当你传入一个字符串时,"it's treated as a passphrase and used to derive [the] actual key and IV"。两者都是随机生成的,这就是您的加密结果不断变化的原因。但更重要的是,这意味着 CryptoJS 使用的 key 与您的 CF 代码中的 key 完全不同,这就是 decrypt() 失败的原因。 (至少这是部分原因……)

  2. 第二个问题是除了算法“AES”之外,还有另外两个必须匹配的加密设置:modepadding scheme。虽然 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 中进行加密,并且在客户端公开密钥,一开始听起来并不安全......

【讨论】:

  • +1 @Leigh - 我今天早上一直在看它(但后来不得不离开),基本上得出了和你一样的结论。如果没有所有相同的部分,ColdFusion 将无法解密该值。我什至写了一个类似于你在这里的测试脚本,但从来没有让它正确解密......
  • 是的,它通常是像编码、模式或填充这样的小差异。但是使用加密就可以获得完全不同的结果;-) @Phil - 为了清楚起见,您可能需要明确设置 CryptoJS 模式和填充,即{iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}。就这么清楚了。
  • @Miguel-F - 出于笑容,我也尝试使用不太安全的ECB 模式。但没有运气。文档说它是受支持的,但我不太确定......因为他们还说“如果你传递实际的密钥,你还必须传递实际的 IV。”。鉴于 ECB 不使用没有意义的 iv .. 不过没有太大的损失,因为无论如何 CBC 更好。
  • 你这么说很有趣,因为我正在尝试 ECB 模式。至少这让我感觉更好,因为我无法让它工作。 ;)
  • 非常感谢您花时间写这个答案,Leigh 的工作就像一个魅力,我学到了更多关于加密过程和特定模式的知识,因为我以前从未使用过 CBC 和 IV。我可以确认您生成的 IV 和密钥都可以使用 Coldfusion GenerateSecretKey('AES') 来完成。我看起来像一个 AES 密钥,但只是想确认一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 2013-07-20
  • 1970-01-01
相关资源
最近更新 更多