Помогите разобраться что я упустил из виду SHA256 и Gzip

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
Отправлял содержимое файла, в котором ничего нет только строка со значением 1
В фиддлере отловил такие данные (скриншот):
67370

Как видим - данных всего 21 байт.

Для удобства, скопировал себе их в массив:
C#:
byte[] arrOutput1 = {
    0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 
   0x00, 0x02, 0x0A, 0x33, 0x04, 0x00, 0xB7,
   0xEF, 0xDC, 0x83, 0x01, 0x00, 0x00, 0x00
};
В другом запросе нашел хеш:
697d5abc7fded2dbb8ffc4f84c4441274ab23c9e718278a9ebb4b741ba14e69c
Если пропустить байты через Decompress - получаю число строку со значением 1 - как и должно быть.
В результате, стало понятно что хеш - это SHA256.
И уже с этого сделано вывод, что считывается файл, сжимается и с содержимого получается хеш.

Отлично!

Но, проблема в том, что когда я беру, полученную разжатую строку обратно сжимаю, и пытаюсь получить хеш - у меня получается другое значение.
Видимо я что-то упускаю, но никак не могу понять, почему при сжатии строки со значением 1 я никак не могу получить такой же SHA256 хеш.
Что я делаю не так?

Пример реализации:
string h = "697d5abc7fded2dbb8ffc4f84c4441274ab23c9e718278a9ebb4b741ba14e69c"; // искомое значение

// Беру байты
byte[] bytes_in = { // Так должно быть
    0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x02, 0x0A, 0x33, 0x04, 0x00, 0xB7, 
    0xEF, 0xDC, 0x83, 0x01, 0x00, 0x00, 0x00
};
project.SendInfoToLog(bytes_in.Length.ToString() + " 21 байт");

// Разжимаю
byte[] result_line = new byte[bytes_in.Length];
using (var ss = new MemoryStream(bytes_in)) {
    using (var dss = new System.IO.Compression.GZipStream(ss, System.IO.Compression.CompressionMode.Decompress)) {
        dss.Read(result_line, 0, result_line.Length);                   
    }
}

// Смотрю строку в логе
string line_out = System.Text.Encoding.UTF8.GetString(result_line);
project.SendInfoToLog("Сжатая строка: "+line_out);    
project.Variables["Variable1"].Value = line_out;


// Перевожу полученную строку в байты
byte[] bytes_out = Encoding.UTF8.GetBytes(line_out);
MemoryStream output = new MemoryStream();
using (var dstream = new System.IO.Compression.GZipStream(output, System.IO.Compression.CompressionMode.Compress)){
    dstream.Write(bytes_out, 0, bytes_out.Length);
}
bytes_out = output.ToArray(); // здесь байты после сжатия
project.SendInfoToLog(bytes_out.Length.ToString() + " почему-то 23 байта");
// Извлекаю Хеши с оригинала и созданного значения
string hash_in;
string hash_out;
using (var sha256 = System.Security.Cryptography.SHA256.Create()){
    hash_in = BitConverter.ToString(sha256.ComputeHash(bytes_in)).ToLower().Replace("-", ""); // Оригинал
    hash_out = BitConverter.ToString(sha256.ComputeHash(bytes_out)).ToLower().Replace("-", ""); // После преобразования
}

if(hash_in == h ) project.SendInfoToLog("arrOutput1 + hash1 Совпадает - на него ровняемся: "+hash_in);
else project.SendWarningToLog("хеш плохой:" +hash_in);
if(hash_out == h ) project.SendInfoToLog("хеш хороший - это и ищу:" + hash_out);
else project.SendWarningToLog("хеш плохой: "+hash_out);
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 691
Баллы
113
может метод сжатия разный ? уровень сжатия одинаковый ?
https://habr.com/ru/post/135696/ от параметров сжатия меняется конечный результат. поэтому не зная параметры сжатия, будет сложно получить тот же результат.
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
может метод сжатия разный ? уровень сжатия одинаковый ?
Разжимал: System.IO.Compression.CompressionMode.Decompress
Сжимал: System.IO.Compression.CompressionMode.Compress
Сжимал: System.IO.Compression.CompressionLevel.Optimal
Сжимал: System.IO.Compression.CompressionLevel.Fastest
Сжимал: System.IO.Compression.CompressionLevel.NoCompression
Пробовал ещё разные уровни сжатия - но это не дало результата - хеши отличаются (хотя по идее должны совпадать).
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 691
Баллы
113
Разжимал: System.IO.Compression.CompressionMode.Decompress
Сжимал: System.IO.Compression.CompressionMode.Compress

Пробовал ещё разные уровни сжатия - но это не дало результата - хеши отличаются (хотя по идее должны совпадать).
нет не должны. одно дело распаковать, другое дело так же сжать. там же куча параметров при сжатии. вы же не знаете с какими параметрами был получен тот результат для того хэша.
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
нет не должны. одно дело распаковать, другое дело так же сжать. там же куча параметров при сжатии. вы же не знаете с какими параметрами был получен тот результат для того хэша.
Да, я действительно не знаю с какими параметрами была сжата 1-ка.
Но, разжимал определенным методом - и 1-ку получил.
Нужно теперь её как-то сжать чтобы получить такой-же хеш.
И уже к сожалению варианты которые знал - перебрал.
Может Вы каких-то парочку вариантов подбросите?
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 691
Баллы
113
Да, я действительно не знаю с какими параметрами была сжата 1-ка.
Но, разжимал определенным методом - и 1-ку получил.
Нужно теперь её как-то сжать чтобы получить такой-же хеш.
И уже к сожалению варианты которые знал - перебрал.
Может Вы каких-то парочку вариантов подбросите?
эм... с криптографией вообще не знаком :-) а уж попасть в нужный хэш.... по мне это вообще будет чудо :-)
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
эм... с криптографией вообще не знаком :-) а уж попасть в нужный хэш.... по мне это вообще будет чудо :-)
Я уже и здесь читал: https://tools.ietf.org/html/rfc1952
И тут читал: https://habr.com/ru/post/133176/
Но, добиться того, чтобы получить нужный набор байт не получается....
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 691
Баллы
113
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
ну тут код посложнее будет чем у вас в примере :-)
заметил что по флаг по операционной системе не такой вроде... ну тут курить тему конечно надо серьезно....
67379


Вот, выглядит, что именно эти штуки отличаются.
Но, установить 04 вместо 02 устанавливая разными уровнями сжатия не получается.
Также установить OS не получается (хотя, генерировался токен браузером на моей машине - виндовс что там, что здесь должен быть)
67380
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 691
Баллы
113
тыкс... может их уже принудительно после сжатия заменить на нужные. это же заголовок.... не сами же данные :-)
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
тыкс... может их уже принудительно после сжатия заменить на нужные. это же заголовок.... не сами же данные :-)
C#:
//bytes_out[8] = 0x02;
//bytes_out[9] = 0x0A;
Пытался заменить примерно так.
Не принимает тогда файл (хотя хеш и получается получить правильным образом).

Взят текст побольше, чтобы сравнить отличия.
Вижу, что не только эти байты в шапке отличаются - отличия есть и в конце.
Метод сжатия какой-то не такой использую как надо (хотя, разжимаются данные вроде корректно - строки получаю как доктор прописал).

67381
 
Последнее редактирование:

nicanil

Client
Регистрация
06.03.2016
Сообщения
2 242
Благодарностей
1 804
Баллы
113
Что я делаю не так?
Сайт показывает, что 697d5abc7fded2dbb8ffc4f84c4441274ab23c9e718278a9ebb4b741ba14e69c - это SHA2-256.

Загуглил c# sha2_256, попал сюда (хоть там и обсуждают другую проблему, ничего нам не мешает взять оттуда код).

И вот такой код даёт необходимый результат:
C#:
string original_hash = "697d5abc7fded2dbb8ffc4f84c4441274ab23c9e718278a9ebb4b741ba14e69c"; // искомое значение

// Беру байты
byte[] bytes_in = { // Так должно быть
    0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x02, 0x0A, 0x33, 0x04, 0x00, 0xB7,
    0xEF, 0xDC, 0x83, 0x01, 0x00, 0x00, 0x00
};

var sha2 = new System.Security.Cryptography.SHA256Managed();
byte[] hash= sha2.ComputeHash(bytes_in);
string  computed_hash = BitConverter.ToString(hash).ToLower().Replace("-", "");

if (computed_hash == original_hash)
{
    project.SendInfoToLog("Хэши равны!");
}
else
{
    project.SendErrorToLog("Хэши НЕ равны!");
}
 
Последнее редактирование:

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
Сайт показывает, что 697d5abc7fded2dbb8ffc4f84c4441274ab23c9e718278a9ebb4b741ba14e69c - это SHA2-256.

Загуглил c# sha2_256, попал сюда (хоть там и обсуждают другую проблему, ничего нам не мешает взять оттуда код).

И вот такой код даёт необходимый результат:
C#:
string original_hash = "697d5abc7fded2dbb8ffc4f84c4441274ab23c9e718278a9ebb4b741ba14e69c"; // искомое значение

// Беру байты
byte[] bytes_in = { // Так должно быть
    0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x02, 0x0A, 0x33, 0x04, 0x00, 0xB7,
    0xEF, 0xDC, 0x83, 0x01, 0x00, 0x00, 0x00
};

var sha2 = new System.Security.Cryptography.SHA256Managed();
byte[] hash= sha2.ComputeHash(bytes_in);
string  computed_hash = BitConverter.ToString(hash).ToLower().Replace("-", "");

if (computed_hash == original_hash)
{
    project.SendInfoToLog("Хэши равны!");
}
else
{
    project.SendErrorToLog("Хэши НЕ равны!");
}
Этот код, как и мой получает SHA256 - валидный у Вас, валидный у меня - с этим порядок.
Проблема заключается в том, что у меня нет изначально массива байт - у меня есть строка (в данном случае со значением 1).
Эта строка должна быть сжата алгоритмом gzip - что должно выдать в результате массив байт.
Так вот как я не шаманю - одинаковый набор байт после сжатия мне получить не выходит.
А из-за этого в результате хеш получается разный.

Начальные байты я предоставил потому, чтобы провести преобразования (разжать, преобразовать их в строку - убедиться что там значение 1). А уже после этого попытаться преобразовать эту строку обратно в такой же массив байт, и потом получить такой же хеш. В результате - именно это не получается :(
 
  • Спасибо
Реакции: nicanil

Geograph

Client
Регистрация
16.02.2014
Сообщения
209
Благодарностей
113
Баллы
43
Если файл отправляется сжатым, то нет разницы какой версией gzip сжимать - всё равно хеш будет считаться от этого файла. Или он сжимается на сервере?

А вообще такой вариант сжатия даёт PHP-функция gzencode с уровнем сжатия 9. Как вариант можно бросить php.exe + dll рядом с зенкой и запускать его.

PHP:
php -r "echo bin2hex(gzencode('1', 9));"
даёт результат:
1f8b080000000000020a330400b7efdc8301000000
проверял на php версии 7.2.3

PHP:
php -r "echo hash('sha256', gzencode('1', 9));"
>>>
697d5abc7fded2dbb8ffc4f84c4441274ab23c9e718278a9ebb4b741ba14e69c
 
  • Спасибо
Реакции: nicanil и BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
PHP:
php -r "echo bin2hex(gzencode('1', 9));"
PHP:
php -r "echo hash('sha256', gzencode('1', 9));"
Это именно то, что нужно (имеется ввиду, что сжатие GZIP должно происходить с уровнем 9).
С# - (документация) не дает возможности это сделать.
Есть библиотека, которая позволяет это решить: SharpZipLib
Но, со всеми моими танцами с бубном - пишет что версия не совместима.
Уже даже в студию забрасывал, компилировал заново, удалял подпись - результат такой, что не получается подключить её к Зенно.
67442


Пока, я разбираюсь именно с тем, чтобы совпадал хеш.
Дальше, когда совпадать Хеш будет - тогда нужно будет записать в нужные байты нужное время сжатия (чтобы время сжатия всегда изменялось при любой повторной отправке файла - что и изменит хеш). Просто чтобы не плясать потом с другими проблемами -необходимо всё же убедиться, что хеш соответствует тому, который шлёт браузер.

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

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
Видимо проблема будет решена с помощью библиотеки: DotNetZip 1.15.0 (дает возможность изменять уровень сжатия + дает возможность изменять время сжатия + дает возможность добавлять комментарий). Когда разберусь - отпишусь получилось ли это или нет.
 
Регистрация
05.06.2019
Сообщения
570
Благодарностей
453
Баллы
63
мб md5 => sha256 == result
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 764
Благодарностей
2 407
Баллы
113
мб md5 => sha256 = result
Спасибо за желание помочь!
Подсчитать хеш не проблема (любые коды выше решают эту проблему).
Открытая проблема осталась в том, чтобы сжимая 2 раза строку получить одинаковый набор байт (при подсчёте хеша с которого получится одинаковый хеш).

С шапкой GZIP разобрался - можно её подменить и будет безболезненно для набора данных.
А вот что делать с теми байтами, которые дописываются в конец после сжатия - это пока не понял (думал на себя эту работу какая-то библиотека возьмет - но, вижу что пока не берет - скорее всего нужно будет изучить что там хранится и как его там подменять, благо последняя библиотека какая-то более гибкая, шапку сформировать с её помощью можно, например подменив время сжатия, комментарий, имя файла...). А с последними байтами - не ясно..

Алгоритм сжатия PHP и JS, Node.js - идентичные (на сколько я понял). Но, они не годятся при работе с огромными файлами - из-за чего и необходимо найти решение на C#...
 
  • Спасибо
Реакции: Маломальский
Регистрация
05.06.2019
Сообщения
570
Благодарностей
453
Баллы
63
Спасибо за желание помочь!
Шифрование может строится цепочкой, да вообще как угодно) кто на что горазд.
Возможно решение лежит ближе, чем этот путь. Тут нужно смотреть пример, что-куда. Возможно и решение найдется.
 
  • Спасибо
Реакции: BAZAg

nicanil

Client
Регистрация
06.03.2016
Сообщения
2 242
Благодарностей
1 804
Баллы
113
Этот код, как и мой получает SHA256 - валидный у Вас, валидный у меня - с этим порядок.
Да, с предыдущим сообщением поспешил, прошу простить :bk:
А вот что делать с теми байтами, которые дописываются в конец после сжатия - это пока не понял (думал на себя эту работу какая-то библиотека возьмет - но, вижу что пока не берет - скорее всего нужно будет изучить что там хранится и как его там подменять, благо последняя библиотека какая-то более гибкая, шапку сформировать с её помощью можно, например подменив время сжатия, комментарий, имя файла...). А с последними байтами - не ясно..
По вот этому могу поделиться одним наблюдением - если 20-ю строку (где идёт преобразование из байт в строковое представление) заменить на string line_out = "1"; то получим практически такой же набор байт, который у Вас в первом сообщении - 1f 8b 08 00 00 00 00 00 04 00 33 04 00 b7 ef dc 83 01 00 00 00 (отличия только в 9 и 10 байтах; на сколько я понимаю, они относятся к описанию формата, а не к самим данным ).
Возможно проблема в неверной кодировке при преобразовании в строку.

Надеюсь это поможет Вам в решении задачи.
 
  • Спасибо
Реакции: BAZAg

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)