簡體   English   中英

將HMAC-SHA1 PHP腳本轉換為C#腳本

[英]Convert HMAC-SHA1 PHP script to C# script

我正在研究一個使用API​​的項目,並且需要為Web服務調用標頭生成簽名。 API文檔提供了一些具有“已知良好”結果的PHP示例代碼,因此您可以將其轉換為您選擇的編程語言,我碰壁了,我需要一些幫助。

我以前從未與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]";
    ?>

輸出: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 =

這里的問題是因為您( 或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哈希值,它實際上是生成一個...... UTF-8中HMAC哈希自身的小寫十六進制值的base64編碼的字符串 ...在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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM