将 HMAC 哈希从 C# 转换为 PHP

Converting HMAC Hash from C# to PHP

我已经查看了很多与此相关的问题,但看不出我犯了什么错误。我正在尝试生成共享访问签名以访问 Azure SB 队列。

我的 C# 代码运行正常:

    var expiry = 1499177142;// GetExpiry();
    string stringToSign = HttpUtility.UrlEncode(resourceUri);// + "\n" + expiry;
    HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));

    Console.WriteLine(Encoding.UTF8.GetBytes(stringToSign));

    var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    Console.WriteLine(signature);

    var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
    HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
    return sasToken;
// returns slXBw0u7Dt/YKS1Y+Wot02z730YXJ9NkS599JRzvDQI= for the signature element

我的 PHP 给出了一个非常不同的结果:

$stringToSign = rawurlencode($resourceURI);// . "%0A" . $expiry;

$sig = hash_hmac("sha256",utf8_encode($stringToSign),utf8_encode($key),false);
echo $sig."<br>";

$token = "SharedAccessSignature sr=".urlencode($resourceURI)
."&sig=".rawurlencode(base64_encode($sig))."&se=".$expiry."&skn=".$keyName;
return $token; //returns MGNlZWViYWRmMjE2NWJhZGRjNWNhNDZkYWRlOTQyMzc3ODBhMWM2ZjA1OTk4MjI0MGUzMzllZmY4ZTk2OGUxNA==

我试过编码 $stringToSign$key 而不是在散列中, strtoupperstrtolower$stringToSign 上但无法得到结果与 C#

相同

此代码应适用于 PHP 和 C#。

PHP:

<?php

$resourceURI = "http://nifi-eventhub.servicebus.windows.net/hub1";
$keyName = "hub-user";
$key = "secret";
$expiry = '1499177142'; // timestamp

// The format for the string is <resourceURI> + \n + <expiry>    
$stringToSign = strtolower(rawurlencode($resourceURI)) . "\n" . $expiry;

// Hash the URL encoded string using the shared access key
$sig = hash_hmac("sha256", utf8_encode($stringToSign), utf8_encode($key), false);

// Convert hexadecimal string to binary and then to base64
$sig = hex2bin($sig);
$sig = base64_encode($sig);

// 7kS3apSDpJFTYI1vxuo4t7syGG3FTBYI8foamMOtrEE=
echo $sig . "<br>\n";

// Generate authorization token
$token = "SharedAccessSignature sr=" . urlencode($resourceURI) . "&sig=" . rawurlencode($sig) . "&se=" . $expiry . "&skn=" . $keyName;
echo $token . "<br>\n";

在 C# 中

string expiry = "1499177142";
string resourceUri = "http://nifi-eventhub.servicebus.windows.net/hub1";
string keyName = "hub-user";
string secretkey = "secret";

string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;

HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secretkey));
byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));

var signature = Convert.ToBase64String(hashBytes);

// 7kS3apSDpJFTYI1vxuo4t7syGG3FTBYI8foamMOtrEE=
Console.WriteLine(signature);

var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);

Console.WriteLine(sasToken);