<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Stepan Novozhilov]]></title><description><![CDATA[Stepan Novozhilov]]></description><link>https://hit2hat.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 08 Nov 2026 13:56:15 GMT</lastBuildDate><atom:link href="https://hit2hat.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Zero-Knowledge Proof: Доказательство с нулевым разглашением для гамильтонова цикла]]></title><description><![CDATA[Zero-Knowledge Proof (ZKP или Доказательство с нулевым разглашением) - это передовая технология, которая уже используется во многих современных продуктах…]]></description><link>https://hit2hat.hashnode.dev/zkp-graphs</link><guid isPermaLink="true">https://hit2hat.hashnode.dev/zkp-graphs</guid><category><![CDATA[zk-snark]]></category><category><![CDATA[Cryptography]]></category><category><![CDATA[zero-knowledge-proofs]]></category><category><![CDATA[zero-knowledge]]></category><dc:creator><![CDATA[Stepan Novozhilov]]></dc:creator><pubDate>Wed, 13 Mar 2024 23:01:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710370032142/bc1cf9b5-8ee6-4be3-a923-1824428d2dc3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Zero-Knowledge Proof</strong> <em>(ZKP или Доказательство с нулевым разглашением)</em> - это передовая технология, которая уже используется во многих современных продуктах, которыми вы даже может быть пользовались. Давайте посмотрим, как это работает на примере абстрактных задач, а после попробуем решить уже вполне конкретную, используя графы и их свойства.</p>
<h2 id="heading-chto-takoe-dokazatelstvo-s-nulevym-razglasheniem">Что такое доказательство с нулевым разглашением?</h2>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Доказательство с нулевым разглашением</strong> — это такое доказательство, которое способно доказать одной стороне <em>(проверяющему)</em> утверждение без разглашения конфиденциальной информации второй стороны <em>(доказывающего)</em>.</div>
</div>

<p>Думаю, что сухое определение - это явно не то, зачем вы сюда пришли. Поэтому давайте взглянем на примеры, которые в своё время помогли лично мне понять в какой области задач можно применять ZKP:</p>
<h3 id="heading-primer-1-bazovyj">Пример 1. Базовый.</h3>
<p>У Алисы есть почтовый ящик с кодовым замком. Она поспорила со своим другом Бобом, что знает от него пароль, но разглашать пароль ей категорически нельзя: в почтовый ящик иногда попадает секретная почта, и если Боб узнает пароль от кодового замка, то он может получить доступ и к ней. Почтовый ящик Алисы не имеет функции изменения пароля.</p>
<p>Чтобы доказать, что Алиса действительно знает пароль от почтового ящика, она отворачивается, просит Боба написать на листочке любое число и бросить его в её ящик. После этого Алиса просит Боба отойти, открывает свой почтовый ящик с помощью пароля и говорит вслух число Боба.</p>
<p><img src="https://rudalle-coordinator.sberdevices.ru/static/5c/c0/58/5cc05867397b4a2dbf6b7a1336146884_res_00000_image.jpg" alt /></p>
<p>Алиса доказала Бобу, что знает пароль, а Боб не получил никакой конфиденциальной информации Алисы. Хотя более корректно будет сказать, что Боб вообще не получил никакой новой информации.</p>
<h3 id="heading-primer-2-rasshirennyj">Пример 2. Расширенный.</h3>
<p>Айтишники имеют небольшое преимущество в понимании ZKP, так как есть очень простая аналогия. Представим у вас есть пароль <code>mycoolpassword</code>. Вы вычислили значение хеш-функции sha256 от него: <code>835d052d985517cb1fa5fc4bf44228f898f7a2233383feaf5cd23ea2fd9b2a3f</code>.</p>
<p>Доказательством с нулевым разглашением будет такое решение, которое позволит доказать, что вы знаете захешированное значение в <code>835d052d985517cb1fa5fc4bf44228f898f7a2233383feaf5cd23ea2fd9b2a3f</code> не разглашая само это значене (тот самый пароль <code>mycoolpassword</code>).</p>
<p>К сожалению, я не смогу привести доказательство с нулевым разглашением для этой задачи в рамках данной статьи, поскольку оно очень сложное, но этот пример показывает логику ZKP и где их можно применять.</p>
<h2 id="heading-kto-to-skazal-grafy">Кто-то сказал графы?</h2>
<p>Чтобы разобраться, как можно использовать доказательства с нулевым разглашением в реальных задачах, нам необходимо разобраться с математической моделью. В данной статье мы рассмотрим один из самых простых способов создать ZKP с помощью теории графов, но перед этим нам необходимо вспомнить (а некоторым узнать) несколько определений в области математики, которая изучает графы.</p>
<h3 id="heading-chto-takoe-graf"><strong>Что такое граф?</strong></h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Граф</strong> — это совокупность множества вершин и множества их парных связей (рёбер).</div>
</div>

<p>Обычно, графы изображают <em>(простите за каламбур)</em> графически. Выглядит это как-то так:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710363416554/d5c7ff3b-2286-4ed9-be51-27c7de73b0dc.png" alt class="image--center mx-auto" /></p>
<p><code>0</code>, <code>1</code>, <code>2</code>, <code>3</code>, <code>4</code>, <code>5</code>, <code>6</code> - это вершины графа.<br /><code>0-1</code>, <code>0-2</code>, <code>1-2</code>, <code>1-3</code> и т. д. - это рёбра графа (попарное соединение вершин).</p>
<h3 id="heading-spisok-smezhnosti"><strong>Список смежности</strong></h3>
<p>Один из самых оптимальных вариантов представления графа в компьютере - список смежности. Данный граф можно представить с помощью этого способа в виде следующей таблицы:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Вершина</td><td>Вершины, с которыми есть связь из данной</td></tr>
</thead>
<tbody>
<tr>
<td>0</td><td>1, 2</td></tr>
<tr>
<td>1</td><td>0, 2, 3</td></tr>
<tr>
<td>2</td><td>0, 1, 4, 5</td></tr>
<tr>
<td>3</td><td>1, 4</td></tr>
<tr>
<td>4</td><td>2, 3, 5</td></tr>
<tr>
<td>5</td><td>2, 4, 6</td></tr>
<tr>
<td>6</td><td>5</td></tr>
</tbody>
</table>
</div><h3 id="heading-put-v-grafe"><strong>Путь в графе</strong></h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Путь</strong> — это последовательность вершин, в которой каждая вершина соединена со следующей ребром.</div>
</div>

<p>На примере данного графа <code>0-1-2</code> - это путь.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710363350197/5b72c767-5e74-4d7d-aefa-4da11b8f1d06.png" alt class="image--center mx-auto" /></p>
<p>А <code>0-2-6</code> - нет, потому что даже учитывая, что существует соединение между вершинами 0 и 2, соединения между вершинами 2 и 6 нет <em>(нет такого ребра)</em>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710363219081/7b738459-9337-4dd1-8fd3-f6bcc8d303f0.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-gamiltonov-put">Гамильтонов путь</h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Гамильтонов путь</strong> — это такой путь, который проходит через все вершины графа и при том ровно один раз.</div>
</div>

<p>Например, в нашем графе есть такой гамильтонов путь <code>0-1-3-4-2-5-6</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710363834194/f740e19b-2f79-45c9-9e20-777de3810532.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-gamiltonov-cikl"><strong>Гамильтонов цикл</strong></h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Гамильтонов цикл</strong> — это такой гамильтонов путь, последняя вершина которого имеет общее ребро с первой.</div>
</div>

<p>В нашем графе вершина под номером 6 не имеет второго ребра и поэтому граф априори не может иметь гамильтонов цикл.</p>
<p>Для примера рассмотрим другой граф:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710364462607/9d0aa884-38f2-44c9-a2cb-246dbf0ece69.png" alt class="image--center mx-auto" /></p>
<p>В этом графе можно найти следующий гамильтонов цикл: <code>1-4-3-2</code>. Последняя вершина пути (вершина 2) имеет общее ребро с первой вершиной пути (вершиной 1).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710364449361/e9e3aa14-785d-421e-afd3-055bf0024a9d.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-zkp-i-grafy">ZKP и графы</h2>
<p>Понимаю, что небольшой экскурс в основы теории графов мог вас утомить, но это было необходимо для вашего первого доказательства с нулевым разглашением с использованием математики. Наконец, вы дождались этого.</p>
<h3 id="heading-zadacha">Задача</h3>
<p>У Боба есть граф G. Боб заказал у Алисы поиск гамильтонова цикла в своём графе за 100 рублей. Алиса нашла гамильтонов цикл, но сначала хочет получить от Боба оплату, поскольку после его разглашения Боб может получить решение и не заплатить за него.</p>
<p>Нужно помочь Алисе доказать, что она знает гамильтонов цикл в графе Боба без его разглашения.</p>
<h3 id="heading-reshenie">Решение</h3>
<p>В глянем на решение Алисы в графе Боба:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710365531753/fe22f90c-7cf8-4eea-91f9-7d3d1ffc6a76.png" alt class="image--center mx-auto" /></p>
<p>Алиса нашла цикл <code>a-b-c-d-e-f-g</code>. Вершина <code>g</code> имеет общее ребро с вершиной <code>a</code>, поэтому это точно гамильтонов цикл. Давайте построим список смежности для этого графа:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Вершина</td><td>Вершины, с которыми есть связь из данной</td></tr>
</thead>
<tbody>
<tr>
<td>a</td><td>b, c, g</td></tr>
<tr>
<td>b</td><td>a, c</td></tr>
<tr>
<td>c</td><td>a, b, d, e, g</td></tr>
<tr>
<td>d</td><td>c, e</td></tr>
<tr>
<td>e</td><td>c, d, f, g</td></tr>
<tr>
<td>f</td><td>e, g</td></tr>
<tr>
<td>g</td><td>a, c, e, f</td></tr>
</tbody>
</table>
</div><p>Чтобы помочь Алисе нам потребуется сделать изоморфный граф. Грубо говоря мы просто возьмём все вершины и перемешаем их названия. Из такого определения легко понять, что свойства графа никак не изменятся, поскольку связи между вершинами (пусть и переименованными) остаются неизменными.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710366186849/970d1ffd-0c0b-4b48-93cf-ad26f9d20a92.png" alt class="image--center mx-auto" /></p>
<p>Опишем найденный ранее гамильтонов цикл с помощью новых названий вершин: <code>f-g-a-e-d-c-b</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710367155587/ffcc3c2a-bb70-4e7b-a0e5-223a5b460631.png" alt class="image--center mx-auto" /></p>
<p>Таблица смежности для нового графа будет выглядеть таким образом:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Вершина</td><td>Вершины, с которыми есть связь из данной</td></tr>
</thead>
<tbody>
<tr>
<td>a</td><td>b, d, e, f, g</td></tr>
<tr>
<td>b</td><td>a, c, d, f</td></tr>
<tr>
<td>c</td><td>b, d</td></tr>
<tr>
<td>d</td><td>a, b, c, e</td></tr>
<tr>
<td>e</td><td>a, d</td></tr>
<tr>
<td>f</td><td>a, b, g</td></tr>
<tr>
<td>g</td><td>a, f</td></tr>
</tbody>
</table>
</div><p>Зачем мы это сделали? Дело в том, что определить смежность двух графов достаточно сложно: просто посмотрите на таблицы смежности оригинального графа и изоморфного графа. Боб не может быстро однозначно сопоставить точки в изначальном графе и изоморфном графе. Это свойство нам очень пригодится.</p>
<p>Теперь мы можем предоставить такой граф Бобу. У него есть возможность задать один из двух вопросов:</p>
<ul>
<li><p>Точно ли этот граф изоморфный? (Алиса покажет, как именно она поменяла вершины)</p>
</li>
<li><p>Точно ли в таком графе есть гамильтонов цикл? (Алиса покажет гамильтонов цикл в изоморфном графе)</p>
</li>
</ul>
<p>Если Алиса раскроет и доказательства изоморфности графа, и доказательства найденного гамильтонова цикла, то у Боба будет вся необходимая ему информация, а при ответе только на один вопрос Бобу не хватит информации, чтобы применить решение Алисы для исходного графа, однако он будет убеждён в том, что у Алисы оно есть.</p>
<p>Если Боб задаёт вопросы полностью случайно, то Алиса не знает какой вопрос задаст Боб. Соответственно, если Алиса пытается соврать, то она сможет подготовить ответ только на один вопрос:</p>
<ul>
<li><p>либо то, что граф изоморфный (но тогда если Боб спросит гамильтонов цикл, то Алиса правильно ответить не сможет)</p>
</li>
<li><p>либо то, что гамильтонов цикл в графе есть (но тогда если Боб спросит об изоморфности, то Алиса не сможет доказать Бобу, что это его исходный граф)</p>
</li>
</ul>
<p>Получается, вероятность, что Алиса угадает вопрос и подстроит под него решение - <code>1/2</code>.</p>
<p>Далее Алиса и Боб могут повторять эту процедуру нужное Бобу количество раз. Если вероятность Алисы успешно соврать <code>1/2</code>, то для 2 прогонов такого сценария <code>1/2 * 1/2 = 1/4</code> и так далее.</p>
<h3 id="heading-a-teper-na-yazyke-matematiki">А теперь на языке математики</h3>
<p>Обозначим исходный граф Боба G с вершинами V как <code>G(V)</code>. Тогда можем обозначить найденый гамильтонов цикл как функцию от графа <code>H(G)</code>. Алиса преобразует граф <code>G(V)</code> в изоморфный с помощью функции <code>P</code>: <code>P(G)</code>. Гамильтонов цикл для нового графа: <code>H(P(G))</code>.</p>
<p>Лучший алгоритм поиска гамильтонова цикла в графе с <code>n</code> вершинами сейчас имеет сложность:</p>
<p>$$O(n * 2^n)$$</p><p>Быстрого алгоритма для восстановления оригинального графа из изоморфного нет. Боб не сможет за полиномиальное время выполнить эту задачу и ему придётся перебрать все возможные варианты. Сложность такого алгоритма для графов с <code>n</code> вершинами:</p>
<p>$$O(n!)$$</p><p>Можем сравнить графики алгоритмических сложностей этих алгоритмов наглядно (зелёный - алгоритм поиска гамильтонова цикла, синий - алгоритм перебора изоморфного графа):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710368265400/0be26446-4e17-458b-b065-7e0141d443fa.png" alt class="image--center mx-auto" /></p>
<p>Как видно из этого графика, сложность намного быстрее возрастает для алгоритма полного перебора графа: уже для 10 вершин это <code>3 628 800</code> комбинаций, когда для алгоритма нахождения гамильтонова цикла количество комбинаций всего <code>10 240</code>.</p>
<p>При этом, проверить решение Алисы таким способом очень просто и быстро. Боб сможет сделать это за линейное время. Алгоритмическая сложность для графа с <code>n</code> вершинами:</p>
<p>$$O(n)$$</p><p>Также, поскольку Боб задаёт вопросы равновероятно, то шанс, что Алиса сможет успешно обмануть Боба каждый из <code>n</code> раз:</p>
<p>$$P = \frac{1}{2^n}$$</p><p>Для 300 раз вероятность обмануть Боба становится уже <code>2^300</code>, что оценивается как "супер-пупер-дупер крайне маловероятно". Для сравнения, количество частиц в наблюдаемой вселенной оценивается как <code>10^87</code>, но:</p>
<p>$$10^{87} &lt; 2^{300}$$</p><h3 id="heading-algoritm-resheniya">Алгоритм решения</h3>
<ol>
<li><p>Найти в графе <code>G(V)</code> гамильтонов цикл <code>H(G)</code></p>
</li>
<li><p>Создать изоморфный граф <code>G' = P(G)</code></p>
</li>
<li><p>Переименовать точки в ранее найденом гамильтоновом цикле согласно полученному изоморфному графу: <code>H' = P(H(G))</code></p>
</li>
<li><p>Предоставить получившийся изоморфный граф <code>G'</code> Бобу</p>
</li>
<li><p>Боб может задать один из двух вопросов:</p>
<ol>
<li><p>Как именно был переименован граф? Мы предоставляем сопоставление точек изоморфного графа <code>G'</code> и оригинального графа <code>G</code></p>
</li>
<li><p>Какой гамильтонов цикл в графе? Мы предоставляем для графа <code>G'</code> найденый гамильтонов цикл <code>H'</code></p>
</li>
</ol>
</li>
<li><p>Если Бобу нужно ещё доказательство, то возвращаемся на шаг 2</p>
</li>
</ol>
]]></content:encoded></item></channel></rss>