2016-07-29 14 views
0

Я работаю над проектом, чтобы использовать API, и мне нужно сгенерировать подпись для заголовка вызова веб-службы. Документация API предоставляет некоторый пример кода PHP с «хорошо известным» результатом, поэтому вы можете преобразовать его на свой язык программирования, и я столкнулся с стеной, и мне нужна помощь.Преобразование HMAC-SHA1 PHP-скрипт в сценарий C#

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

В основном API предоставил образец PHP-скрипта и его результаты, чтобы вы могли написать свою версию и протестировать ее.

Вот пример PHP и его результат. Я отправлю свою текущую попытку C# на тот же код ниже этого. Снова, СПАСИБО заблаговременно за любую помощь, которую вы можете предоставить.

Use the following code example to compare your signature generation with a 
    known signature. The PHP code example that follows provides a reference to 
    the generation of a signature for a GET call into the CDRN API. Use your 
    code with the parameter values listed to validate the same signature is 
    generated. 

    <?php 
    $cdrn_domain = "api.testing.cdrn.com"; 
    $secret_key = "cdrnpassword"; 
    $api_version = "1.1"; 
    $method_type = "GET"; 
    $case_id = "12345"; 
    $string_date = "2014-06-20T12:06:31Z"; 
    $string_to_sign = $method_type . "\n" . $cdrn_domain . "\n" . "/partners/cases/$case_id" . "\n" . "" . "\n" . $api_version . "\n" . $string_date . "\n"; 

    $signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, false))); 
    echo "SIGNATURE[$signature]"; 
    ?> 

Выход: ПОДПИСЬ [NWY3N2Q0NTdmZDQxZjA4YWI0Njg3YTEwODljODdiNTEwMTdmMzNlZg ==]

Здесь C# код мне нужна помощь с:

using System.Security.Cryptography; 

    string cdrn_domain = "api.testing.cdrn.com"; 
    string secret_key = "cdrnpassword"; 
    string api_version = "1.1"; 
    string method_type = "GET"; 
    string case_id = "12345"; 
    string string_date = "2014-06-20T12:06:31Z"; 
    string string_to_sign = method_type + "\n" + cdrn_domain + "\n" + "/partners/cases/" + case_id + "\n" + "" + "\n" + api_version + "\n" + string_date + "\n"; 

    var result = CreateSignature(string_to_sign, secret_key); 

    public string CreateSignature(string message, string key) 
    { 
     var encoding = new System.Text.UTF8Encoding(); 
     byte[] keyByte = encoding.GetBytes(key); 
     byte[] messageBytes = encoding.GetBytes(message); 
     using (var hmacsha1 = new HMACSHA1(keyByte, false)) 
     { 
      byte[] hashmessage = hmacsha1.ComputeHash(messageBytes); 
      return Convert.ToBase64String(hashmessage); 
     } 
    } 

Подпись генерируется из MY C# кодекса: X3fUV/1B8Iq0aHoQich7UQF/M + 8 =

ответ

1

Проблема здесь в том, что вы (или API) кодировали ошибочное значение хеша.

Из документации PHP для hash_hmac:

string hash_hmac (string $algo , string $data , string $key [, bool $raw_output = false ])

Параметры

...

raw_output

          Когда установлено значение TRUE, выводит необработанные двоичные данные. FALSE выходы нижнего регистра.

Так линия:

$signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, false))); 

вместо производства кодировке base64 HMAC хэш-значение, то на самом деле производит ... в кодировке base64 строку строчными-шестнадцатеричное значение хэша HMAC сама по себе ... в UTF-8 ... ¯ \ _ (ツ) _/¯

Вы должны заметить, что при замене третьего параметра hash_mac от false к true, было бы на самом деле производят такое же значение, как ваш C# функция.

$signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, true))); 

демо: ideone.com/lyrgKV


Очевидно, чтобы исправить вещи с вашей стороны (C#), чтобы соответствовать выходной API, мы должны в нижнем регистре-проклясть хэш перед кодированием его в base64:

public static string CreateSignature(string message, string key) 
{ 
    var encoding = new System.Text.UTF8Encoding(); 
    byte[] keyByte = encoding.GetBytes(key); 
    byte[] messageBytes = encoding.GetBytes(message); 
    using (var hmacsha1 = new HMACSHA1(keyByte, false)) 
    { 
     byte[] hashmessage = hmacsha1.ComputeHash(messageBytes); 

     string hashstring = BitConverter.ToString(hmacsha1.ComputeHash(messageBytes)).Replace("-","").ToLower(); 

     return Convert.ToBase64String(encoding.GetBytes(hashstring)); 
    } 
} 

демо: dotnetfiddle.net/FT4OQ4

+0

IronGeek, я никогда бы не понял это без тебя Помогите сэр! Большое вам спасибо за объяснение и помощь! Принимая ваш ответ сразу! – Josh