将C#散列函数转换为PHP

324*_*423 7 php c# hmac

我在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;
} 
Run Code Online (Sandbox Code Playgroud)

PHP中的一次(错误)尝试是这样的:

function encode($data,$key)
{
    return base64_encode( hash_hmac('sha256', $data, $key ) );
}
Run Code Online (Sandbox Code Playgroud)

答案

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 ) );
}
Run Code Online (Sandbox Code Playgroud)

请不要使用hash_hmac的第四个参数 - 现在将原始输出设置为true作为二进制数据

Dam*_*S8N 6

我怀疑你的.net代码的第一行是罪魁祸首.PHP 没有编码字符串本身,所以当谈到时间哈希它要么被散列内部PHP字符串格式的字节(不太可能,可别人证实?),或者更可能被转换成别的东西第一.在这种情况下,可能是unicode,它绝对不是字符串在ASCII中作为.net请求的字节.

我的建议是确保PHP也使用带有iconv的 ASCII 来实现互操作性.

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 ) ) );
}
Run Code Online (Sandbox Code Playgroud)

我不能确定上面的代码会输出所需的哈希值,但是,因为我没有.net方便测试初始代码.但这可能会指向正确的方向.

如果这不起作用,里面的值iconv_get_encoding(可能是罪魁祸首,尝试"output_encoding"或者"input_encoding"也是如此.您也可能需要将这些相同的值设置为ASCII iconv_set_encoding(.

祝好运!


更新!这是最终奏效的:

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 ) );
}
Run Code Online (Sandbox Code Playgroud)