如何在PHP中复制此C#散列? (toByteArray(),ComputeHash())

我试图在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()和我在网上发现的其他function的许多变化,但没有任何可比性,我不知道我是否做得对。

任何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# ?)所以我可以看到每行的输出?


更新 – 赏金添加

我仍然遇到麻烦,我已经设法在Visual Studio中测试C#代码,但是在获取PHP生成的相同哈希时遇到了麻烦。

我想要…

..上面的C#代码(具体来说,创建SHA1哈希的3行)要转换成PHP(查看我上面发布的Pseudo Code )。 我应该能够使用PHP匹配C#哈希。

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

问题是GUID的字符串forms颠倒了GUID的前3个段中的2个字符的hex数字的顺序。 有关更多信息,请参阅示例中的注释: 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无效,因此我不得不稍微更改它。

当我不必测试代码时,它非常简单:P

http://php.net/manual/en/function.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() – >这是GUID的16字节(16 * 8 = 128)表示 – 这是32 * 4 = 128位。 这是关键。

$ key是一个字符串,所以你需要你的$ apiToken等效的ASCII字符串(这是32个hex字符 – 第一个条带/忽略它们之间的破折号) – E10247631234567891E0T32E4E7EB316(更正密钥 – 它不能有“T”)

 function hex2str($hex) { for($i=0;$i 

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) 

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