Я разрабатываю игру на Java, которая будет упакована в виде апплета, и я работаю над сетевым аспектом. Я разработал поток сеанса, который будет работать для частоты запросов и потребностей безопасности, не требуя использования SSL. Процесс передачи данных свободно основан на том, как facebook подписывает свой подписанный_токен, используемый с их процессом OAuth. Вот упрощенный контекст:
Как вы можете сделать вывод, если они не совпадают, тогда я сбросил пакеты данных и ошибок из-за недействительных данных. Моя проблема в том, что, в то время как шестнадцатеричное кодирование результата идеально соответствует, необработанный двоичный код, похоже, никогда не соответствует . Ниже приведены извлеченные тестовые примеры php и Java, которые я установил:
Примечание. Из-за различий в том, как php и java генерируют структуру JSON для ассоциативных массивов php / java, я использую значение секретности вместо полезной нагрузки строки, чтобы оба поля были согласованы между платформами.
Php:
$secret = "922ec205d8e4d0ea06079d60a5336fffd9cf0aea"; $json = $secret; //json_encode($test_array); $hmac_a = hash_hmac('sha256',$json,$secret); $hmac_b = hash_hmac('sha256',$json,$secret,$raw=true); echo(htmlentities($hmac_a)."<br/>\n"); echo(htmlentities($hmac_b)."<br/>\n");
Вывод в браузере:
ff21a9e468ac49863e5e992324ac8bc92f239a08100b0f329b087be16f5ad382
ÿ! © äh¬I †> ^ ™ # $ ¬ <Э / # Š2> {áoZÓ,
Ява:
Mac hmac = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(Charset.forName("UTF-8").encode(this.secret).array(), "HmacSHA256"); hmac.init(secret_key); byte[] digest = hmac.doFinal(this.secret.getBytes("UTF-8")); System.out.println(hexify(digest)); System.out.println(new String(digest,"UTF-8"));
Консольный выход:
ff21a9e468ac49863e5e992324ac8bc92f239a08100b0f329b087be16f5ad382
! h I > ^ # $ / # 2 { oZӂ
При копировании на php и произнесении эхо, эта вторая строка выглядит так:
: Ï¿½ ��h�I�> ^ � # $ ��� / # ���2 {�oZÓ,
Обратите внимание, что хотя шестнадцатеричный код идентичен, двоичный файл отличается, но содержит тот же конец (oZÓ,), когда отображается из одного источника. Фактически, он содержит все более общие символы (! HI> ^ # $ / # 2 {oZÓ,) по порядку. Я играл с копированием вывода консоли на php, а затем отображал как двоичную строку, регулярную строку, utf8_encode'd двоичную / регулярную строку, а также utf8_encode'ing $ hmac_b. Кажется, ничто не сравнит исходные версии.
Я запустил mb_detect_encoding на hmac php, и он сказал мне UTF-8. Я также установил все в javax.crypto.Mac для UTF-8 и отображался как UTF-8, но не играл в кости. Я знаю, что UTF-8 Java не отличается от UTF-8 php, потому что это противоречит концепции наличия стандартных наборов символов. Что тут происходит?
Примечание. Хотя я теперь предпочитаю и могу использовать шестнадцатеричную версию для кодировки URL, мне все равно хотелось бы знать, что происходит с этим набором символов, и, возможно, как это исправить.
Я не эксперт по Java, но похоже, что вы делаете две разные вещи …
Вы используете htmlentities()
в PHP, который преобразует символы, такие как ÿ
в &yulm;
, в то время как ваша Java отключена, пытается сбросить данные UTF-8.
Почему вы действительно ожидаете действительных данных UTF-8 после HMAC? UTF-8 предназначен для представления символов Unicode, а не случайных хэшей.
Используя это в PHP:
$secret = "922ec205d8e4d0ea06079d60a5336fffd9cf0aea"; $json = $secret; $hmac_a = hash_hmac('sha256',$json,$secret); $hmac_b = hash_hmac('sha256',$json,$secret,$raw=true); echo $hmac_a . "\n"; echo $hmac_b . "\n";
Я получаю следующее (в терминале с поддержкой UTF-8):
ff21a9e468ac49863e5e992324ac8bc92f239a08100b0f329b087be16f5ad382 ! h I >^ #$ /#2{ oZӂ
Это вполне ожидаемо. $hmac_b
эффективно бинарно интерпретируется как UTF-8, поэтому он будет заполнен недопустимыми последовательностями UTF-8. Не ожидайте, что это будут персонажи. Вы будете лучше смотреть на него как на выход ISO-8859-1, который не является многобайтным:
ff21a9e468ac49863e5e992324ac8bc92f239a08100b0f329b087be16f5ad382 �!��h�I�>^�#$���/#ï¿2ï¿{�oZÓ
(В конце этого выхода есть также управляющий символ \x82
)
Дело в том, что вы сравниваете яблоки с апельсинами в грушей упаковке.