Возможен ли перевод 16 байт в одно UInt64?

Язык C#: программирование на C#, портирование кода C# на VB и VB на C#.

Модератор: Ramzes

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Возможен ли перевод 16 байт в одно UInt64?

Сообщение Admiralisimys » 21.01.2013 (Пн) 23:28

Здравствуйте.

Помогите разобраться в ниже следующем коде.
Код: Выделить всё
using System;
using System.Linq;

class Program
{
    static public String StringToHexString(String S)
    {
        return BitConverter.ToString(System.Text.Encoding.Default.GetBytes(S).ToArray()).Replace("-", "");
    }

    static public String ToReverseHexString(UInt64 S)
    {
        return BitConverter.ToString(BitConverter.GetBytes(S).ToArray()).Replace("-", "");
    }

    static void Main(String[] args)
    {
        String message = "Hello! Lets do something here.";
        message = StringToHexString(message);        //Byte[] bMessage = { (Byte)'H', (Byte)'e', (Byte)'l', (Byte)'l', (Byte)'o'//... };
        //...
        UInt64 uiM64 = Convert.ToUInt64(message.Substring(0, 16), 16);//"Hello! Lets do "
        String temp = ToReverseHexString(uiM64);
        uiM64 = Convert.ToUInt64(temp, 16);
    }
}

Меня интересуют последние три строчки метода Main.
Так как вторая (метод StringToHexString) нивелируется использовав для данных целей сразу массив Byte.
Использование автором String, как я понимаю, оправданно для иллюстрации процесса, - показать что происходит с данными.

А вот первый вызов ToUInt64 делает то что я вынес в заголовок?
Мы берём строку из 16 символов (в примере это "Hello! Lets do ") и представляем её в виде целого значения UInt64?
Но ведь если вместо символа использовать один байта, то в одной переменной UInt64, с точки зрения Сишной унарной операции sizeof (проверялось на аналоге UInt64 - unsigned long long), там всего может находится 8 байт.

Понимание ситуация с другой стороны осложняется ещё тем что 16 в 16 степени вмещается в UInt64.

Оставшиеся две будут ясны если с этой разберусь. Вторая возвращает число UInt64 в виде 16ричной системе в 16 символьной переменной String.

P.S.
Вариант перевода в лоб на С++ проблем не возникает.
А вот человеческий перевод требует замены String на Byte[] ещё в CSharp варианте.

P.S.S.
В общем-то элементарные вещи спрашиваю, но боюсь без свежего взгляда со стороны не разберусь.

Предполагаю что на ответ на вопрос из заголовка должно быть (рассмотрим Си вариант) что-то на подобие
Код: Выделить всё
unsigned long long SixteensBytesToUInt64(const unsigned char bVal[16])
{
   unsigned long long ulVal = 0L;
   //for(unsigned char i = 0; i < 16; i++)
   ulVal |= bVal[0] << 24;
   ulVal |= bVal[1] << 16;
   ulVal |= bVal[2] << 8;
   ulVal |= bVal[3];
   return ulVal;
}

Это для варианта char [4] -> UInt64.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Возможен ли перевод 16 байт в одно UInt64?

Сообщение FireFenix » 22.01.2013 (Вт) 6:07

Какая-то каша из слов и зачем-то притянутый cpp.

Всё очень просто
Код: Выделить всё
return BitConverter.ToString(System.Text.Encoding.Default.GetBytes(S).ToArray()).Replace("-", "");

System.Text.Encoding.Default.GetBytes(S).ToArray(); //Получаем массив байт переданной строки
BitConverter.ToString(System.Text.Encoding.Default.GetBytes(S).ToArray()); //получаем HEX представление массивая байтов в строке FF-FF-FF и т.д.
BitConverter.ToString(System.Text.Encoding.Default.GetBytes(S).ToArray()).Replace("-", ""); //заменяем черту, чтобы в строке HEX шли слитно FF-FF-FF -> FFFFFF


Код: Выделить всё
return BitConverter.ToString(BitConverter.GetBytes(S).ToArray()).Replace("-", "");

BitConverter.GetBytes(S).ToArray(); //Получаем массив байтов переданного числа
BitConverter.ToString(BitConverter.GetBytes(S).ToArray()); //Представляем массив байтов в виде HEX строки FF-FF-FF
BitConverter.ToString(BitConverter.GetBytes(S).ToArray()).Replace("-", ""); //заменяем черту, чтобы в строке HEX шли слитно FF-FF-FF -> FFFFFF


Код: Выделить всё
        String message = "Hello! Lets do something here."; //загружаем любую строку
        message = StringToHexString(message);  //преобразуем char -> byte -> string (в формате HEX, т.е. 16ти разрядная система)
        //...
        UInt64 uiM64 = Convert.ToUInt64(message.Substring(0, 16), 16); //Берём первые 16 символов строки в HEX формате и приводим в эквивалентное представление UInt64. (берём 16, потому что максимум в int64 влезает 16 чисел в 16 системе, т.е.  16^16 = 2^(4*16) = 2^64)
        String temp = ToReverseHexString(uiM64); //Число представляем в виде HEX-строки
        uiM64 = Convert.ToUInt64(temp, 16); //Конвертируем HEX-строку в число


msdn Convert.ToUInt64 -> http://msdn.microsoft.com/en-us/library/3zk09b81.aspx (первый строковой параметр - число, второй чтсловой - порядок системы (двоичная, десятеричная и т.д.) представленный в строке

В итоге получаем
"Hello! Lets do something here." -> "48656C6C6F21204C65747320646F20736F6D657468696E6720686572652E" //Строка -> массив byte -> HEX-строка
"48656C6C6F21204C65747320646F20736F6D657468696E6720686572652E" -> "48656C6C6F21204C" //обрезаем первые 16
"48656C6C6F21204C" -> 3762817090839590467//HEX-строка в UInt64
3762817090839590467 -> "4C20216F6C6C6548" //Uint64 -> HEX-строка
"4C20216F6C6C6548" -> 5485421108581393736 //HEX-строка в UInt64


Почему мы с ToReverseHexString не получили то же число? Потому что little-endian (т.е. обратный порядок байтов)

Если смотреть в корень, то ответ на вопрос в шапке:
Возможен ли перевод 16 байт в одно UInt64?

* 16 байт в Uint64 не возможно, т.к. 16 байт = (2^8)^16 = 2^(128) больше чем 2^(64) Логично же!!!
* Что же происходит в этом примере? из заданной строки забираются первые 16 HEX-символов представления байтового массива 16^16 = (2^4)^16 = 2^64 равно Uint64 = 2^64, что в итоге позволяет получить UInt64

Ну вроде всё написал, не должно быть больше вопросов...

P.S. Научитесь уже использовать отладчик, он вам всё подробно покажет и расскажет!!!
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 22.01.2013 (Вт) 7:49

Вообще не понимаю, зачем всё это нужно...
А разве кодировка Default - это не Unicode?

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: Возможен ли перевод 16 байт в одно UInt64?

Сообщение Admiralisimys » 23.01.2013 (Ср) 15:44

Qwertiy вот проект из которого взят и адаптированный для форумного вопроса код.
А вот описание самого проекта (только там этот момент не описывается).

Разумеется String в .NET это Unicode, но в данном частном случаи это не так важно.

FireFenix уже не знал куда двигаться, по этому, даже сформировать вопрос толком не смог.

Тем не менее всё оказалось действительно просто, я упустил один важный момент: байт меньше 17 (0x10) в строковом представлении будет записываться не 0x0 - 0xF, а 0х00 - 0х0F (или в качестве строки как 00 - 0F, из которой в коде выше программа возьмёт по очереди по одному символу).

Да, теперь код вполне ясен, вопросов больше не имею. Спасибо!

P.S.
Отладчик как раз помог всё это дело перенести на С++. Как я его для себя назвал методом калибровки: добиться на С++ точно такого результата (ответа функций) как на С#, при равных входных параметрах. По сути это можно так же назвать меж языковым юнит тестом.
Только после перевода все равно было не ясно, как можно перейти к без "строчной" обработки.

P.S.S
Вот что получилось
Код: Выделить всё
    //...
    static public UInt64 EightBytesToUInt64(Byte[] bVal)
    {
        UInt64 ulVal = 0L;
        Byte j = 0;
        for (Byte i = 0; i < 8; i++)
        {
            ulVal += (UInt64)((bVal[i] & 0xF0) >> 4) * (UInt64)Math.Pow(16.0F, 15 - (j++));//Берём первые 4 бита от байта
            ulVal += (UInt64)(bVal[i] & 0x0F) * (UInt64)Math.Pow(16.0F, 15 - (j++)); //Теперь оставшиеся 4
        }
        return ulVal;
    }//И всё это по правилу перевода десятичного числа в шестнадцатеричное

    static void Main(String[] args)
    {
        String message = "Hello! Lets do something here.";
        Byte[] bMessage = { (Byte)'H', (Byte)'e', (Byte)'l', (Byte)'l', (Byte)'o', (Byte)'!',
                          (Byte)' ', (Byte)'L', (Byte)'e', (Byte)'t', (Byte)'s', (Byte)' ', (Byte)'d', (Byte)'o', (Byte)' '};

        message = StringToHexString(message);
        UInt64 uiM64 = Convert.ToUInt64(message.Substring(0, 16), 16);//"Hello! Lets do "
        UInt64 uiM64b = EightBytesToUInt64(bMessage);//uiM64b будет равен uiM64, значит всё сделано правильно
    }


Ну, а что бы полностью заменить указанные три строчки кода на без "строчную" обработку
Код: Выделить всё
    //...
    static public UInt64 ReverseEightBytesAndToUInt64(Byte[] bVal)
    {
        UInt64 ulVal = 0L;
        Byte j = 0;
        for (Byte i = 8; i > 0; i--)
        {
            ulVal += (UInt64)((bVal[i - 1] & 0xF0) >> 4) * (UInt64)Math.Pow(16.0F, 15 - (j++));
            ulVal += (UInt64)(bVal[i - 1] & 0x0F) * (UInt64)Math.Pow(16.0F, 15 - (j++));
        }
        return ulVal;
    }

    static void Main(String[] args)
    {
        String messageS = "00" + "01" + "02" + "03" +
                         "04" + "05" + "06" + "07";
        Byte[] messageB = {00, 01, 02, 03, 04, 05, 06, 07};

        UInt64 uiM64s = Convert.ToUInt64(messageS, 16);
        String temp = ToReverseHexString(uiM64s);
        uiM64s = Convert.ToUInt64(temp, 16);

        UInt64 uiM64b = ReverseEightBytesAndToUInt64(messageB);//и снова всё правильно, так как uiM64b равен uiM64s
    }

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Возможен ли перевод 16 байт в одно UInt64?

Сообщение FireFenix » 23.01.2013 (Ср) 19:21

Qwertiy писал(а):Вообще не понимаю, зачем всё это нужно...
А разве кодировка Default - это не Unicode?

msdn писал(а):The system ANSI code page defined by Default covers the ASCII set of characters, but the encoding is different from the encoding for ASCII. Because all Default encodings lose data, your application might use UTF8 instead. UTF-8 is often identical in the U+00 to U+7F range, but can encode other characters without loss.


Admiralisimys писал(а):вот проект из которого взят и адаптированный для форумного вопроса код.
А вот описание самого проекта (только там этот момент не описывается).

Чем стандартное хеширование не устроило?
Или просто для развития?
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: Возможен ли перевод 16 байт в одно UInt64?

Сообщение Admiralisimys » 23.01.2013 (Ср) 20:26

FireFenix для развития. Как оказалось по части "умения читать чужой код" это было полезным.
Тут ещё есть много места для манёвров, например добавить методы Update и Final, для хеширования больших файлов.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.01.2013 (Ср) 21:46

Admiralisimys писал(а):Qwertiy вот проект из которого взят и адаптированный для форумного вопроса код.
А вот описание самого проекта (только там этот момент не описывается).

Код мне не нравится.
И вообще, либо я не понимаю, что он делает, либо он делает это неправильно. Хэш, посчитанный так
Код: Выделить всё
string.Join("", (new System.Security.Cryptography.SHA256CryptoServiceProvider()).ComputeHash(Encoding.Default.GetBytes(textBox1.Text)).Select(b => (b < 16 ? "0" : "") + System.Convert.ToString((long)b, 16)))
не совпадает с тем, что выводится для SHA-256.

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: Возможен ли перевод 16 байт в одно UInt64?

Сообщение Admiralisimys » 24.01.2013 (Чт) 1:56

Qwertiy лично для меня он оказался более ясным чем рефересный пример с сайта разработчиков.
Код высчитывает хеши разной длины согласно SHA-3.

А встроенный в .NET SHA256CryptoServiceProvider это для SHA-2.


Вернуться в C#

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

    TopList  
cron