Как я могу реплицировать хеширование C # в PHP? (toByteArray (), ComputeHash ())

Я пытаюсь реплицировать следующий код в PHP Это пример кода для API, с которым мне нужно взаимодействовать (код API и пример находится на C# , Мое приложение находится в PHP 5.3 ). Я не разработчик C #, и поэтому у меня проблемы с этим.

 // C# Code I am trying to replicate in PHP var apiTokenId = 1887; var apiToken = "E1024763-1234-5678-91E0-T32E4E7EB316"; // Used to authenticate our request by the API (which is in C#) var stringToSign = string.Empty; stringToSign += "POST"+"UserAgent"+"http://api.com/post"; // Here is the issue, How can I do the following 3 lines in PHP? // No "secret key" provided?.. How do I do this in PHP? var hmacsha1 = new HMACSHA1(new Guid(apiToken).toByteArray()); // Make a byte array with ASCII encoding. byte[] byteArray = System.Text.Encoding.ASCII.GetBytes(stringToSign); // Finally, 'computeHash' of the above (what does this do exactly?!) var calculatedSignature = Convert.ToBase64String(hmacsha1.ComputeHash(byteArray)); 

Я пробовал много вариантов с помощью pack() и других функций, которые я нашел в Интернете, но без каких-либо сравнений, я не знаю, правильно ли я сделал это.

Могут ли любые разработчики C # выполнить приведенный выше код и опубликовать полученные значения, чтобы я мог использовать это для проверки / проверки?

Я попытался проверить MSDN, чтобы узнать, что делают эти методы, но я застрял (и не уверен, что это правильно, поскольку мне нечего сравнивать).

PHP-псевдодекс

 // Set vars $apiToken = 'E1024763-1234-5678-91E0-T32E4E7EB316'; $apiTokenId = '1887'; $stringToSign = "POST"."UserAgent"."http://api.com/post"; // HowTo: Build a `byteArray` of our apiToken? (i think) // C#: var hmacsha1 = new HMACSHA1(new Guid(apiToken).toByteArray()); // HowTo: Convert our $stringToSign to a ASCII encoded `byteArray`? // C#: byte[] byteArray = System.Text.Encoding.ASCII.GetBytes(stringToSign); // HowTo: Generate a base64 string of our (`hmacsha1`.ComputeHash(byteArray)) // C#: var calculatedSignature = Convert.ToBase64String(hmacsha1.ComputeHash(byteArray)); 

Это звучит довольно просто и прямолинейно, но я не уверен, что делают некоторые из этих методов C #.

Что делают эти методы C# ?

  • ComputeHash(byteArray)ComputeHash(byteArray) на что? .. что возвращается?
  • System.Text.Encoding.ASCII.GetBytes(stringToSign); -Что это возвращает?
  • new HMACSHA1(new Guid(apiToken).toByteArray()); Нет секретного ключа ?, какой ключ используется?

Любые ресурсы или помощь будут высоко оценены. Я попробовал варианты других ответов на SO, но без радости.

Могу ли я запустить 3 строки кода где-нибудь в сети (например, JSFiddle но для C# ?), Чтобы я мог видеть вывод каждой строки?


Обновление – Добавлена ​​баунти

У меня все еще есть проблемы с этим, мне удалось проверить код C# в Visual Studio, но мне трудно получить тот же хеш, сгенерированный в PHP .

Я бы хотел…

.. приведенный выше код C# (в частности, 3 строки, которые создают хэш SHA1 ), которые должны быть преобразованы в PHP (ознакомьтесь с Pseudo Code опубликованным выше). Я должен уметь сопоставлять хэш C# с помощью PHP.

Если у вас есть другие вопросы, пожалуйста, спросите.

Проблема в том, что строковая форма GUID меняет порядок двухзначных шестнадцатеричных чисел в первых трех сегментах GUID. Для получения дополнительной информации см. Комментарии в этом примере: http://msdn.microsoft.com/en-us/library/system.guid.tobytearray.aspx

Следующий код должен работать:

 $apiTokenId = 1887; $apiToken = "E1024763-1234-5678-91E0-FF2E4E7EB316"; $stringToSign = ''; $hexStr = str_replace('-','',$apiToken); $c = explode('-',chunk_split($hexStr,2,'-')); $hexArr = array($c[3],$c[2],$c[1],$c[0],$c[5],$c[4],$c[7],$c[6],$c[8],$c[9],$c[10],$c[11],$c[12],$c[13],$c[14],$c[15]); $keyStr = ''; for ($i = 0; $i < 16; ++$i) { $num = hexdec($hexArr[$i]); $keyStr .= chr($num); } $stringToSign .= "POST" . "UserAgent" . "http://api.com/post"; $hmacsha1 = base64_encode(hash_hmac('sha1',$stringToSign,$keyStr,true)); 

Я протестировал этот код против кода C #, который вы указали выше, и результат был таким же. Однако GUID, указанный в исходном коде, недействителен, поэтому мне пришлось слегка его изменить.

Это довольно легко, когда мне не нужно проверять код: P

http://php.net/manual/en/function.hash-hmac.php – это эквивалент класса C # HMACSHA1.

string hash_hmac (строка $ algo, строка $ data, строка $ key [, bool $ raw_output = false])

Итак, $ algo = "sha1"

$ data – ваш $ stringToSign – поскольку это уже строка ascii (надеюсь), C # просто принимал эквивалент байта.

new Guid (apiToken) .toByteArray () -> это 16-байтное (16 * 8 = 128) представление GUID – 32 * 4 = 128 бит. Это ключ.

$ key – строка, так что вам нужен эквивалент строки ASCII для вашего $ apiToken (который содержит 32 шестнадцатеричных символа – первая полоса / игнорирует штрихи между ними) – E10247631234567891E0T32E4E7EB316 (исправить ключ – он не может иметь «T»)

 function hex2str($hex) { for($i=0;$i<strlen($hex);$i+=2) $str .= chr(hexdec(substr($hex,$i,2))); return $str; } $hexKey = hex2str($apiToken); //strip the dashes first 

http://www.linux-support.com/cms/php-convert-hex-strings-to-ascii-strings/

Итак, вызов метода теперь работает:

 $almostResult = hash_hmac ("sha1" , $stringToSign, $hexKey, true) 

Это возвращает двоичную строку, которую нужно преобразовать в кодировку base64.

 $final = base64_encode ($almostResult) 

Это должно сделать это … наслаждайтесь 🙂