Подробное объяснение проекта ERC-7520: защита от атаки переполнения общедоступного ввода zk-SNARK

Автор: эксперты по исследованию безопасности Beosin Сая и Брайс

1. Что такое доказательство с нулевым разглашением

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

Эту концепцию можно объяснить на простом примере. Предположим, есть два человека: один — доказывающий, другой — проверяющий. Доказывающий хочет доказать проверяющему, что он знает секретный пароль, не раскрывая при этом самого пароля. Традиционным способом доказывающий может сообщить проверяющему, какой у него пароль, но при доказательстве с нулевым разглашением доказывающий может использовать специальный протокол, чтобы доказать проверяющему, что он знает правильность пароля, не раскрывая сам пароль.

В настоящее время распространенные алгоритмы системы доказательства с нулевым разглашением включают zk-SNARK, zk-STARK, BulletProofs и т. д.

2. Применение ZKP в блокчейне

В технологии блокчейна ZKP имеет множество приложений, таких как улучшение конфиденциальности, улучшение масштабируемости и безопасности и т. д. Вот некоторые ключевые применения ZKP в блокчейне:

1 Защита конфиденциальности:

Блокчейн является общедоступным, то есть любой может просмотреть все транзакции в цепочке. Однако иногда пользователи могут пожелать сохранить конфиденциальность информации о своих транзакциях. ZKP позволяет пользователям доказать, что у них достаточно средств для торговли, без необходимости раскрывать общую сумму своих средств. Это значительно повышает защиту конфиденциальности пользователей. Например, Zcash — это криптовалюта, использующая технологию доказательства с нулевым разглашением, которая позволяет пользователям скрывать отправителя, получателя и сумму транзакции.

2 Вычислительное сжатие и расширение блокчейна:

Масштабируемость блокчейна является непростой задачей, особенно в крупномасштабных приложениях. ZKP можно использовать для снижения нагрузки на узлы и улучшения масштабируемости всей системы. Используя ZKP для проверки достоверности транзакций, узлам не нужно просматривать полную историю транзакций, тем самым снижая нагрузку на хранение и обработку.ZK Rollup, в настоящее время наиболее широко используемый, представляет собой масштабируемое решение, предназначенное для улучшения Ethereum и других областей. Пропускная способность и эффективность сетей блокчейн. Он сочетает в себе преимущества технологий Rollup и ZKP для предоставления высокопроизводительных решений для расширения децентрализованных приложений (DApps). В традиционной сети Ethereum каждая транзакция должна быть проверена и записана в блокчейне, что приводит к задержкам и высоким затратам на обработку транзакций. ZK Rollup группирует и сжимает большое количество транзакций в один блок, а ZKP используется для подтверждения достоверности пакетных транзакций, чтобы гарантировать правильность и безопасность транзакций.

3 Аутентификация:

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

4 Децентрализованное хранилище:

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

В целом, **доказательство с нулевым разглашением информации в блокчейне имеет широкое применение в защите конфиденциальности, сжатии и расширении вычислений, проверке личности, децентрализованном хранении и т. д. Он предоставляет больше функций и возможностей для технологии блокчейна и способствует развитию и применению блокчейна в различных областях. **

3. Атака двойных расходов в приложениях ZKP

zk-SNARK (Краткий неинтерактивный аргумент знания с нулевым разглашением) — это технология, основанная на доказательстве с нулевым разглашением, которая может доказать подлинность утверждения без раскрытия реальной информации. Это очень эффективная технология доказательства с нулевым разглашением, которая может генерировать и проверять доказательства за очень короткое время, обеспечивая при этом конфиденциальность и безопасность, поэтому она широко используется. Однако с расширением приложений его безопасность привлекает все больше внимания. Не так давно мы обнаружили его общую уязвимость: если диапазон значений входного параметра в функции проверки неправильно проверен в проекте ZKP, злоумышленник может подделать несколько входных данных для прохождения проверки, что приведет к атаке двойного расходования. Влияние этой атаки очень велико и включает в себя несколько алгоритмов zk-SNARK, включая Groth16, plonk и т. д., и эта уязвимость существует во многих языках разработки, таких как Solidity и js. Эта уязвимость была впервые обнаружена Poma в проекте доказательства с нулевым разглашением Semaphore, и были приведены два примера успешно реализованных транзакций, как показано на рисунке ниже:

Конкретный принцип атаки этой уязвимости заключается в том, что если вы хотите сгенерировать и проверить доказательство zk-SNARK в Ethereum, вам необходимо использовать схему эллиптической кривой с конечным полем F_p-арифметики, где значение p используется для определения диапазона конечного поля эллиптической кривой, поэтому диапазон входных значений схемы составляет [0,1,…,p-1]. Разные кривые имеют разные значения p:

Кривая BN254, определенная в EIP-196 (также известная как кривая ALT_BN128):

р = 21888242871839275222246405745257275088548364400416034343698204186575808495617

circom2 представляет два новых простых числа — кривые BLS12-381:

р = 52435875175126190479447740508185965837690552500527637822603658699938581184513

и плинк2:

18446744069414584321

YkMsUbmKFjMsTG6nLSo6mdggbsABtGXrkBJb8GxQ.png

Позже Semaphore подтвердил и исправил уязвимость, а библиотеки zk, такие как ZoKrates и snarkjs, также одновременно произвели аварийный ремонт. Однако исследователи безопасности Beosin обнаружили, что в настоящее время не существует единого решения этой проблемы. Например, протокол Semaphore записывает ограничения в сопряжение. допустимый диапазон данных не проверяется явно во внешней бизнес-логике; код контракта, сгенерированный circom и Tornado.Cash, явно проверяет SNARK_SCALAR_FIELD в функции проверки. Это запутанное и противоречивое решение. Это может привести к проблемы и риски безопасности для многих новых участников проекта zk DApp, поэтому мы надеемся использовать стандартизированный способ решения этой проблемы.

4. Атака двойной траты в ERC-1922

В настоящее время у Ethereum есть связанный с zk стандарт EIP-1922, который представляет стандартный интерфейс контракта Verify для проверки zk-SNARK. Конкретный код выглядит следующим образом:

pragma Solidity ^0.5.6;/// @title EIP-XXXX zk-SNARK Verifier Standard/// @dev См. /// Примечание: идентификатор ERC-165 для этого интерфейса — 0xXXXXXXXX./// ⚠️ TODO: Вычислить интерфейс идентификатор интерфейса ERC1922 /* равен ERC165 */ { /// @notice Проверяет аргументы доказательства с помощью функций объединения эллиптических кривых ///. /// @dev /// ДОЛЖЕН возвращать true, если Доказательство проходит все проверки (т. е. Доказательство /// действительно). /// ДОЛЖЕН возвращать false, если Доказательство не проходит все проверки (т. е. если /// Доказательство недействительно). /// @param доказательство А zk-SNARK. /// @param inputs Открытые входные данные, сопровождающие доказательство. /// @paramverificationKeyId Уникальный идентификатор (известный этому /// контракту верификатора) ключа проверки, которому соответствует Proof. /// @return result Результат проверочного расчета. True /// если Доказательство действительно; ложь в противном случае. функция проверки (uint256[] calldataproof, uint256[] calldata inputs, bytes32verificationKeyId) внешние возвраты (логический результат);}

Среди них доказательство с нулевым разглашением и типы входных переменных - uint256[]. Этот тип переменной в настоящее время является наиболее часто используемой операцией эллиптической кривой в алгоритме ZKP. Однако соответствующая защита безопасности не добавлена к этому интерфейсу, поэтому дважды Атаки на траты также существуют.Огромная угроза безопасности.

5. Решение ERC-7520

Учитывая вышеизложенные проблемы, Beosin предложил EIP-7520 для предотвращения такого рода угроз безопасности.В частности, все проекты DApp, использующие технологию zk в экосистеме Ethereum, должны реализовать этот интерфейс в совместимом контракте верификатора, чтобы использовать унифицированные и безопасные стандарты.Метод работает действительная проверка диапазона на всех входах.Конкретный интерфейс выглядит следующим образом:

pragma Solidity ^0.5.6;/// @title EIP-XXXX zk-SNARK public inputs Verifier Standard/// Примечание: идентификатор ERC-165 для этого интерфейса — 0xXXXXXXXX./// ⚠️ TODO: Вычислить идентификатор интерфейсаinterface EIP7520 /* is ERC165 и ERC1922 */ { /// @notice Проверяет, что аргументы входных данных находятся в пределах скалярного поля /// @dev /// ДОЛЖЕН возвращать true, если входные данные проходят проверку диапазона (т. е. входные данные /// действительны). /// ДОЛЖЕН возвращать false, если входные данные не проходят проверку диапазона (т. е. если /// входные данные недействительны). /// @param inputs Открытые входные данные, сопровождающие доказательство. /// @param p Открытый ввод, сопровождающий кривую. функцияverifyPublicInput(uint256[] inputs,uint256 p) внешние возвраты (логический результат);}

ФункцияverifyPublicInput является ядром этого стандарта. Конкретные значения задействованных параметров следующие:

  • входные данные: определены как тип uint256[], представляющий параметры общедоступного сигнала, задействованные в функции проверки в проекте ZKP.
  • p: определено как тип uint256, это значение соответствует значению p эллиптической кривой, используемой в алгоритме.

Ниже будут сравниваться две ситуации внедрения и нереализации интерфейса EIP-7520 с целью выявления различных проявлений этой атаки, чтобы указать на риски для сторон проекта:

1 Предположим, что мы напрямую используем код контракта проверки для проверки, не вызываяverifyPublicInput этого интерфейса eip.Конкретный код выглядит следующим образом:

функция проверки (uint [] ввод памяти, доказательство памяти) внутреннее представление возвращает (uint) { VerifyingKey Memory vk = VerifyingKey(); require(input.length + 1 == vk.IC.length, "verifier-bad-input"); // Вычисление линейной комбинации vk_x Pairing.G1Point в памяти vk_x = Pairing.G1Point(0, 0); for (uint i = 0; i < input.length; i++) vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input [i] )); vk_x = Сопряжение.дополнение(vk_x, vk.IC [0] ); if (!Pairing.pairingProd4( Pairing.negate(proof.A),proof.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2,proof.C, vk.delta2)) вернуть 1; вернуть 0;}

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

В то же время следующие четыре сертификата могут быть подделаны и также могут пройти проверку, вызывая атаку двойного расходования:

Результаты проверки с использованием одного из поддельных доказательств показаны ниже:

  1. Если вызывается интерфейсverifyPublicInput в этом eip, приведенное выше поддельное доказательство не сможет быть проверено.Часть кода контракта выглядит следующим образом.Остальную информацию см. в разделе «Справочная реализация»:

functionverifyx(uint[]входы памяти, доказательство памяти, bytes32verificationKeyId,uint256 p) public return (uint){ require(verifyPublicInput(inputs,p),"verifier-over-snark-scalar-field"); require(verify(inputs,proof,verificationKeyId),"проверка не удалась"); return true;}functionverifyPublicInput(uint256[] inputs,uint256 p) внутреннее представление возвращает (bool) { for (uint i = 0; i < input.length; i++) { require(input < p,"verifier-gte-snark -скалярное поле"); } вернуть истину;}

Результаты эксперимента показаны на рисунке ниже:

Таким образом, можно обнаружить, что если этот интерфейс не используется для проверки достоверности диапазона значений общедоступного сигнала, может возникнуть риск атак двойного расходования. **

Посмотреть Оригинал
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
  • Награда
  • комментарий
  • Поделиться
комментарий
0/400
Нет комментариев
  • Закрепить