EssayAI
Блог
Блог
Математика и алгоритмы

Протокол Шнорра: схема доказательства знания и подпись

19 июня 2026Время чтения: 8 минут
#криптография#протокол шнорра#дискретный логарифм#цифровая подпись#фиат-шамир
Протокол Шнорра: схема доказательства знания и подпись

Протокол Шнорра - это интерактивная схема, в которой одна сторона (доказывающий) убеждает другую (проверяющего) в том, что знает секрет - дискретный логарифм xx публичного значения y=gxy = g^x, - ни на бит не раскрывая сам секрет. Это канонический пример доказательства с нулевым разглашением и одновременно основа целого семейства цифровых подписей: убрав интерактивность приёмом Фиата - Шамира, из протокола получают компактную подпись Шнорра, которая лежит в основе EdDSA и обновления Bitcoin Taproot. В этой статье разберём тройку обязательство - вызов - ответ, уравнение проверки, три свойства протокола (полнота, корректность, нулевое разглашение) и переход к неинтерактивной подписи. Чтобы пройти раунд по шагам с конкретными числами, воспользуйтесь конструктором ниже.

Что доказывает протокол Шнорра

Зафиксируем циклическую группу GG порядка qq с генератором gg - обычно это подгруппа простого порядка в Zp\mathbb{Z}_p^* или группа точек эллиптической кривой. Доказывающий знает секретный ключ x{1,,q1}x \in \{1, \dots, q-1\}, а публичным является y=gxy = g^x. Перейти от xx к yy легко, а восстановить xx по yy - это задача дискретного логарифма, для которой в правильно выбранной группе не известно эффективного алгоритма. Именно на этой односторонности держится вся конструкция.

Задача протокола - убедить проверяющего, что доказывающий действительно знает xx, не передавая ни xx, ни даже частичной информации о нём. Это сильнее, чем просто «знать пароль и показать его»: проверяющий после диалога не сможет ни сам выдать себя за доказывающего, ни убедить кого-то третьего. Похожая идея односторонней функции и пары ключей лежит и в основе цифровой подписи ECDSA, но там схема сразу неинтерактивна, тогда как Шнорр начинается с честного диалога из трёх сообщений.

Тройка обязательство - вызов - ответ

Один раунд протокола Шнорра - это три сообщения между доказывающим (П) и проверяющим (В). Их традиционно обозначают (t,c,s)(t, c, s) и называют обязательством, вызовом и ответом.

  1. Обязательство. Доказывающий выбирает случайный одноразовый секрет r{1,,q1}r \in \{1, \dots, q-1\} (его называют нонсом или маскирующим), вычисляет t=grt = g^r и отправляет tt проверяющему. Это «заявка», которую нельзя будет изменить задним числом.
  2. Вызов. Проверяющий выбирает случайный вызов cc из множества допустимых значений и отправляет его доказывающему.
  3. Ответ. Доказывающий вычисляет s=r+cxmodqs = r + c \cdot x \bmod q и отправляет ss. В этом ответе секрет xx присутствует, но он спрятан под слагаемым rr, которое проверяющий не знает.
Схема протокола Шнорра: три стрелки обязательство, вызов и ответ между доказывающим и проверяющим, внизу уравнение проверки
Схема протокола Шнорра: три стрелки обязательство, вызов и ответ между доказывающим и проверяющим, внизу уравнение проверки

Вся соль в том, что rr - свежий случайный для каждого раунда. Без него ответ ss был бы просто функцией от xx, и секрет можно было бы извлечь. С ним ss выглядит для проверяющего как равномерно случайное число.

Уравнение проверки

Получив тройку (t,c,s)(t, c, s), проверяющий принимает решение по единственному равенству:

gs=?tyc.g^s \stackrel{?}{=} t \cdot y^c.

Если оно выполняется, проверка пройдена. Почему это работает, видно из прямой подстановки. У честного доказывающего s=r+cxs = r + c x, поэтому

gs=gr+cx=gr(gx)c=tyc.\begin{aligned} g^s &= g^{r + c x} \\ &= g^r \cdot (g^x)^c \\ &= t \cdot y^c. \end{aligned}

Равенство - тождество, значит честный доказывающий всегда проходит проверку. Это свойство называют полнотой (completeness): кто знает xx, тот гарантированно убеждает проверяющего. Заметьте, что проверяющему для расчёта нужны только публичные gg, yy и пришедшие tt, cc, ss - секрет xx в проверку не входит.

Почему секрет не раскрывается

Главное обещание протокола - нулевое разглашение (zero-knowledge): из диалога проверяющий не узнаёт об xx ничего, чего не мог бы вычислить сам. Формально это доказывают через симулятор: можно сгенерировать тройку (t,c,s)(t, c, s) с тем же распределением, что у настоящего диалога, вообще не зная xx. Достаточно выбрать случайные cc и ss, а затем положить t=gsyct = g^s \cdot y^{-c} - такая тройка пройдёт проверку и неотличима от честной. Раз поддельный протокол с правильным распределением строится без секрета, значит настоящий протокол секрета и не выдаёт.

Сравнение двух тропинок: знающий секрет проходит проверку, симулятор подделывает тройку без секрета, обе ведут к успешной проверке
Сравнение двух тропинок: знающий секрет проходит проверку, симулятор подделывает тройку без секрета, обе ведут к успешной проверке

Здесь важно условие честного проверяющего: он выбирает cc независимо от tt. Если бы проверяющий мог подсмотреть tt и хитро подобрать cc, схема в базовом виде уже не была бы строго нулевого разглашения - для общего случая нужны дополнительные приёмы. В учебных задачах почти всегда подразумевают честно-проверяющую модель.

Корректность: почему нельзя обмануть

Симметричное свойство - корректность (soundness, особая корректность): жулик, не знающий xx, не сможет систематически проходить проверку. Доказывают это так. Предположим, доказывающий с одним и тем же обязательством tt сумел ответить на два разных вызова c1c2c_1 \ne c_2 корректными ответами s1s_1 и s2s_2. Тогда

gs1=tyc1,gs2=tyc2.\begin{aligned} g^{s_1} &= t \cdot y^{c_1}, \\ g^{s_2} &= t \cdot y^{c_2}. \end{aligned}

Поделив одно на другое, получаем gs1s2=yc1c2g^{s_1 - s_2} = y^{c_1 - c_2}, откуда

x=s1s2c1c2modq.x = \frac{s_1 - s_2}{c_1 - c_2} \bmod q.

То есть любой, кто отвечает на два вызова при одном tt, тем самым вычисляет секрет xx. Раз вычислить дискретный логарифм нельзя, нельзя и отвечать на два вызова, - значит, на случайный единственный вызов жулик угадывает ответ лишь с пренебрежимо малой вероятностью. Этот же приём «извлечения секрета из двух ответов» дословно повторяет логику атаки на повтор нонса в алгоритме обмена ключами Диффи - Хеллмана и в ECDSA.

От диалога к подписи: эвристика Фиата - Шамира

Интерактивность неудобна: подписать файл «один раз для всех» в диалоге нельзя. Приём Фиата - Шамира убирает проверяющего, заменяя его случайный вызов на хэш. Доказывающий сам вычисляет

c=H(g,y,t,m),c = H(g, y, t, m),

где mm - подписываемое сообщение, а HH - криптографическая хэш-функция. Поскольку cc зависит от tt непредсказуемым образом, доказывающий не может заранее подогнать tt под удобный cc - хэш играет роль честного проверяющего. Подпись Шнорра - это пара (c,s)(c, s) или (t,s)(t, s), а проверка остаётся той же: пересчитать c=H(g,y,t,m)c = H(g, y, t, m) и убедиться, что gs=tycg^s = t \cdot y^c.

Именно так из учебного протокола вырастает практичная подпись: компактная, с простым и линейным уравнением, поддающаяся агрегации нескольких подписей в одну. Поэтому Шнорр выбрали для EdDSA (Ed25519) и для Bitcoin Taproot.

Частые ошибки

  • Повтор нонса rr. Если переиспользовать одно rr для двух подписей, по двум ответам s1,s2s_1, s_2 мгновенно вычисляется x=(s1s2)/(c1c2)x = (s_1 - s_2)/(c_1 - c_2) - ровно как в доказательстве корректности. Нонс обязан быть свежим и непредсказуемым для каждого раунда.
  • Путать порядок группы qq и модуль pp. Степени и t=grt = g^r считают по модулю pp, а показатели s=r+cxs = r + cx - по модулю qq (порядка генератора). Смешение модулей - самая частая арифметическая ошибка в задачах.
  • Считать, что ss что-то выдаёт об xx. Слагаемое rr маскирует секрет: при честном случайном rr ответ ss распределён равномерно и сам по себе об xx не говорит ничего.
  • Забывать про честно-проверяющую модель. Нулевое разглашение базового протокола доказано для проверяющего, который выбирает cc независимо от tt; это условие нужно явно оговаривать.
  • Брать вызов cc из слишком маленького множества. Если вызовов всего несколько, жулик угадывает ответ с заметной вероятностью; стойкость требует большого пространства вызовов.

FAQ

Чем протокол Шнорра отличается от подписи Шнорра? Протокол - это интерактивный диалог из трёх сообщений (обязательство, вызов, ответ), доказывающий знание дискретного логарифма. Подпись Шнорра получается из него приёмом Фиата - Шамира: вызов cc заменяют на хэш H(g,y,t,m)H(g, y, t, m), и диалог сворачивается в неинтерактивную пару чисел.

Почему протокол Шнорра считают доказательством с нулевым разглашением? Потому что существует симулятор, который строит тройку (t,c,s)(t, c, s) с тем же распределением, что и настоящий диалог, не зная секрета xx (выбирает c,sc, s и кладёт t=gsyct = g^s y^{-c}). Раз правдоподобный протокол собирается без секрета, настоящий диалог секрета не выдаёт.

Где протокол Шнорра применяется на практике? Его неинтерактивная форма - подпись Шнорра - лежит в основе схемы EdDSA (Ed25519) и обновления Bitcoin Taproot, где ценят компактность подписи, простое линейное уравнение проверки и возможность агрегировать несколько подписей в одну.

Коротко

Протокол Шнорра доказывает знание дискретного логарифма xx публичного y=gxy = g^x через диалог обязательство - вызов - ответ (t,c,s)(t, c, s) с проверкой gs=tycg^s = t \cdot y^c. Он полон (честный всегда проходит), корректен (ответ на два вызова при одном обязательстве выдаёт секрет, значит обмануть нельзя) и нулевого разглашения (тройку подделывает симулятор без секрета). Заменив случайный вызов на хэш по Фиату - Шамиру, из протокола получают компактную подпись Шнорра - основу EdDSA и Bitcoin Taproot.

Доверьте текст нейросети EssayAI

Открыть EssayAI

Бесплатно, на русском языке и без VPN

Читайте также