将C#哈希函数转换为PHP

7
我在C#中有以下的函数,是一个哈希函数,我需要将其转换为PHP。我尝试了一些PHP代码,但结果不同(我并不擅长.NET)。
private static string GetSignature(string args, string privatekey)
{
    var encoding = new System.Text.ASCIIEncoding();
    byte[] key = encoding.GetBytes(privatekey);
    var myhmacsha256 = new HMACSHA256(key);
    byte[] hashValue = myhmacsha256.ComputeHash(encoding.GetBytes(args));
    string hmac64 = Convert.ToBase64String(hashValue);
    myhmacsha256.Clear();
    return hmac64;
} 

在 PHP 中,一个错误的尝试是这样的:

function encode($data,$key)
{
    return base64_encode( hash_hmac('sha256', $data, $key ) );
}

答案

DampeS8N下面提供的略有变化的方法对我起了很大作用。

function encode($data,$key)
{
    iconv_set_encoding("input_encoding", "ASCII");
    iconv_set_encoding("internal_encoding", "ASCII");
    iconv_set_encoding("output_encoding", "ASCII");

    return base64_encode( hash_hmac('sha256', $data, $key, true ) );
}

请注意 hash_hmac 的第四个参数 - 现在设置为 true 以输出原始的二进制数据。

如果DampeS8Ns指出了正确的方向,你应该接受他的答案。 - jgauffin
1个回答

6
我怀疑你的.net代码的第一行是罪魁祸首。PHP 没有为该字符串编码,所以当需要对其进行哈希处理时,它要么对内部PHP字符串格式的字节进行哈希处理(不太可能,可以有其他人确认吗?),要么更有可能先转换为其他东西。在这种情况下,可能是Unicode,而这些字节与.net请求的ASCII字符串不同。
我的建议是确保PHP也使用ASCII,使用iconv,以实现互操作性。
function encode($data,$key)
{
    return base64_encode( hash_hmac('sha256', iconv( iconv_get_encoding( "internal_encoding"), "ASCII", $data ), iconv( iconv_get_encoding( "internal_encoding"), "ASCII", $key ) ) );
}

我无法确定上述代码是否会输出所需的哈希值,因为我没有 .net 工具来测试初始代码。但这可能会指引您朝着正确的方向前进。
如果这不起作用,iconv_get_encoding() 内部的值可能是罪魁祸首,也可以尝试将其设置为 "output_encoding""input_encoding"。同样可能需要使用 iconv_set_encoding() 将这些值设置为 ASCII。
祝好运!

更新!最终有效的方法如下:

function encode($data,$key)
{
    iconv_set_encoding("input_encoding", "ASCII");
    iconv_set_encoding("internal_encoding", "ASCII");
    iconv_set_encoding("output_encoding", "ASCII");

    return base64_encode( hash_hmac('sha256', $data, $key, true ) );
}

谢谢您。虽然看起来好像不起作用,但这完全是有道理的。我也遇到了同样的问题,因为我没有 .net 环境进行测试。我认为我仍然需要使用 encoding.GetBytes(privatekey)。 - 32423hjh32423
1
这只需要获取密钥的ASCII原始字节。由于PHP中的动态类型,要想控制它可能会非常困难。我确信这是通过使用iconv_set_encoding()设置正确的参数组合来实现的,以确保hash_hmac()不会撤销你在iconv()上所做的所有努力。 - DampeS8N
抱歉,我没有意识到那是我应该做的事情! - 32423hjh32423

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接