C#相当于PHP中的hash_hmac

C#相当于PHP中的hash_hmac,c#,hmac,sha512,C#,Hmac,Sha512,使用.NET和C#我需要使用HMAC SHA512向PHP服务器提供完整性字符串。 在C#中使用: 但它与PHP hash_hmac()不匹配 PHP代码: $hmac = strtoupper(hash_hmac($pbx_hash, $msg, $binKey)); 我试图用C#(utf8、ASCII、Unicode)更改编码,但没有成功 我尝试了许多在网上找到的解决方案,但都没有给出相同的字符串:( 我无法更改PHP代码,也看不出C中有什么错误# 编辑这是ByteToString(从注释

使用.NET和C#我需要使用HMAC SHA512向PHP服务器提供完整性字符串。 在C#中使用:

但它与PHP hash_hmac()不匹配 PHP代码:

$hmac = strtoupper(hash_hmac($pbx_hash, $msg, $binKey));
我试图用C#(utf8、ASCII、Unicode)更改编码,但没有成功

我尝试了许多在网上找到的解决方案,但都没有给出相同的字符串:(

我无法更改PHP代码,也看不出C中有什么错误#

编辑这是
ByteToString
(从注释中复制):

静态字符串ByteToString(字节[]buff)
{
字符串sbinary=“”;
for(int i=0;i

经过多次测试后,in发现如果PHP hash_hmac key是一个字符串而不是一个字节数组,我会得到相同的结果。似乎问题在于PHP转换函数$binKey=pack(“H*”,$keyTest);

问题一定是密钥/消息数据的实际表示

请参阅以下测试:

PHP
!/usr/bin/php
输出(实时通过):

C#
使用系统;
使用系统文本;
使用System.Security.Cryptography;
公共课程
{
private const string key=“key”;
private const string message=“message”;
私有静态只读编码编码=Encoding.UTF8;
静态void Main(字符串[]参数)
{
var keyByte=encoding.GetBytes(键);
使用(var hmacsha256=新的hmacsha256(keyByte))
{
hmacsha256.ComputeHash(encoding.GetBytes(message));
WriteLine(“结果:{0}”,ByteToString(hmacsha256.Hash));
}
}
静态字符串ByteToString(字节[]buff)
{
字符串sbinary=“”;
for(int i=0;i
输出(实时通过):


因此,请检查PHP输入数据的字符集/编码。还要检查实际的算法(在
$pbx_hash
中)。

如上所述,问题在于用于将密钥转换为字节数组的PHP Pack(H*函数)。 C#Getbytes不会给出相同的结果(utf8、asci、unicode…)。 这里找到的解决方案:对我来说没问题。 现在,来自C#的HMAC与PHP匹配

public static byte[] PackH(string hex)
{
       if ((hex.Length % 2) == 1) hex += '0';
       byte[] bytes = new byte[hex.Length / 2];
       for (int i = 0; i < hex.Length; i += 2)
       {
             bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
       }
 return bytes;
}
公共静态字节[]PackH(字符串十六进制)
{
如果((十六进制长度%2)==1)十六进制+='0';
字节[]字节=新字节[hex.Length/2];
对于(int i=0;i<十六进制长度;i+=2)
{
字节[i/2]=转换为字节(十六进制子字符串(i,2),16);
}
返回字节;
}

Manu感谢所有人的帮助。

请查看下面的“ByteToString”?谢谢,这里是ByteToString的代码:静态字符串ByteToString(byte[]buff){string sbinary=“”;for(int i=0;iBitConverter.ToString
System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary
已经有了内置类。谢谢,BitConverter比较短,但它并没有解决PHP和C之间的差异问题:(@Philippe我已经根据你的
ByteToString
函数重新做了分析。请看我从scratchHi改写的答案,谢谢你的回复,经过多次测试后,问题来自PHP Pack(H*函数!当提供的键是字符串时,它是可以的,但使用Pack(H*提供键会给出与C#GetBytes不同的结果。)(可能是因为内部PHP编码)。在这里找到了解决方案:我遇到了完全相同的问题。我尝试过使用您的方法,但仍然存在问题。我在这里问了一个类似的问题。您能告诉我您在解决方案中实际在何处使用此PackH函数的信息吗?谢谢!我使用的是c#来自PHP的hash_hmac(),并能够使用上述答案获得所需的结果。许多API需要base64版本的哈希,只需将现有的“return…”行替换为return Convert.ToBase64String(哈希),即可获得此结果;请解释为什么需要.Replace(“-”,string.Empty)?
    private static string HashHmac(string message, string secret)
    {
        Encoding encoding = Encoding.UTF8;
        using (HMACSHA512 hmac = new HMACSHA512(encoding.GetBytes(secret)))
        {
            var msg = encoding.GetBytes(message);
            var hash = hmac.ComputeHash(msg);
            return BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
        }
    }
6E9EF29B75FFFC5B7ABAE527D58FDADB2FE42E7219011976917343065F58ED4A
Result: 6E9EF29B75FFFC5B7ABAE527D58FDADB2FE42E7219011976917343065F58ED4A
public static byte[] PackH(string hex)
{
       if ((hex.Length % 2) == 1) hex += '0';
       byte[] bytes = new byte[hex.Length / 2];
       for (int i = 0; i < hex.Length; i += 2)
       {
             bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
       }
 return bytes;
}
    private static string HashHmac(string message, string secret)
    {
        Encoding encoding = Encoding.UTF8;
        using (HMACSHA512 hmac = new HMACSHA512(encoding.GetBytes(secret)))
        {
            var msg = encoding.GetBytes(message);
            var hash = hmac.ComputeHash(msg);
            return BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
        }
    }