Преобразование шестнадцатеричного кода в строку C # не совпадает с шестнадцатеричным в строке PHP

Я работаю над преобразованием библиотеки шифрования, написанной на 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);
}

Значение Hex, которое я использую:

E0D644FCDEB4CCA04D51F617D59084D8

И вот картина различия между PHP-скриптом и возвращаемым значением моих C-скриптов:

введите описание изображения здесь

Если кто-нибудь может помочь мне обнаружить мою ошибку в коде C #, я был бы очень признателен за вашу помощь!

0

Решение

Я думаю, что ваш алгоритм 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, используя base64_encode перед записью в консоль. Это гарантирует чистое представление 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(sb);
}
return sb.ToString();
}

Я считаю, что теперь все должно совпадать.

1

Другие решения

Разница заключается в разных кодовых страницах. Похоже, что PHP использовал OEM charset (кодовая страница 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 в командной строке.

1

По вопросам рекламы [email protected]