LINUX.ORG.RU

Криптографический хэш огромного массива/btree с быстрой вставкой в середину

 btree, ,


0

1

Есть, предположительно, огромный массив (или что-то более структурированное, например btree), из однотипных элементов (но могущих быть разного размера в байтах). У этого списка надо организовать криптографическую проверку целостности с помощью хэша, но с дополнительным условием: при вставке/удалении/замене элемента откуда-то из середины надо чтобы не требовалось заново пробегать по каждому из элементов и пересчитывать его.

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

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

Предлагаемая схема. Берём некий уже готовый традиционный криптохэш, считающийся надёжным по условию извне задачи. Этим хэшом хэшируем каждый элемент списка отдельно. Итоговый хэш списка считаем как степенной ряд с хэшами элементов в качестве коэфициентов:

hash(item[0..N-1]) = hash(item[0]) + hash(item[1]) * k + hash(item[2]) * pow(k,2) + ... + hash(item[N-1]) * pow(k,N-1)

где k - некое большое простое число, разрядностью равной или чуть меньше разрядности базовой хэш-функции, N - количество элементов списка, item[] - массив элементов, pow() - функция возведения в степень большой разрядности, hash() - базовая хэш-функция. Вся арифметика считается по модулю разрядности хэша, разумеется.

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

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

И ещё вопрос: а если k имеет заметно меньшую разрядность чем базовая хэш-функция, это чему-то навредит?

★★★★★

Последнее исправление: firkax (всего исправлений: 3)
Ответ на: комментарий от anonmyous

Но я вам предлагаю даже этого не делать…

Хотя, конечно, заменить меркель на AVL, но использовать попарное хеширование, а-ля меркель - это всё пляски с бубном. И если бы вы поняли, как работать с меркелем, то это бы и не понадобилось. Но я выдумал то, что подходит под ваши условия, какими бы «странными» они ни были.

anonmyous ★★
()
Последнее исправление: anonmyous (всего исправлений: 1)
Ответ на: комментарий от anonmyous

Последний раз попытаюсь объяснить в чём дело, хотя надежды, из опыта прошлого общения с тобой, мало.

У нас есть два дерева

A = ((1,2,3),(4,5,6),(7,8,9),(10,11,12),(13,14,15))
B = ((1,3,4),(5,6,7),(8,9,10),(11,12,13),(14,15,16))

Затем в первое вставляется элемент 16, во второе - элемент 2. В итоге последовательность элементов в обоих деревьях получается одинаковая - все числа от 1 до 16. Требуется чтобы у получившихся двух деревьев был одинаковый хэш. В случае с merkle tree для этого придётся как минимум в одном из двух деревьев делать перебалансировку, потому что никак ты хэши им не сравняешь, если в одном есть (7,8,9) а в другом (8,9,10). Перебалансировка эта будет заключаться в пересчитывании всех узлов дерева заново - тут их всего 5 штук, но речь идёт про огромные массивы, и объём требующегося для этого i/o чтобы прочесть всё нужное с диска, и объём необходимых вычислени пересчитывать все хэши будет большой.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

Мля, да ты прикалываешься? Я же сказал, забудь про меркель. Мы идём в порядке твоего списка, и считаем хеши у соседних элементов. Потом спариваем их и считаем хеш снова (это единственное, что осталось тут от меркелья). И дальше спариваем это со следующим элементом, и тд.

Короче. Ты не понял ни слова из сказанного мной. Но мало того, ты продолжаешь писать вот это:

случае с merkle tree для этого придётся как минимум в одном из
двух деревьев делать перебалансировку

Хотя я уже сказал, что в меркель не делается перебалансировка, там операция добавления сохраняет достаточный баланс.

пересчитывании всех узлов дерева заново

Мля, в меркеле только нон-лифы пересчитываются, что является легчайшей операцией, так как не требует никакого чтения данных! Да и то, не все, а по 1й ветви до корня!

И это после того, что я сто раз сказал: «про меркель забываем, кроме алгоритма его хеширования».

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

Есть кто в аудитории, кто следит за дискуссией? Скажите, можно ли этого чела из ступора вывести, или бесполезно?

anonmyous ★★
()