Перейти к содержимому
ecdsa.com

ECDSA или подписи Schnorr: что изменил Taproot

Schnorr — более старая и простая схема с более строгим доказательством стойкости; ECDSA появилась во многом из-за патента. BIP-340 принёс Schnorr в Bitcoin в 2021 году, а EdDSA — во все остальные системы.

Сегодня выбор между ECDSA и Schnorr касается в основном Bitcoin: Taproot (BIP 340–342, активирован в ноябре 2021 года) добавил подписи Schnorr наряду с ECDSA на той же кривой secp256k1. Обе схемы используют одни и те же ключи и опираются на одну и ту же трудную задачу, но линейная структура Schnorr делает мультиподписи, пороговое подписание и пакетную проверку естественными, а структура ECDSA превращает их в громоздкие конструкции.

Коротко о главном

ECDSA (secp256k1)Schnorr (BIP-340, secp256k1)
Уравнение подписиs = k⁻¹·(z + r·d) mod ns = k + e·d mod n, e = H(R ‖ P ‖ m)
Открытый ключ33 байта в сжатой форме (65 в несжатой)32 байта, только координата x (x-only)
Подпись64 байта в компактной форме; 70–72 байта в DER в скриптах Bitcoin64 байта
Пластичность(r, n − s) тоже верна; Bitcoin требует low-SОтсутствует при проверке по BIP-340
Восстановление открытого ключаВозможно (ecrecover в Ethereum)Невозможно
Агрегирование ключейНужны протоколы многосторонних вычисленийВстроено (MuSig2, BIP-327)
Пороговое подписаниеСложные протоколы (GG18/20, CGGMP)FROST (RFC 9591)
Пакетная проверкаНетДа
Доказательство стойкостиТолько в модели универсальной группы (generic group model)В модели случайного оракула, через задачу дискретного логарифмирования
СтандартыFIPS 186-5, SEC 1BIP-340; EdDSA (RFC 8032) — вариант Schnorr
Где используетсяУстаревшие выходы Bitcoin и SegWit v0, Ethereum, большинство EVM-сетейBitcoin Taproot, Nostr, системы на FROST

Чем они различаются

Обе схемы подписывают с помощью секретного одноразового числа nonce k и соответствующей ему точки R = k·G. ECDSA смешивает хеш z, закрытый ключ d и r (координату x точки R) через обратный по модулю элемент к k. Schnorr вместо этого хеширует обязательство (commitment), открытый ключ и сообщение в вызов (challenge) e и отвечает значением s = k + e·d, а проверяющая сторона сверяет его с равенством s·G = R + e·P.

Из этого единственного проектного решения следует всё остальное:

  • Линейность. Подписи Schnorr складываются. Несколько подписантов могут объединить свои nonce и частичные ответы в одну подпись, которая проходит проверку по сумме их ключей. MuSig2 (BIP-327) делает это за два раунда для подписи n из n; FROST (RFC 9591) реализует пороговую подпись t из n. В ECDSA обращение k нарушает линейность, поэтому пороговому ECDSA нужны тяжёлые многосторонние протоколы; кошельки и кастодиальные сервисы ими пользуются, но в этих протоколах уже находили серьёзные ошибки.
  • Пакетная проверка. Много подписей Schnorr можно проверить вместе быстрее, чем по одной, а это важно при проверке блоков. У ECDSA такого способа ускорения нет.
  • Привязка к ключу. Поскольку в хеш e входит открытый ключ, подпись Schnorr нельзя использовать повторно с другим ключом, а сам ключ нельзя восстановить по подписи. ECDSA допускает восстановление открытого ключа, на которое Ethereum полагается, чтобы экономить байты; со Schnorr ключ нужно передать или знать заранее.
  • Пластичность. В ECDSA проверку проходят и (r, s), и (r, n − s), поэтому Bitcoin требует low-S и строгий DER. BIP-340 фиксирует единственную кодировку, так что третьи лица не могут изменить верную подпись.
  • История. Схема Клауса Шнорра (Claus Schnorr) 1989 года была запатентована, и DSA (а позже ECDSA) разработали так, чтобы обойти этот патент; срок его действия истёк в 2008 году, когда ECDSA уже прочно укоренилась. EdDSA (2011) — детерминированный вариант Schnorr на кривых Эдвардса.

Что Taproot изменил на практике

Выход Taproot привязан к одному 32-байтному ключу x-only. Для траты по ключу (key path) нужна одна 64-байтная подпись Schnorr, независимо от того, принадлежит ли ключ одному человеку или это агрегат MuSig2 из ключей нескольких участников, поэтому трата с мультиподписью 2 из 2 или 3 из 3 выглядит в блокчейне как любая трата с одной подписью. Альтернативные условия траты хранятся в дереве Меркла из скриптов, которое раскрывается только при использовании. Эквивалентная трата с одним ключом в SegWit v0 несёт в witness подпись ECDSA в DER длиной до 72 байт, байт sighash и 33-байтный открытый ключ.

Скрипт ниже, запущенный с @noble/curves 2.3.0 на Node.js 26.10, показывает разницу в размерах для одного и того же секретного ключа.

@noble/curves: ECDSA и Schnorr по BIP-340 с одним ключом secp256k1
import { secp256k1, schnorr } from "@noble/curves/secp256k1.js";
import { sha256 } from "@noble/hashes/sha2.js";
import { utf8ToBytes } from "@noble/hashes/utils.js";

const secretKey = secp256k1.utils.randomSecretKey();
const msg = sha256(utf8ToBytes("pay 0.01 BTC to bc1p..."));

// ECDSA: 33-byte compressed public key, 64-byte compact (r, s) signature.
const ecdsaPub = secp256k1.getPublicKey(secretKey, true);
const ecdsaSig = secp256k1.sign(msg, secretKey, { prehash: false });

// BIP-340 Schnorr: 32-byte x-only public key, 64-byte (R.x, s) signature.
const schnorrPub = schnorr.getPublicKey(secretKey);
const schnorrSig = schnorr.sign(msg, secretKey);

console.log("ECDSA   public key:", ecdsaPub.length, "bytes, signature:", ecdsaSig.length, "bytes, valid:", secp256k1.verify(ecdsaSig, msg, ecdsaPub, { prehash: false }));
console.log("Schnorr public key:", schnorrPub.length, "bytes, signature:", schnorrSig.length, "bytes, valid:", schnorr.verify(schnorrSig, msg, schnorrPub));
Результат
ECDSA   public key: 33 bytes, signature: 64 bytes, valid: true
Schnorr public key: 32 bytes, signature: 64 bytes, valid: true

Компактная форма ECDSA тоже занимает 64 байта, но в скриптах Bitcoin подпись ECDSA передаётся в DER, а Ethereum добавляет байт восстановления; подпись Schnorr попадает в блокчейн в исходном виде.

Общие подводные камни

Ни одна из схем не прощает плохого nonce: если использовать k повторно для двух сообщений или раз за разом допускать утечку нескольких его бит, закрытый ключ раскрывается в обеих схемах. BIP-340 рекомендует выводить nonce из ключа и сообщения, подмешивая 32 байта свежих вспомогательных случайных данных. Многосторонний Schnorr добавляет новое правило: nonce в MuSig2 никогда нельзя выводить детерминированно из одного только сообщения, потому что атакующий, который контролирует другого участника, может добиться, чтобы один и тот же nonce подписал два разных агрегированных вызова. Используйте реализации, прошедшие аудит, например модуль MuSig2 из libsecp256k1, а не собирайте схему из примитивов самостоятельно.

Что когда выбирать

  • Новые кошельки и выходы Bitcoin: траты Taproot по ключу с подписью Schnorr; MuSig2 для ключей нескольких участников, если они могут координировать свои действия, и траты по скрипту (script path) как запасной вариант.
  • Подпись сообщений Bitcoin: BIP-322 для адресов Taproot, поскольку более старый формат BIP-137 знает только ECDSA.
  • Ethereum и EVM-сети: ECDSA, потому что на эту схему рассчитаны транзакции, ecrecover и кошельки; смарт-аккаунты могут проверять подписи других схем в коде контракта.
  • Nostr: Schnorr по BIP-340, как требует NIP-01.
  • Пороговое хранение средств: FROST там, где проверяющие стороны принимают подписи Schnorr или EdDSA; пороговый ECDSA — только там, где целевая сеть требует ECDSA.
  • Системы вне блокчейнов: Ed25519 даёт устройство Schnorr вместе со стандартом (RFC 8032), поддержкой в библиотеках и детерминированными nonce.

Заметки о миграции

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

  1. Обновите программные и аппаратные кошельки до версий, которые поддерживают Taproot (путь деривации BIP-86 m/86'/0'/0') и поля Taproot в PSBT.
  2. Правильно используйте ключи x-only: в ключах BIP-340 нет байта чётности, а сами ключи модифицируются (tweak) обязательством дерева скриптов; не используйте повторно кодировки открытых ключей ECDSA.
  3. Переведите подпись сообщений на BIP-322, чтобы адреса Taproot могли подтверждать владение.
  4. Для мультиподписи выберите между агрегированием ключей MuSig2 для траты по ключу (самый конфиденциальный и дешёвый вариант, но подписание интерактивное) и тратами по скрипту Tapscript с OP_CHECKSIGADD (подписание неинтерактивное, но при использовании политика раскрывается).
  5. Продолжайте проверять ECDSA для старых выходов: правила консенсуса поддерживают обе схемы бессрочно.

Источники

Все сравнения