Разгледайте разширени операции за криптография с елиптични криви (ECC) като ECDH, възстановяване на публичен ключ и Schnorr подписи, използвайки native BigInt на JavaScript за подобрена сигурност и производителност.
JavaScript BigInt Криптография с елиптични криви: Задълбочено изследване на разширени операции
В ера, доминирана от цифрово взаимодействие, от децентрализирано финансиране (DeFi) до криптирани съобщения от край до край, силата на нашите криптографски основи никога не е била по-критична. Криптографията с елиптични криви (ECC) е стълб на съвременната криптография с публичен ключ, предлагайки стабилна сигурност с по-малки размери на ключовете в сравнение с нейните предшественици като RSA. В продължение на години извършването на тези сложни математически операции директно в JavaScript беше предизвикателство, често изискващо специализирани библиотеки, които абстрахираха детайлите от ниско ниво или се занимаваха с ограниченията на стандартния числов тип на JavaScript.
Въвеждането на native типа BigInt в JavaScript (ES2020) беше революционен момент. Той освободи разработчиците от ограниченията на 64-битовия floating-point тип Number, предоставяйки механизъм за обработка на произволно големи цели числа. Тази единична функция отключи потенциала за производителни, native и по-прозрачни криптографски реализации директно в JavaScript среди като браузъри и Node.js.
Въпреки че много разработчици са запознати с основите на ECC - генериране на двойки ключове и подписване на съобщения - истинската сила на тази технология се крие в нейните по-разширени операции. Тази статия надхвърля основите, за да изследва сложни криптографски протоколи и техники, които вече са достъпни благодарение на BigInt. Ще се задълбочим в Elliptic Curve Diffie-Hellman (ECDH) за сигурен обмен на ключове, възстановяване на публичен ключ от подписи и мощните, агрегиращи Schnorr подписи.
BigInt революцията в JavaScript криптографията
Преди да се потопим в разширените операции, е важно да разберем защо BigInt е толкова променяща играта за криптографията в JavaScript.
Проблемът с типа `Number`
Традиционният тип Number на JavaScript е IEEE 754 double-precision 64-битово floating-point число. Този формат е отличен за широк спектър от приложения, но има критично ограничение за криптографията: той може безопасно да представя само цели числа до Number.MAX_SAFE_INTEGER, което е 253 - 1.
Криптографските ключове и междинните стойности в ECC са много по-големи. Например, популярната крива secp256k1, използвана от Bitcoin и Ethereum, работи в поле от прости числа, които са 256 бита дълги. Тези числа са с порядъци по-големи от това, което стандартният тип Number може да обработи без загуба на прецизност. Опитът да се извършват изчисления с такива числа ще доведе до неправилни и несигурни резултати.
Въведете `BigInt`: Цели числа с произволна прецизност
BigInt решава този проблем елегантно. Това е отделен числов тип, който предоставя начин за представяне на цели числа с всякакъв размер. Можете да създадете BigInt, като добавите `n` в края на цялочислен литерал или като извикате конструктора BigInt().
Пример:
const aLargeNumber = 9007199254740991n; // Безопасно с BigInt
const anEvenLargerNumber = 115792089237316195423570985008687907853269984665640564039457584007908834671663n; // 256-битово просто число
С BigInt всички стандартни аритметични оператори (+, -, *, /, %, **) работят както се очаква на тези масивни цели числа. Тази възможност е основата, върху която са изградени native JavaScript ECC реализации, позволяващи директно, прецизно и сигурно изчисление на криптографски алгоритми, без да се разчита на външни WebAssembly модули или тромави библиотеки за многокомпонентни числа.
Опреснителен курс по основи на криптографията с елиптични криви
За да оцените разширените операции, нека накратко да прегледаме основните концепции на ECC.
В основата си ECC се основава на алгебричната структура на елиптичните криви над крайни полета. Тези криви са определени от уравнението на Weierstrass:
y2 = x3 + ax + b (mod p)
Където `a` и `b` са константи, определящи формата на кривата, а `p` е голямо просто число, определящо крайното поле.
Ключови концепции
- Точка върху кривата: Двойка координати (x, y), които удовлетворяват уравнението на кривата. Всички наши криптографски операции са по същество "аритметика на точки".
- Базова точка (G): Публично известна, стандартизирана начална точка на кривата.
- Частен ключ (d): Много голямо, криптографски сигурно случайно цяло число. Това е вашата тайна. В контекста на
BigInt, `d` е голям `BigInt`. - Публичен ключ (Q): Точка върху кривата, получена от частния ключ и базовата точка чрез операция, наречена скаларно умножение: Q = d * G. Това означава добавяне на точката G към себе си `d` пъти.
Сигурността на ECC зависи от Проблема за дискретния логаритъм на елиптичната крива (ECDLP). Изчислително е лесно да се изчисли публичният ключ `Q`, като се даде частният ключ `d` и базовата точка `G`. Въпреки това е изчислително невъзможно да се определи частният ключ `d`, като се даде само публичният ключ `Q` и базовата точка `G`.
Разширена операция 1: Обмен на ключове по Elliptic Curve Diffie-Hellman (ECDH)
Едно от най-мощните приложения на ECC е установяването на споделена тайна между две страни по несигурен комуникационен канал. Това се постига с помощта на протокола за обмен на ключове Elliptic Curve Diffie-Hellman (ECDH).
Целта
Представете си двама души, Алис и Боб, които искат да комуникират сигурно. Те трябва да се споразумеят за ключ за симетрично криптиране, който само те знаят, но единственото им средство за комуникация е публичен канал, който подслушвач, Ив, може да наблюдава. ECDH им позволява да изчислят идентична споделена тайна, без никога да я предават директно.
Протоколът стъпка по стъпка
- Генериране на ключ:
- Алис генерира своя частен ключ, `d_A` (голям случаен
BigInt), и съответния си публичен ключ, `Q_A = d_A * G`. - Боб генерира своя частен ключ, `d_B` (друг голям случаен
BigInt), и своя публичен ключ, `Q_B = d_B * G`.
- Алис генерира своя частен ключ, `d_A` (голям случаен
- Обмен на публичен ключ:
- Алис изпраща своя публичен ключ, `Q_A`, на Боб.
- Боб изпраща своя публичен ключ, `Q_B`, на Алис.
- Ив, подслушвачът, може да види както `Q_A`, така и `Q_B`, но не може да извлече частните ключове `d_A` или `d_B` поради ECDLP.
- Изчисляване на споделена тайна:
- Алис взема публичния ключ на Боб `Q_B` и го умножава със собствения си частен ключ `d_A`, за да получи точка S: S = d_A * Q_B.
- Боб взема публичния ключ на Алис `Q_A` и го умножава със собствения си частен ключ `d_B`, за да получи точка S: S = d_B * Q_A.
Магията на комутативността
И Алис, и Боб достигат до точно същата тайна точка `S` на кривата. Това е така, защото скаларното умножение е асоциативно и комутативно:
Изчисление на Алис: S = d_A * Q_B = d_A * (d_B * G)
Изчисление на Боб: S = d_B * Q_A = d_B * (d_A * G)
Тъй като d_A * d_B * G = d_B * d_A * G, и двамата изчисляват един и същ резултат, без никога да разкриват частните си ключове.
От споделена точка до симетричен ключ
Получената споделена тайна `S` е точка на кривата, а не симетричен ключ, подходящ за алгоритми за криптиране като AES. За да се получи ключ, стандартна практика е да се вземе x-координатата на точката `S` и да се прекара през Функция за извличане на ключ (KDF), като например HKDF (HMAC-based Key Derivation Function). KDF взема споделената тайна и по избор сол и друга информация и произвежда криптографски силен ключ с желаната дължина.
Всички основни изчисления - генериране на частни ключове като случайни `BigInt`-и и извършване на скаларното умножение - силно разчитат на `BigInt` аритметиката.
Разширена операция 2: Възстановяване на публичен ключ от подписи
В много системи, особено блокчейни, ефективността и минимизирането на данните са от първостепенно значение. Обикновено, за да се провери подпис, са необходими съобщението, самият подпис и публичният ключ на подписалия. Въпреки това, умно свойство на алгоритъма за цифров подпис с елиптична крива (ECDSA) ви позволява да възстановите публичния ключ директно от съобщението и подписа. Това означава, че публичният ключ не трябва да се предава, спестявайки ценно място.
Как работи (на високо ниво)
ECDSA подписът се състои от два компонента, (`r`, `s`).
- `r` се получава от x-координатата на случайна точка `k * G`.
- `s` се изчислява въз основа на хеша на съобщението (`z`), частния ключ (`d`) и `r`. Формулата е: `s = k_inverse * (z + r * d) mod n`, където `n` е редът на кривата.
Чрез алгебрични манипулации на уравнението за проверка на подписа е възможно да се изведе израз за публичния ключ `Q`. Въпреки това, този процес дава два възможни валидни публични ключа. За да се разреши тази неяснота, малка част от допълнителна информация, наречена recovery ID (често обозначавана като `v` или `recid`), се включва в подписа. Този ID, обикновено 0, 1, 2 или 3, указва кое от възможните решения е правилното и дали y-координатата на ключа е четна или нечетна.
Защо `BigInt` е от съществено значение
Математическите операции, необходими за възстановяване на публичен ключ, са интензивни и включват модулни обратни, умножение и събиране на 256-битови числа. Например, ключова стъпка включва изчисляването на `(r_inverse * (s*k - z)) * G`. Тези операции са точно това, за което е предназначен `BigInt`. Без него извършването на тези изчисления в native JavaScript би било невъзможно без значителна загуба на прецизност и сигурност.
Практическо приложение: Ethereum транзакции
Тази техника е известна с това, че се използва в Ethereum. Подписана транзакция не съдържа директно публичния адрес на подателя. Вместо това, адресът (който е извлечен от публичния ключ) се възстановява от компонентите `v`, `r` и `s` на подписа. Този избор на дизайн спестява 20 байта на всяка отделна транзакция, значителна икономия в мащаба на глобален блокчейн.
Разширена операция 3: Schnorr подписи и агрегиране
Въпреки че ECDSA се използва широко, той има определени недостатъци, включително пластичност на подписите и липса на свойства за агрегиране. Schnorr подписите, друга схема, базирана на ECC, предоставят елегантни решения на тези проблеми и се считат от много криптографи за по-добри.
Основни предимства на Schnorr подписите
- Доказуема сигурност: Те имат по-просто и стабилно доказателство за сигурност в сравнение с ECDSA.
- Непластичност: Невъзможно е трета страна да промени валиден подпис в друг валиден подпис за същото съобщение и ключ.
- Линейност (Суперсилата): Това е най-значителното предимство. Schnorr подписите са линейни, което позволява мощни техники за агрегиране.
Обяснено агрегиране на подписи
Свойството линейност означава, че множество подписи от множество подписали могат да бъдат комбинирани в един, компактен подпис. Това е промяна в играта за схемите с множество подписи (multisig).
Помислете за сценарий, при който транзакция изисква подписи от 3 от 5 участници. С ECDSA ще трябва да включите всичките три отделни подписа в блокчейна, заемайки значително място.
Със Schnorr подписи процесът е много по-ефективен:
- Агрегиране на ключове: 3-те участници могат да комбинират своите индивидуални публични ключове (`Q1`, `Q2`, `Q3`), за да създадат един агрегиран публичен ключ (`Q_agg`).
- Агрегиране на подписи: Чрез протокол за сътрудничество като MuSig2 участниците могат да създадат един агрегиран подпис (`S_agg`), който е валиден за агрегирания публичен ключ `Q_agg`.
Резултатът е транзакция, която изглежда идентична на стандартна транзакция с един подпис отвън. Тя има един публичен ключ и един подпис. Това драстично подобрява ефективността, мащабируемостта и поверителността, тъй като сложните multisig настройки стават неразличими от простите.
Ролята на `BigInt`
Магията на агрегирането се корени в простото събиране на точки на елиптична крива и скаларна аритметика. Създаването на агрегирания ключ включва `Q_agg = Q1 + Q2 + Q3`, а създаването на агрегирания подпис включва добавяне на отделните компоненти на подписа по модул реда на кривата. Всички тези операции - които формират основата на протоколи като MuSig2 - се извършват върху големи цели числа и координати на кривата, което прави `BigInt` незаменим инструмент за прилагане на Schnorr подписи и схеми за агрегиране в JavaScript.
Съображения за изпълнение и най-добри практики за сигурност
Въпреки че `BigInt` ни дава възможност да разбираме и прилагаме тези разширени операции, изграждането на криптография от производствен клас е опасна задача. Ето някои критични съображения.
1. НЕ прилагайте собствена криптография за производство
Тази статия има за цел да образова и илюстрира основните механики. Никога не трябва да прилагате тези криптографски примитиви от нулата за производствено приложение. Използвайте добре проверени, одитирани и рецензирани библиотеки като `noble-curves`. Тези библиотеки са създадени специално от експерти и отчитат множество фини, но критични проблеми със сигурността.
2. Операции с постоянно време и атаки по странични канали
Един от най-опасните капани е атаката по странични канали. Нападател може да анализира нефункционални аспекти на системата - като консумация на енергия или точното време, което отнема една операция - за да изтече информация за тайни ключове. Например, ако умножението с бит '1' в ключа отнема малко повече време, отколкото с бит '0', нападател може да реконструира ключа, като наблюдава вариациите във времето.
Стандартните `BigInt` операции в JavaScript не са с постоянно време. Времето им за изпълнение може да зависи от стойността на операндите. Професионалните криптографски библиотеки използват високоспециализирани алгоритми, за да гарантират, че всички операции, включващи частни ключове, отнемат постоянно време, независимо от стойността на ключа, като по този начин смекчават тази заплаха.
3. Сигурно генериране на случайни числа
Сигурността на всяка криптографска система започва с качеството на нейната случайност. Частните ключове трябва да се генерират с помощта на криптографски сигурен псевдо-генератор на случайни числа (CSPRNG). В JavaScript среди винаги използвайте вградените API:
- Браузър:
crypto.getRandomValues() - Node.js:
crypto.randomBytes()
Никога не използвайте `Math.random()` за криптографски цели, тъй като той не е предназначен да бъде непредсказуем.
4. Валидиране на параметри на домейна и публичен ключ
Когато получавате публичен ключ от външен източник, е важно да го валидирате. Нападател може да предостави злонамерена точка, която всъщност не е върху посочената елиптична крива, което може да доведе до атаки, които разкриват вашия частен ключ по време на ECDH обмен на ключове (напр. Invalid Curve Attacks). Реномираните библиотеки обработват тази валидация автоматично.
Заключение
Пристигането на `BigInt` коренно промени пейзажа на криптографията в рамките на JavaScript екосистемата. Той премести ECC от сферата на непрозрачни, black-box библиотеки към нещо, което може да бъде внедрено и разбрано native, насърчавайки ново ниво на прозрачност и възможности.
Проучихме как тази единична функция позволява разширени и мощни криптографски операции, които са централни за съвременните сигурни системи:
- ECDH обмен на ключове: Основата за установяване на сигурни комуникационни канали.
- Възстановяване на публичен ключ: Техника за повишаване на ефективността, от решаващо значение за мащабируеми системи като блокчейни.
- Schnorr подписи: Схема за подписи от следващо поколение, предлагаща превъзходна ефективност, поверителност и мащабируемост чрез агрегиране.
Като разработчици и архитекти, разбирането на тези разширени концепции вече не е просто академично упражнение. Те се разгръщат в глобални системи днес, от Taproot надстройката в Bitcoin до протоколите за сигурно съобщения, които защитават ежедневните ни разговори. Въпреки че окончателното внедряване винаги трябва да бъде оставено на одитирани, експертно рецензирани библиотеки, задълбочено разбиране на механиката, възможно благодарение на инструменти като `BigInt`, ни дава възможност да изграждаме по-сигурни, ефективни и иновативни приложения за глобална аудитория.