【问题标题】:Creating a Google reCAPTCHA 'secure token' in ColdFusion在 ColdFusion 中创建 Google reCAPTCHA“安全令牌”
【发布时间】:2015-12-21 11:31:02
【问题描述】:

Google 允许您为 reCAPTCHA 创建一个“安全令牌”,这意味着您可以在多个域中使用相同的密钥/秘密。无需为您照顾的每个域创建密钥/秘密。

这是他们的文档,正如您所见,除了an example in Java 之外,它对令牌的加密方式一无所知。我的问题是这将如何用 ColdFusion 编写。我已经破解了 4 个小时,但就是无法让它工作。我查看过的其他示例:

任何 ColdFusion 加密专家都知道如何做到这一点?

更新

感谢 Leigh,认为我们已经走得更远了,但仍然看到“无效 stoken”。这是我所拥有的:

json_token = '{"session_id":"#createUUID()#","ts_ms":#dateDiff("s", dateConvert("utc2Local", "January 1 1970 00:00"), now())#}';
secret_key_hash = hash(secret_key,"SHA", "UTF-8");
secret_key_binary = binaryDecode(secret_key_hash, "hex");
secret_key_aes = arraySlice(secret_key_binary,1,16);
secret_key_base64 = binaryEncode( javacast("byte[]", secret_key_aes), "base64");
secure_token = Encrypt(json_token,secret_key_base64,"AES/ECB/PKCS5Padding",'base64');

我们在 Java 1.7 上使用 ColdFusion 9,arraySlice 方法不可用或底层 java .subList()。所以我们使用来自 cflib.org 的 arraySlice UDF

我在PHP实现上也看到了关于URL编码的cmets,所以最后我也试过这个,没有效果:

    secure_token = Replace(secure_token,"=","","ALL");
    secure_token = Replace(secure_token,"+","-","ALL");
    secure_token = Replace(secure_token,"/","_","ALL");

【问题讨论】:

  • 虽然这是一个有趣的问题,但考虑到范围 - 它很可能因“太宽泛”而被关闭。你能告诉我们你尝试了什么,特别是你翻译困难或遇到问题的部分吗?
  • 重新阅读您的问题后,您只是问加密是如何完成的吗?因为这是一个狭窄得多的问题。简而言之,它只是标准的 AES,对加密密钥进行了轻微的操作。见my response。尽管将来,请在问题中包含您尝试过的代码。这将有助于澄清问题(并且可能避免将其关闭为“过于宽泛”)。

标签: coldfusion cfml lucee


【解决方案1】:

注意:发布此内容是因为我在问题结束之前就已经写过了。尽管将来,请在问题中包含您尝试过的代码。这将有助于澄清问题(并可能避免将其关闭为“过于宽泛”)

不了解令牌是如何加密的

如果您只停留在加密部分,它看起来像来自the java example 的标准 AES 加密(ECB 模式和 PKCS5Padding)。唯一棘手的部分是加密密钥的处理。

byte[] key = siteSecret.getBytes("UTF-8");
key = Arrays.copyOf(MessageDigest.getInstance("SHA").digest(key), 16);

在 java 代码中,getKey() 方法解码密钥字符串并使用 SHA1 对其进行哈希处理,生成 20 个字节(或 160 位)。由于这不是valid AES key size,因此代码会抓取前十六 (16) 个字节以用作 128 位 AES 加密密钥。其余的 java 代码只是基本的 AES 加密,您可以使用 encrypt() 函数在 CF 中轻松重现。

在 CF 中复制加密:

  1. 散列密钥字符串

    hashAsHex = hash(secretKey, "SHA", "UTF-8");

  2. 然后将哈希解码为二进制,这样您就可以提取前十六 (16) 个字节。这为您提供了 128 位 AES 加密密钥(二进制形式):

    hashAsBinary = binaryDecode(hashAsHex, "hex"); keyBytes = arraySlice(hashAsBinary, 1, 16);

  3. 现在只需将密钥字节转换为 base64 字符串,并将其传递给 encrypt() 函数:

    keyAsBase64 = binaryEncode( javacast("byte[]", keyBytes), "base64"); token = encrypt(jsonToken, keyAsBase64 , "AES/ECB/PKCS5Padding", "base64");

就是这样。我会让你自己解决剩下的问题。

【讨论】:

  • 感谢 Leigh,我们快到了,但仍然看到“无效 stoken”。我已经修改了顶部的问题
  • 天啊 :) 你是对的。更改为 #dateConvert("local2utc", now()).getTime()# 现在可以使用了!但之后还需要字符转换secure_token = Replace(secure_token,"=","","ALL"); secure_token = Replace(secure_token,"+","-","ALL"); secure_token = Replace(secure_token,"/","_","ALL");
  • 感谢 Leigh 的所有帮助,非常感谢。
  • 对于ts_ms,我必须使用dateDiff("s", dateConvert("utc2Local", "January 1 1970 00:00"), now()) * 1000
猜你喜欢
  • 2015-10-07
  • 1970-01-01
  • 2022-07-21
  • 1970-01-01
  • 2017-09-15
  • 1970-01-01
  • 2017-11-14
  • 2020-08-29
  • 2014-10-27
相关资源
最近更新 更多