5

我正在尝试复制以下代码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)- 计算到什么?.. 返回什么?
  • System.Text.Encoding.ASCII.GetBytes(stringToSign);- 这会返回什么?
  • new HMACSHA1(new Guid(apiToken).toByteArray());没有密钥?,使用的密钥是什么?

任何资源或帮助将不胜感激。我在 SO 上尝试了其他答案的变体,但没有任何乐趣。

我可以在线某处运行这 3 行代码吗(例如JSFiddle,但对于C#?),以便我可以看到每一行的输出?


更新 - 增加赏金

仍然有这个问题,我已经设法C#在 Visual Studio 中测试代码,但是在PHP.

我想...

.. 将上面的C#代码(特别是创建SHA1哈希的 3 行)转换为 PHP(查看Pseudo Code我在上面发布的内容)。我应该能够C#使用 PHP 匹配哈希。

如果您有任何其他问题,请询问。

4

3 回答 3

3

问题是 GUID 的字符串形式颠倒了 GUID 前 3 段中 2 个字符的十六进制数字的顺序。有关详细信息,请参阅示例中的注释: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 无效,所以我不得不稍微更改它。

于 2013-06-25T20:38:25.943 回答
0

当我不必测试代码时,这很容易:P

http://php.net/manual/en/function.hash-hmac.php - 这相当于 HMACSHA1 c# 类。

字符串 hash_hmac (字符串 $algo , 字符串 $data , 字符串 $key [, bool $raw_output = false ] )

所以 $algo = "sha1"

$data 是您的 $stringToSign - 因为这已经是一个 ascii 字符串(我希望) - C# 只是采用相同的字节。

new Guid(apiToken).toByteArray() -> 这是 GUID 的 16 字节 (16*8 = 128) 表示 - 即 32*4 = 128 位。这是关键。

$key 是一个字符串,因此您需要与 $apiToken 等效的 ASCII 字符串(这是 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)

那应该这样做...享受:)

于 2013-06-25T19:48:06.730 回答
0

我遇到了几乎同样的问题,经过一番谷歌搜索后,我发现了这篇文章: https ://www.reddit.com/r/PHP/comments/2k9tol/string_to_byte_array_using_utf8_encoding/

在 PHP 中,字符串已经是字节数组。您遇到的具体问题是什么?

对我来说,解决方案只是base64_encode('apikey')

于 2020-05-28T12:47:48.687 回答