C# 十六进制到字符串的转换不匹配 PHP 十六进制到字符串

C# conversion Hex to String does not match PHP Hex to String

我正致力于将用 PHP 编写的加密库转换为 C#,但遇到了一个小问题。将 HEX 字符串转换为 PHP 中的字符串时,我得到的值与我的 C# 代码不同,它应该做完全相同的事情。

这是我使用的 php 代码:

public function hex2str($hex)
{
    $str = '';
    for($i=0; $i<strlen($hex); $i+=2)
    {
        $str.=chr(hexdec(substr($hex, $i, 2)));
    }
    return $str;
}

我的 C# 代码:

public static string Hex2Str(string hexString)
{
    char[] mychar = new char[hexString.Length / 2];
    for (var i = 0; i < mychar.Length; i++)
    {
        // Convert the number expressed in base-16 to an integer. 
        int value = Convert.ToInt32(hexString.Substring(i * 2, 2), 16);
        string stringValue = Char.ConvertFromUtf32(value);
        mychar[i] = (char)value;
    }

    return new String(mychar);
}

我使用的十六进制值是:

E0D644FCDEB4CCA04D51F617D59084D8

下面是 PHP 脚本和我的 C# 脚本之间的区别图片 return 值:

如果有人能帮助我发现我在 C# 代码中的错误,我将不胜感激!

区别在于使用的代码页不同。似乎 PHP 使用了 OEM 字符集(代码页 850),它仍然与默认命令行一起使用。

你可以试试这个:

public static string Hex2Str(string hexString)
{
    byte[] myBytes = new byte[hexString.Length / 2];
    for (var i = 0; i < myBytes.Length; i++)
    {
        // Convert the number expressed in base-16 to an integer. 
        int value = Convert.ToInt32(hexString.Substring(i * 2, 2), 16);

        myBytes[i] = (byte)value;

    }
    return Encoding.GetEncoding(850).GetString(myBytes);
}

请注意,您机器上实际使用的编码取决于本地设置。

您还可以更改代码页或使用其中一种标准编码:

return Encoding.Default.GetString(myBytes);

这个可能会给你第一次尝试的初步结果。

另请注意,可能使用 php 写入文件会给您带来不同于在命令行中打印到 stdio 的结果。

我认为您的 C# 算法 Hex2Str 看起来不错,但我可能会建议进行以下小改动以避免与代理对编码的任何可能不一致:

    public static string Hex2Str(string hexString)
    {
        var sb = new StringBuilder();

        var len = hexString.Length / 2;
        for (var i = 0; i < len; i++)
        {
            // Convert the number expressed in base-16 to an integer. 
            int value = Convert.ToInt32(hexString.Substring(i * 2, 2), 16);
            string stringValue = Char.ConvertFromUtf32(value);
            sb.Append(stringValue);
        }

        return sb.ToString();
    }

我怀疑这里真正的问题是来自 PHP 的字符串在通过控制台时由于编码不一致而被破坏。例如,如果 PHP 控制台具有 Latin 9 (ISO) 编码并且您的输入控制台具有 OEM United States 编码(它在我的计算机上),那么 'à' 将被转换为 'α'。

相反,我建议采取额外的步骤,在将 PHP 字符串写入控制台之前使用 base64_encode 在 Base64 中对其进行编码。这将保证通过控制台传递的是纯 ASCII 表示形式。然后解码如下:

    public static string FromPHPBase64String(string phpString)
    {
        var bytes = Convert.FromBase64String(phpString);
        var sb = new StringBuilder();
        foreach (var b in bytes)
        {
            string stringValue = char.ConvertFromUtf32(b);
            sb.Append(stringValue);
        }
        return sb.ToString();
    }

我相信现在一切都应该匹配了。