【问题标题】:C# conversion Hex to String does not match PHP Hex to StringC# 将十六进制转换为字符串与 PHP 十六进制到字符串不匹配
【发布时间】:2015-04-24 00:05:32
【问题描述】:

我正在将一个用 PHP 编写的加密库转换为 C#,并且有一个小问题。在 PHP 中将 HEX 字符串转换为字符串时,我得到一个不同的值,然后我的 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#脚本返回值的区别图片:

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

【问题讨论】:

  • 您链接的重复帖子都是关于 php 代码以及在十六进制和字符串之间来回转换...我的问题与 C# 严格相关,并试图以一种方式模仿我的 PHP 代码转换到一个字符串。
  • 我不好,我累了,对不起
  • 如何将 PHP 字符串导入 c# 进行打印? 'α' 的十六进制值是 3B1,所以它不可能用两个字节的值来表示。 E0 的值为 224,这恰好是 'α' 的“OEM United States”编码——也许你错误地解码了 PHP 字符串?
  • 我基本上在一个新进程中运行 php 并像这样捕获输出:pastebin.com/d1qxinvj

标签: c# php string hex


【解决方案1】:

我认为您的 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 中编码您的 PHP 字符串。当它通过控制台传递时,这将保证纯 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();
    }

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

【讨论】:

  • 通过转换为Base64字符串,正常保留了来自php(ASCII)的默认编码,现在我的字符串匹配......很好的建议
【解决方案2】:

区别在于使用的代码页不同。好像 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。

【讨论】:

  • 非常感谢您的回答!虽然它不完全是:(。这是使用 Hex2Str 的输出:puu.sh/g8apE/ec07b685a5.png
  • 我使用了代码 437 而不是您的 850,它成功了!非常感谢!
猜你喜欢
  • 2020-11-07
  • 2018-01-31
  • 1970-01-01
  • 2018-01-22
  • 2017-08-12
  • 2012-01-24
  • 2019-07-27
  • 1970-01-01
相关资源
最近更新 更多