如何在PHP中复制这种C#哈希?(到ByteArray(),ComputeHash())

本文关键字:ComputeHash ByteArray 哈希 PHP 复制 | 更新日期: 2023-09-27 18:19:26

我正在尝试在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#?)这样我就可以看到每一行的输出了吗?


更新-已添加赏金

在这方面仍然有问题,我已经设法在Visual Studio中测试了C#代码,但在PHP中生成相同的哈希时遇到了问题。

我想

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

如果你还有其他问题,请问。

如何在PHP中复制这种C#哈希?(到ByteArray(),ComputeHash())

问题是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无效,所以我不得不稍微更改它。

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

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

string 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)

这应该做到…享受:)

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

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

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