Создание «защищенного токена» Google reCAPTCHA в ColdFusion

Google позволяет вам создать «защищенный токен» для reCAPTCHA, что означает, что вы можете использовать один и тот же ключ/секрет в нескольких доменах. Нет необходимости создавать ключи/секреты для каждого домена, за которым вы следите.

Вот их документы, как видите, в них нет понимания того, как зашифрован токен, кроме примера в Ява. Мой вопрос в том, как это будет написано в ColdFusion. Я взломал его в течение 4 часов, но просто не могу заставить его работать. Другие примеры, которые я рассмотрел:

Кто-нибудь из гуру шифрования ColdFusion знает, как это сделать?

ОБНОВЛЕНИЕ

Спасибо, Ли, думаю, мы продвинулись дальше, но все еще видим «недействительный стокен». Вот что у меня есть:

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');

Мы используем ColdFusion 9 на Java 1.7, метод arraySlice недоступен или базовый java .subList(). Итак, мы используем пользовательскую функцию ArraySlice с сайта cflib.org.

Я также видел комментарии к реализации PHP о закодированном URL-адресе, поэтому я также пробовал это в конце, безрезультатно:

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

person Dave Quested    schedule 25.11.2015    source источник
comment
Хотя это интересный вопрос, учитывая масштабы, он, скорее всего, будет закрыт как слишком широкий. Можете ли вы показать нам, что вы пробовали, и конкретно, с какой частью у вас возникли трудности с переводом или проблемы?   -  person Leigh    schedule 26.11.2015
comment
Перечитав свой вопрос, вы просто спрашиваете, как выполняется шифрование? Потому что это гораздо более узкий вопрос. Короче говоря, это просто стандартный AES с небольшими манипуляциями с ключом шифрования. См. мой ответ. Хотя в будущем, пожалуйста, включите код, который вы пробовали, в вопрос. Это помогло бы прояснить проблему (и, вероятно, избежать ее закрытия как слишком широкой).   -  person Leigh    schedule 26.11.2015


Ответы (1)


NB: Публикую это, так как я уже написал это до того, как вопрос был закрыт. Хотя в будущем, пожалуйста, включите код, который вы пробовали, в вопрос. Это помогло бы прояснить проблему (и, возможно, избежать ее закрытия как «слишком широкой»)

нет понимания того, как зашифрован токен

Если вы застряли только на части шифрования, это выглядит как стандартное шифрование AES (режим ECB и PKCS5Padding) из пример Java. Единственная сложная часть — это обработка ключа шифрования.

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

В коде Java метод getKey() декодирует ключевую строку и хэширует ее с помощью SHA1, который выдает 20 байт (или 160 бит). Поскольку это не допустимый размер ключа AES, код захватывает первые шестнадцать (16) байтов для использовать в качестве 128-битного ключа шифрования AES. Остальная часть java-кода представляет собой просто базовое шифрование AES, которое вы можете легко воспроизвести в CF, используя encrypt() функция.

Чтобы воспроизвести шифрование в CF:

  1. Хэш строки secretKey

    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");

Вот и все. Я оставлю вас, чтобы вы сами догадались об остальном.

person Leigh    schedule 26.11.2015
comment
Спасибо, Ли, мы почти у цели, но все еще видим «недействительный стокен». Я исправил вопрос вверху - person Dave Quested; 27.11.2015
comment
ОМГ :) Ты прав. Изменил на #dateConvert("local2utc", now()).getTime()# теперь работает! Но также потребовалось преобразование символов впоследствии secure_token = Replace(secure_token,"=","","ALL"); secure_token = Replace(secure_token,"+","-","ALL"); secure_token = Replace(secure_token,"/","_","ALL"); - person Dave Quested; 27.11.2015
comment
Спасибо за вашу помощь, Лей, признателен. - person Dave Quested; 27.11.2015
comment
Для ts_ms мне пришлось использовать dateDiff("s", dateConvert("utc2Local", "January 1 1970 00:00"), now()) * 1000 - person James Moberg; 04.02.2016