简体   繁体   中英

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

Im working on converting an encryption library written in PHP over to C#, and have a small problem. When converting a HEX string to a string in PHP, and im getting a different value then my C# code which is supposed to be doing the exact same thing.

Here is the php code im using:

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

And my C# code:

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);
}

The Hex value im using is:

E0D644FCDEB4CCA04D51F617D59084D8

And here is a picture of the difference between the PHP script and my C# scripts return value:

在此处输入图片说明

If anyone can help me spot my mistake in the C# code, i would greatly appreciate your help!

The difference is in the different code pages used. It seems that PHP used OEM charset (codepage 850), which is still used with the default command line.

You can try this:

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);
}

Be aware that the real used encoding on your machine is dependent on the local settings.

You are also able to change the codepage or use one of the standard encodings:

return Encoding.Default.GetString(myBytes);

This one will probably give you the initial result of your first try.

Also note that presumably using php to write to a file give you another result than printing to stdio in the commandline.

I think your c# algorithm Hex2Str looks good, though I might suggest the following small change to avoid any possible inconsistencies with surrogate pair encoding:

    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();
    }

The real problem here, I suspect, is that the string from PHP is being mangled when passed through the console due to inconsistent encodings. For instance, if the PHP console has Latin 9 (ISO) encoding and your input console has OEM United States encoding (which it is on my computer) then 'à' will be transformed to 'α'.

Instead, I recommend taking the additional step of encoding your PHP string in Base64 using base64_encode before writing it to the console. This will guarantee a pure ASCII representation as it is passed through the console. Then decode as follows:

    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();
    }

I believe everything should now match.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM