如何在PHP中复制这个C#哈希? (toByteArray(), ComputeHash())

问题描述 投票:5回答:3

我正试图在以下代码中复制 PHP这是一个API的例子代码,我必须与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# 方法doreturn?

  • ComputeHash(byteArray) - 计算到什么......返回的是什么?
  • System.Text.Encoding.ASCII.GetBytes(stringToSign); - 返回的是什么?
  • new HMACSHA1(new Guid(apiToken).toByteArray()); 没有秘钥吗,使用的秘钥是什么?

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

我可以在网上某个地方运行这3行代码吗(如 JSFiddle 但对于 C#)所以我可以看到每一行的输出?


更新 - 添加赏金

还是有问题,我设法测试了一下 C# 代码,但在Visual Studio中却难以得到同样的哈希值。PHP.

我想...

...以上 C# 代码(特别是创建了 SHA1 哈希)转换为PHP(请查阅 Pseudo Code 我在上面发的)。) 我应该能够匹配 C# 使用PHP进行哈希运算。

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

c# php sha1 hmac
3个回答
3
投票

问题是GUID的字符串形式颠倒了GUID前3段中2个字符的十六进制数字的顺序。更多信息请参见示例中的注释。http:/msdn.microsoft.comen-uslibrarysystem.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无效,所以我不得不稍作修改。


0
投票

这很简单,当我不用测试代码的时候:P。

http:/php.netmanualenfunction.hash-hmac.php - 这相当于HMACSHA1的c#类。

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

所以$algo = "sha1"

$data是你的$stringToSign--因为那已经是一个ascii字符串(我希望)--C#只是取相同的字节等价物。

new Guid(apiToken).toByteArray() -> 这是一个16字节(16*8 = 128)的GUID表示--是32*4 = 128位。这就是key。

$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.comcmsphp-convert-hex-strings-to-ascii-strings

因此,该方法调用现在工作。

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

这将返回一个二进制字符串--你需要将其转换为base64编码。

$final = base64_encode ($almostResult)

这样就可以了...享受吧:)


0
投票

我面临着几乎同样的问题,经过一些google搜索,我发现了这个帖子。https:/www.reddit.comrPHPcomments2k9tolstring_to_byte_array_using_utf8_encoding

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

对我来说,解决方法就是 base64_encode('apikey')

© www.soinside.com 2019 - 2024. All rights reserved.