Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
noble-curves — Проверенная и минималистичная реализация эллиптической криптографии на JS. | Kitploit
Инструменты/GitHubGitHub/paulmillr/noble-curves
Инструменты шифрования/дешифрованияАнализ хэшейКриптографияУтилиты и фреймворкиОбучение и Образование
GitHubpaulmillr/noble-curves

noble-curves

Проверенная и минималистичная реализация эллиптической криптографии на JS.

Репозиторий
95810187 дней назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Сайт

noble-curves

Проверенная аудитом и минималистичная реализация эллиптической криптографии на JS.

  • 🔒 Проверена аудитом независимыми фирмами по безопасности
  • 🪶 Минималистична: 15КБ (gzip) secp256k1, неиспользуемый код исключается из ваших сборок
  • 🏎 Быстрая: ручная оптимизация под особенности JS-движков
  • 🔍 Надёжна: кросс-библиотечные / wycheproof тесты гарантируют корректность
  • ➰ Кривые Вейерштрасса, Эдвардса; подписи ECDSA, EdDSA, Schnorr, BLS
  • ✍️ ECDH, hash-to-curve, OPRF, FROST, хеш Poseidon, FFT
  • 🔖 Неотказуемость (SUF-CMA, SBS) и совместимость с консенсусом (ZIP215) в ed25519, ed448
  • 🥈 Обёртка с идентичным API поверх нативного WebCrypto

У кривых есть 5кб родственные проекты secp256k1 и ed25519. У них меньше поверхность атаки, но и меньше возможностей.

Эта библиотека принадлежит noble криптографии

noble криптография — высокобезопасный, легко проверяемый аудитом набор изолированных криптографических библиотек и инструментов.

  • Нулевые или минимальные зависимости
  • Высокочитаемый код на TypeScript / JS
  • Релизы с PGP-подписью и прозрачные сборки NPM
  • Все библиотеки: ciphers, curves, hashes, post-quantum, 5кб secp256k1 / ed25519
  • WASM-версия: awasm-noble
  • Посетите домашнюю страницу для материалов для чтения, документации и приложений, созданных с помощью noble

Использование

npm install @noble/curves

deno add jsr:@noble/curves

Мы поддерживаем все основные платформы и среды выполнения. Для React Native может потребоваться полифилл для getRandomValues. Также доступен автономный файл noble-curves.js.```js // import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size import { secp256k1 } from '@noble/curves/secp256k1.js'; const { secretKey, publicKey } = secp256k1.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = secp256k1.sign(msg, secretKey); const isValid = secp256k1.verify(sig, msg, publicKey);

root@kitploit:~
- [ECDSA, EdDSA, Schnorr signatures](#ecdsa-eddsa-schnorr-signatures)
- [ECDH: Diffie-Hellman shared secrets](#ecdh-diffie-hellman-shared-secrets)
- [webcrypto: friendly wrapper](#webcrypto-friendly-wrapper)
- [BLS signatures, bls12-381, bn254 aka alt\_bn128](#bls-signatures-bls12-381-bn254-aka-alt_bn128)
- [hash-to-curve: hashing to curve points](#hash-to-curve-hashing-to-curve-points)
- [OPRFs](#oprfs) | [FROST threshold signatures](#frost-threshold-signatures)
- [poseidon: Poseidon hash](#poseidon-poseidon-hash) | [fft: Fast Fourier Transform](#fft-fast-fourier-transform) | [utils](#utils-byte-shuffling-conversion)
- Internals: [Point math](#elliptic-curve-point-math) | [modular](#modular-modular-arithmetics--finite-fields) | [custom curves](#weierstrass-custom-weierstrass-curve--ecdsa)
- [Specs](#specs)
- [Security](#security) | [Speed](#speed) | [Upgrading](#upgrading) | [Contributing & testing](#contributing--testing) | [License](#license)

### ECDSA, EdDSA, Schnorr signatures

#### secp256k1, p256, p384, p521, ed25519, ed448, brainpool```js
import { secp256k1, schnorr } from '@noble/curves/secp256k1.js';
import { p256, p384, p521 } from '@noble/curves/nist.js';
import { ed25519 } from '@noble/curves/ed25519.js';
import { ed448 } from '@noble/curves/ed448.js';
import { brainpoolP256r1, brainpoolP384r1, brainpoolP512r1 } from '@noble/curves/misc.js';
for (const curve of [
  secp256k1, schnorr,
  p256, p384, p521,
  ed25519, ed448,
  brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
]) {
  const { secretKey, publicKey } = curve.keygen();
  const msg = new TextEncoder().encode('hello noble');
  const sig = curve.sign(msg, secretKey);
  const isValid = curve.verify(sig, msg, publicKey);
  console.log(curve, secretKey, publicKey, sig, isValid);
}

// Specific private key
import { hexToBytes } from '@noble/curves/utils.js';
const secret2 = hexToBytes('46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236');
const pub2 = secp256k1.getPublicKey(secret2);

Сообщения всегда сначала хешируются: см. подписывание с предварительным хешированием. ECDSA использует детерминированный k, EdDSA следует RFC 8032, Schnorr (только secp256k1) следует BIP 340: см. Спецификации.

Схема подписи MuSig2 и отображение BIP324 ElligatorSwift для secp256k1 доступны в отдельном пакете.

ristretto255, decaf448```ts

import { ristretto255, ristretto255_hasher, ristretto255_oprf } from '@noble/curves/ed25519.js'; import { decaf448, decaf448_hasher, decaf448_oprf } from '@noble/curves/ed448.js';

console.log(ristretto255.Point, decaf448.Point);

root@kitploit:~
Ознакомьтесь с [RFC 9496](https://www.rfc-editor.org/rfc/rfc9496) для получения дополнительной информации о ristretto255 и decaf448.
Ознакомьтесь с отдельной документацией для [Point](#elliptic-curve-point-math), [hasher](#hash-to-curve-hashing-to-curve-points) и [oprf](#oprfs).

#### Предварительно хешированная подпись```js
import { secp256k1 } from '@noble/curves/secp256k1.js';
import { keccak_256 } from '@noble/hashes/sha3.js';
const { secretKey } = secp256k1.keygen();
const msg = new TextEncoder().encode('hello noble');
// prehash: true (default) - hash using secp256k1.hash (sha256)
const sig = secp256k1.sign(msg, secretKey);
// prehash: false - hash using custom hash
const sigKeccak = secp256k1.sign(keccak_256(msg), secretKey, { prehash: false });

По умолчанию (prehash: true) sign() и verify() сначала применяют встроенную хеш-функцию кривой к сообщению: sha256 для secp256k1, sha512 для p521. prehash: false позволяет использовать пользовательскую хеш-функцию (например, secp256k1 + keccak_256). В noble-curves v1 значением по умолчанию было prehash: false.

Восстановление открытых ключей из подписей```js

import { secp256k1 } from '@noble/curves/secp256k1.js'; const { secretKey, publicKey } = secp256k1.keygen(); const msg = new TextEncoder().encode('hello noble'); const sigRec = secp256k1.sign(msg, secretKey, { format: 'recovered' }); const publicKey_ = secp256k1.recoverPublicKey(sigRec, msg); // == publicKey

// recovered sig is compact sig with an extra byte const sigNoRec = secp256k1.sign(msg, secretKey, { format: 'compact' }); // sigNoRec == sigRec.slice(1)

// Signature instance const sigInstance = secp256k1.Signature.fromBytes(sigRec, 'recovered');

root@kitploit:~
Восстановление открытого ключа поддерживается только с ECDSA. Это простая математическая операция:
нет никаких гарантий, что подпись действительно была создана. Поддельная (r, s, h) восстанавливается в
случайный открытый ключ, но найти m, которое привело бы к этому конкретному поддельному h, невозможно.

#### Hedged ECDSA с шумом```js
import { secp256k1 } from '@noble/curves/secp256k1.js';
const { secretKey } = secp256k1.keygen();
const msg = new TextEncoder().encode('hello noble');
// extraEntropy: false - default, hedging disabled
const sigNoisy = secp256k1.sign(msg, secretKey);
// extraEntropy: true - fetch 32 random bytes from CSPRNG
const sigNoisyA = secp256k1.sign(msg, secretKey, { extraEntropy: true });
// extraEntropy: bytes - specific extra entropy
const ent = Uint8Array.from([0xca, 0xfe, 0x01, 0x23]);
const sigNoisy2 = secp256k1.sign(msg, secretKey, { extraEntropy: ent });

По умолчанию подписи ECDSA детерминированы (RFC 6979). Чисто детерминированные подписи уязвимы к атакам по сбоям, поэтому более новые схемы, такие как BIP340 schnorr, включают случайность в генерацию подписи — так называемое хеджирование. extraEntropy включает режим с хеджированием. Для получения дополнительной информации ознакомьтесь со статьёй Deterministic signatures are not your friends.

Дружественность к консенсусу против электронного голосования```js

import { ed25519 } from '@noble/curves/ed25519.js'; const { secretKey, publicKey } = ed25519.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = ed25519.sign(msg, secretKey); // zip215: true const isValid = ed25519.verify(sig, msg, publicKey); // SBS / e-voting / RFC8032 / FIPS 186-5 const isValidRfc = ed25519.verify(sig, msg, publicKey, { zip215: false });

root@kitploit:~
* `zip215: true` (по умолчанию) использует более мягкие, [дружественные к консенсусу](https://hdevalence.ca/blog/2020-10-04-its-25519am) правила верификации, определённые в [ZIP215](https://zips.z.cash/zip-0215).
* `zip215: false` применяет строгую верификацию RFC 8032 / FIPS 186-5 и добавляет основанное на SBS
  неотрекаемость, что полезно для подписания контрактов, электронного голосования и блокчейнов.

Оба режима обладают SUF-CMA (strong unforgeability under chosen message attacks);
большинство других библиотек не имеют ни SUF-CMA, ни SBS.
См. [Taming the many EdDSAs](https://eprint.iacr.org/2020/1244) для получения дополнительной информации.

### ECDH: общие секреты Диффи-Хеллмана```js
import { x25519 } from '@noble/curves/ed25519.js';
const alice = x25519.keygen();
const bob = x25519.keygen();
const sharedKey = x25519.getSharedSecret(alice.secretKey, bob.publicKey);
// Same API: secp256k1, p256, p384, p521, x448

// converting ed25519 keys to x25519
import { ed25519 } from '@noble/curves/ed25519.js';
const alice2 = ed25519.keygen();
const bob2 = ed25519.keygen();
const aliceSecX = ed25519.utils.toMontgomerySecret(alice2.secretKey);
const bobPubX = ed25519.utils.toMontgomery(bob2.publicKey);
const sharedKey2 = x25519.getSharedSecret(aliceSecX, bobPubX);

Мы предоставляем ECDH для всех кривых Вейерштрасса и для 2 кривых Монтгомери X25519 (Curve25519) и X448 (Curve448), соответствующих RFC 7748.

В кривых Вейерштрасса общие секреты:

  • Включают байты чётности y: используйте key.slice(1), чтобы их отбросить
  • Не хешируются: используйте хеширование или KDF поверх, например sha256(shared) или hkdf(shared)

webcrypto: удобная обёртка```js

import { ed25519, x25519 } from '@noble/curves/webcrypto.js';

// signatures: p256, p384, p521, ed25519, ed448 const keys = await ed25519.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = await ed25519.sign(msg, keys.secretKey); const isValid = await ed25519.verify(sig, msg, keys.publicKey);

// ECDH: p256, p384, p521, x25519, x448 const alice = await x25519.keygen(); const bob = await x25519.keygen(); const shared = await x25519.getSharedSecret(alice.secretKey, bob.publicKey);

// key conversion between noble (raw) and webcrypto (pkcs8 / spki) formats import { p256 as p256n } from '@noble/curves/nist.js'; import { p256 } from '@noble/curves/webcrypto.js'; const nobleKeys = p256n.keygen(); const secretKeyPkcs8 = await p256.utils.convertSecretKey(nobleKeys.secretKey, 'raw', 'pkcs8'); const publicKeySpki = await p256.utils.convertPublicKey(nobleKeys.publicKey, 'raw', 'spki');

root@kitploit:~
Тонкая обёртка над встроенным WebCrypto, повторяющая API noble. Методы всегда асинхронны;
поддержка во время выполнения различается — проверяйте с помощью `await curve.isSupported()`.
Ознакомьтесь с [micro-key-producer](https://github.com/paulmillr/micro-key-producer) для
чистых JS-утилит преобразования ключей.

### Подписи BLS, bls12-381, bn254 aka alt_bn128```ts
import { bls12_381 } from '@noble/curves/bls12-381.js';

// G1 pubkeys, G2 sigs
const blsl = bls12_381.longSignatures;
const { secretKey, publicKey } = blsl.keygen();
const msg = new TextEncoder().encode('hello noble');
const msgp = blsl.hash(msg); // hash to point, default DST
const msgpd = blsl.hash(msg, 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_'); // custom DST (Ethereum)
const signature = blsl.sign(msgp, secretKey);
const isValid = blsl.verify(signature, msgp, publicKey);

// G1 sigs, G2 pubkeys: identical API
const blss = bls12_381.shortSignatures;

// Aggregation
const aggregatedKey = blsl.aggregatePublicKeys([
  blsl.getPublicKey(bls12_381.utils.randomSecretKey()),
  blsl.getPublicKey(bls12_381.utils.randomSecretKey()),
]);
// const aggregatedSig = blsl.aggregateSignatures(sigs)

// Pairings: bls12_381.pairing(PointG1, PointG2)
// Fields: bls12_381.fields.Fp, Fp2, Fp12, Fr

Пример использования см. в реализации предкомпилированных контрактов BLS EVM.

API BN254 повторяет bls12-381. Ранее эта кривая называлась alt_bn128. Реализация совместима с EIP-196 и EIP-197: см. реализацию предкомпилированных контрактов bn254 EVM. Точки bn254 не реализуют toBytes, поскольку не существует стандарта сериализации: реализации расходятся в порядке байтов, флагах и порядке мнимой части G2. Инициализируйте точки из bigint.

hash-to-curve: хеширование в точки кривой```ts

import { secp256k1_hasher } from '@noble/curves/secp256k1.js';

const msg = Uint8Array.from([0xca, 0xfe, 0x01, 0x23]); const point = secp256k1_hasher.hashToCurve(msg); const pointDst = secp256k1_hasher.hashToCurve(msg, { DST: 'hello noble' }); const pointNu = secp256k1_hasher.encodeToCurve(msg); const scalar = secp256k1_hasher.hashToScalar(msg);

// Same API: p256_hasher, p384_hasher, p521_hasher (nist.js), // ed25519_hasher, ristretto255_hasher (ed25519.js), ed448_hasher, decaf448_hasher (ed448.js), // bls12_381.G1, bls12_381.G2. // ristretto255 & decaf448 also provide deriveToCurve.

// abstract methods import { expand_message_xmd, expand_message_xof, hash_to_field } from '@noble/curves/abstract/hash-to-curve.js';

root@kitploit:~
Модуль позволяет хешировать произвольные строки в точки эллиптической кривой. Реализует [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
Пространства имён `_hasher` отделены от кривых для tree-shaking:
пользователи, которым не нужен hash-to-curve, не будут иметь его в своих сборках.

### OPRFs```js
import { p256_oprf, p384_oprf, p521_oprf } from '@noble/curves/nist.js';
import { ristretto255_oprf } from '@noble/curves/ed25519.js';
import { decaf448_oprf } from '@noble/curves/ed448.js';

Мы предоставляем OPRF (oblivious pseudorandom functions), соответствующие RFC 9497.

OPRF позволяет интерактивно создавать Output = PRF(Input, serverSecretKey):

  • Сервер не может вычислить Output самостоятельно: он не знает Input
  • Клиент не может вычислить Output самостоятельно: он не знает server secretKey
  • Злоумышленник, перехвативший коммуникацию, не может восстановить Input/Output/serverSecretKey и не может связать Input с некоторым значением.

Пороговые подписи FROST

FROST реализует пороговую подпись Schnorr согласно RFC 9591. С точки зрения приложения это похоже на multisig: любые min из max участников могут совместно создать одну подпись Schnorr под общим открытым ключом. Поддерживаемые наборы шифров: p256_FROST, ed25519_FROST, ed448_FROST, ristretto255_FROST, secp256k1_FROST и schnorr_FROST (совместимый с Taproot secp256k1). Подписание состоит из двух раундов: выбранные подписанты сначала фиксируют обязательства, затем создают доли подписи.```js import { p256_FROST } from '@noble/curves/nist.js';

const signers = { min: 2, max: 3 }; const alice = p256_FROST.Identifier.derive('[email protected]'); const bob = p256_FROST.Identifier.derive('[email protected]'); const carol = p256_FROST.Identifier.derive('[email protected]'); // trusted dealer const deal = p256_FROST.trustedDealer(signers, [alice, bob, carol]); for (const id of [alice, bob, carol]) p256_FROST.validateSecret(deal.secretShares[id], deal.public);

const msg = new TextEncoder().encode('hello threshold'); // round 1: selected signers commit const aliceRound1 = p256_FROST.commit(deal.secretShares[alice]); const bobRound1 = p256_FROST.commit(deal.secretShares[bob]); const commitmentList = [aliceRound1.commitments, bobRound1.commitments]; // round 2: signers produce signature shares const sigShares = { [alice]: https://raw.githubusercontent.com/paulmillr/noble-curves/main/p256_FROST.signShare( deal.secretShares[alice], deal.public, aliceRound1.nonces, commitmentList, msg ), [bob]: https://raw.githubusercontent.com/paulmillr/noble-curves/main/p256_FROST.signShare( deal.secretShares[bob], deal.public, bobRound1.nonces, commitmentList, msg ), }; const sig = p256_FROST.aggregate(deal.public, commitmentList, msg, sigShares); const isValid = p256_FROST.verify(sig, msg, deal.public.commitments[0]);

root@kitploit:~
Генерация ключей может быть выполнена с помощью доверенного дилера (см. выше) или с помощью DKG (распределённая генерация ключей).
DKG состоит из трёх раундов: участники фиксируют обязательства по генерации ключей, обмениваются приватными долями,
затем выводят итоговые ключи участников — см. использование `DKG.round1` / `round2` / `round3` в
[тестах](https://github.com/paulmillr/noble-curves/blob/main/test/rfc9591-frost.test.ts).
Библиотека реализует криптографические шаги, а не окружающий протокол приложения:
вызывающей стороне по-прежнему необходимы аутентифицированная связь, координация, повторные попытки, управление сессиями и политика.

### poseidon: хеш Poseidon

Реализует [Poseidon](https://www.poseidon-hash.info) — ZK-дружественный хеш:
перестановку и губку.

Существует множество вариантов poseidon с разными константами.
Мы их не предоставляем: их следует конструировать вручную.
Ознакомьтесь с пакетом [scure-starknet](https://github.com/paulmillr/scure-starknet) для надлежащего примера.```ts
import { bn254 } from '@noble/curves/bn254.js';
import { grainGenConstants, poseidon, poseidonSponge } from '@noble/curves/abstract/poseidon.js';

const rate = 2;
const capacity = 1;
const Fp = bn254.fields.Fr;
const { mds, roundConstants } = grainGenConstants({
  Fp,
  t: rate + capacity,
  roundsFull: 8,
  roundsPartial: 31,
});
const opts = {
  Fp,
  rate,
  capacity,
  sboxPower: 17,
  mds,
  roundConstants,
  roundsFull: 8,
  roundsPartial: 31,
};
const permutation = poseidon({ ...opts, t: rate + capacity });
const sponge = poseidonSponge(opts); // use carefully, not specced

fft: Быстрое преобразование Фурье```ts

import * as fft from '@noble/curves/abstract/fft.js'; import { bls12_381 } from '@noble/curves/bls12-381.js'; const Fr = bls12_381.fields.Fr; const roots = fft.rootsOfUnity(Fr, 7n); const fftFr = fft.FFT(roots, Fr);

root@kitploit:~
NTT / FFT (быстрое преобразование Фурье) над конечными полями.

### utils: перестановка байтов, преобразование```ts
import { bytesToHex, concatBytes, equalBytes, hexToBytes } from '@noble/curves/utils.js';

bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23]));
hexToBytes('cafe0123');
concatBytes(Uint8Array.from([0xca, 0xfe]), Uint8Array.from([0x01, 0x23]));
equalBytes(Uint8Array.of(0xca), Uint8Array.of(0xca));

Внутреннее устройство

Математика точек эллиптических кривых```js

import { secp256k1 } from '@noble/curves/secp256k1.js'; const { Point } = secp256k1; const { BASE, ZERO, Fp, Fn } = Point; const p = BASE.multiply(2n);

// Math const p1 = p.add(p); const p2 = p.double(); const p3 = p.subtract(p); const p4 = p.negate(); const p5 = p.multiply(451n);

// MSM (multi-scalar multiplication) import { pippenger } from '@noble/curves/abstract/curve.js'; const pa = [BASE, BASE.multiply(2n), BASE.multiply(4n), BASE.multiply(8n)]; const p6 = pippenger(Point, pa, [3n, 5n, 7n, 11n]); // == BASE.multiply(129n)

// Cofactor const pcl = p.clearCofactor(); const isTorsionFree = p.isTorsionFree();

// Conversions const bytes = p.toBytes(); const p_ = Point.fromBytes(bytes); const { x, y } = p.toAffine(); const p__ = Point.fromAffine({ x, y });

root@kitploit:~
Каждая кривая предоставляет свой класс Point: secp256k1, schnorr, p256, p384, p521, ed25519, ed448,
ristretto255, decaf448, bls12_381.G1 / G2, bn254.G1, jubjub, babyjubjub.
Точки Вейерштрасса используют проективные (однородные) координаты `new Point(X, Y, Z)`,
точки Эдвардса используют расширенные координаты `new Point(X, Y, Z, T)`; обе с x=X/Z, y=Y/Z.

#### modular: Модульная арифметика и конечные поля```js
import { mod, invert, Field } from '@noble/curves/abstract/modular.js';

// Finite Field utils
const fp = Field(2n ** 255n - 19n); // Finite field over 2^255-19
fp.mul(591n, 932n); // multiplication
fp.pow(481n, 11024858120n); // exponentiation
fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17)
fp.inv(5n); // modular inverse
fp.sqrt(4n); // square root

// Non-Field generic utils are also available
mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse

Все арифметические операции выполняются с использованием JS bigint над конечными полями, которые определяются из подмодуля modular.

Операции над полем не являются константными по времени: см. безопасность. Этот факт в основном несущественен, но важный метод, который следует иметь в виду, — pow, который может раскрывать биты экспоненты при наивном использовании.

weierstrass: пользовательская кривая Вейерштрасса и ECDSA```js

import { weierstrass, ecdsa } from '@noble/curves/abstract/weierstrass.js'; import { sha256 } from '@noble/hashes/sha2.js'; // NIST secp192r1 aka p192. https://www.secg.org/sec2-v2.pdf const p192_CURVE = { p: 0xfffffffffffffffffffffffffffffffeffffffffffffffffn, n: 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n, h: 1n, a: 0xfffffffffffffffffffffffffffffffefffffffffffffffcn, b: 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n, Gx: 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012n, Gy: 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n, }; const p192_Point = weierstrass(p192_CURVE); const p192 = ecdsa(p192_Point, sha256);

const keys = p192.keygen(); const msg = new TextEncoder().encode('custom curve'); const sig = p192.sign(msg, keys.secretKey); const isValid = p192.verify(sig, msg, keys.publicKey);

root@kitploit:~
Формула короткой кривой Вейерштрасса: `y² = x³ + ax + b`. `weierstrass`
принимает аргументы `a`, `b`, характеристику поля `p`, порядок кривой `n`,
кофактор `h` и координаты `Gx`, `Gy` порождающей точки, и возвращает класс Point.
`ecdsa` объединяет класс Point с хеш-функцией в схему подписи.

#### edwards: Пользовательская кривая Эдвардса```js
import { edwards } from '@noble/curves/abstract/edwards.js';
const ed25519_CURVE = {
  p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
  n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
  h: 8n,
  a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
  d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
  Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
  Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n,
};
const ed25519_Point = edwards(ed25519_CURVE);

Формула скрученной кривой Эдвардса: ax² + y² = 1 + dx²y². Необходимо указать a, d, характеристику поля p, порядок кривой n (иногда обозначается как L), кофактор h и координаты Gx, Gy порождающей точки.

Спецификации

  • ECDSA: детерминированный k из RFC 6979, хеджированные подписи из черновика cfrg-det-sigs-with-noise
  • EdDSA: RFC 8032, FIPS 186-5; дружественная к консенсусу верификация: ZIP215
  • Подписи Schnorr: BIP 340
  • X25519, X448 ECDH: RFC 7748
  • ristretto255, decaf448: RFC 9496
  • hash-to-curve: RFC 9380
  • OPRF: RFC 9497
  • FROST: RFC 9591
  • bn254: EIP-196, EIP-197
  • Poseidon: сайт

Безопасность

Библиотека прошла аудит:

  • в версии 2.3.0, в августе 2026, компанией Trail of Bits, в сотрудничестве с OpenAI
    • Проведён в рамках инициативы "Patch the Planet"
    • Область: всё
  • в версии 1.6.0, в сентябре 2024, независимо, компанией Cure53
    • PDF: сайт, в репозитории
    • Область: ed25519, ed448, их дополнения, bls12-381, bn254, hash-to-curve, низкоуровневые примитивы bls, tower, edwards, montgomery.
    • Аудит был профинансирован OpenSats
  • в версии 1.2.0, в сентябре 2023, независимо, компанией Kudelski Security
    • PDF: в репозитории
    • Область: scure-starknet и связанные с ним абстрактные модули noble-curves: curve, modular, poseidon, weierstrass
    • Аудит был профинансирован Starkware
  • в версии 0.7.3, в феврале 2023, независимо, компанией Trail of Bits
    • PDF: сайт, в репозитории
    • Область: абстрактные модули , , , , , и модули верхнего уровня и

В апреле 2026 мы начали регулярные самоаудиты с использованием ИИ.

Библиотека тестируется на основе свойств, кросс-библиотечных и векторов Wycheproof, а также проходит фаззинг в GitHub CI.

Если вы заметите что-то необычное: исследуйте и сообщите.

Константное время выполнения

Мы стремимся к алгоритмическому константному времени. JIT-компилятор и сборщик мусора делают "константное время" чрезвычайно труднодостижимым для защиты от атак по времени в скриптовом языке. Это означает, что любая другая JS-библиотека не может обладать константным временем выполнения. Даже статически типизированный Rust, язык без сборщика мусора, затрудняет достижение константного времени в некоторых случаях. Если ваша цель — абсолютная безопасность, не используйте никакие JS-библиотеки — включая привязки к нативным. Используйте низкоуровневые библиотеки и языки.

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

  • Фиксированная последовательность операций: multiply() использует таблицы со знаковым фиксированным окном и сканирование таблиц, не зависящее от данных — количество и порядок операций над точками не зависят от значения скаляра.
  • Ослепление скаляра: секретные скаляры дополнительно маскируются как s + r·n со случайным 128-битным r перед умножением. Это применяется ко всем умножениям на кривых с кофактором 1 (p256, p384, p521, secp256k1) и к умножениям на базовую точку везде.
  • Статистическая валидация: тестовый стенд в стиле dudect с t-критерием Уэлча (benchmark/ct.ts) сравнивает время выполнения для различных классов скаляров (разреженные против плотных, младшие против старших битов, близкие к порядку, битовые шаблоны). Умножение на базовую точку не показывает различимого времени ни на одной кривой, а умножение на случайную точку не показывает его на кривых Вейерштрасса (макс. |t| ≤ 2.8 при 1000 выборках; порог 4.5).

Известное ограничение: на кривых Эдвардса с кофактором (ed25519, ed448) умножение небазовой точки на секретный скаляр не ослепляется. Тот же стенд надёжно это обнаруживает. Подписание EdDSA не затронуто (оно умножает только ослеплённую базовую точку), а X25519/X448 используют отдельную реализацию лестницы Монтгомери (также не затронуто). Это важно для протоколов, которые умножают произвольные точки Эдвардса/Ristretto на долгоживущие секретные скаляры; предпочитайте скаляры, полноразмерные по построению. Отметим, что обнаружимость в изолированном стенде не означает практической эксплуатируемости: мы пытались извлечь скаляр в реалистичной кросс-тенантной / браузерной среде и не смогли восстановить скаляры Эдвардса даже при 100 000 выборках времени.

Дамп памяти

Используйте низкоуровневые языки вместо JS / WASM, если ваша цель — абсолютная безопасность.

Библиотека в основном использует Uint8Array и bigint.

  • Uint8Array имеет .fill(0), который предписывает заполнить содержимое нулями, но в JS нет никаких гарантий
  • bigint неизменяемы и не имеют метода для затирания содержимого: пользователю нужно ждать следующего цикла сборки мусора
  • hex-строки также неизменяемы: нет способа затереть их
  • await fn() запишет все внутренние переменные в память. С асинхронными функциями нет гарантий, когда блок кода будет выполнен. Это означает, что у злоумышленника может быть достаточно времени, чтобы прочитать данные из памяти.

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

Безопасность цепочки поставок

  • Коммиты подписываются PGP-ключами для предотвращения подделки. Обязательно проверяйте подписи коммитов
  • Релизы выпускаются прозрачно через GitHub CI без токенов и Trusted Publishing. Обязательно проверяйте журналы происхождения на подлинность.
  • Редкие релизы практикуются для минимизации необходимости повторных аудитов конечными пользователями.
  • Зависимости минимизированы и строго зафиксированы для снижения рисков цепочки поставок.
    • Мы используем как можно меньше зависимостей.
    • Диапазоны версий заблокированы, а изменения проверяются с помощью npm-diff.
  • Dev-зависимости исключены из установок конечных пользователей; они используются только для разработки и сборки.

Для этого пакета существует 1 зависимость; и несколько dev-зависимостей:

  • noble-hashes предоставляет функциональность криптографического хеширования
  • jsbt используется для бенчмаркинга / тестирования / инструментов сборки и разработан тем же автором
  • prettier, fast-check и typescript используются для качества кода / генерации тестов / компиляции ts

Случайность

Мы полагаемся на встроенный crypto.getRandomValues, который считается криптографически стойким PRNG.

У браузеров в прошлом были слабости — и могут появиться снова — но реализация CSPRNG в пользовательском пространстве ещё хуже, поскольку нет надёжного источника высококачественной энтропии в пользовательском пространстве.

Квантовые компьютеры

Криптографически значимый квантовый компьютер, если будет построен, позволит взломать криптографию на эллиптических кривых (как ECDSA / EdDSA, так и ECDH) с помощью алгоритма Шора.

Рассмотрите переход на более новые / гибридные алгоритмы, такие как SPHINCS+. Они доступны в noble-post-quantum.

NIST запрещает классическую криптографию (RSA, DSA, ECDSA, ECDH) после 2035 года. Австралийское ASD запрещает её после 2030 года.

Скорость```sh

npm run benchmark

root@kitploit:~
noble-curves тратит 10+ мс на генерацию 20MB+ предвычислений базовой точки.
Это делается **один раз** на кривую.

Генерация откладывается до вызова любого метода (pubkey, sign, verify).
Пользователь может принудительно запустить генерацию предвычислений, вручную вызвав `Point.BASE.precompute(windowSize, false)`.
Ознакомьтесь с исходным кодом.

Результаты бенчмарка на Apple M4:```
# algorithm=getPublicKey
ed25519                    7,299 ops/sec · 137 μs/op
secp256k1                  4,872 ops/sec · 205 μs/op · -1.5x
p256                       4,724 ops/sec · 212 μs/op · -1.5x
bls12_381 (long, G2 sig)   3,466 ops/sec · 288 μs/op · -2.1x
ed448                      3,224 ops/sec · 310 μs/op · -2.3x
p384                       2,185 ops/sec · 458 μs/op · -3.3x
p521                       1,221 ops/sec · 819 μs/op · -6x
bls12_381 (short, G1 sig)  1,070 ops/sec · 934 μs/op · -6.8x

# algorithm=sign
secp256k1                  4,217 ops/sec · 237 μs/op
p256                       4,116 ops/sec · 243 μs/op · ≈
ed25519                    3,536 ops/sec · 283 μs/op · -1.2x
p384                       1,992 ops/sec · 502 μs/op · -2.1x
ed448                      1,577 ops/sec · 634 μs/op · -2.7x
p521                       1,131 ops/sec · 884 μs/op · -3.7x
bls12_381 (short, G1 sig)  417 ops/sec · 2.39 ms/op · -10x
bls12_381 (long, G2 sig)   112 ops/sec · 8.88 ms/op · -37x

# algorithm=verify
ed25519                    1,504 ops/sec · 665 μs/op
secp256k1                  1,352 ops/sec · 739 μs/op · -1.1x
p256                       917 ops/sec · 1.09 ms/op · -1.6x
ed448                      546 ops/sec · 1.83 ms/op · -2.8x
p384                       381 ops/sec · 2.62 ms/op · -3.9x
p521                       187 ops/sec · 5.34 ms/op · -8x
bls12_381 (short, G1 sig)  100 ops/sec · 9.98 ms/op · -15x
bls12_381 (long, G2 sig)   77 ops/sec · 12.9 ms/op · -19x

# algorithm=getSharedSecret
ed25519                    1,695 ops/sec · 590 μs/op
secp256k1                  763 ops/sec · 1.31 ms/op · -2.2x
p256                       737 ops/sec · 1.36 ms/op · -2.3x
ed448                      599 ops/sec · 1.67 ms/op · -2.8x
p384                       326 ops/sec · 3.06 ms/op · -5.2x
p521                       176 ops/sec · 5.68 ms/op · -9.6x

Обновление

Поддерживаемые версии node.js:

  • v2 (2025-08): v20.19+ (только ESM)
  • v1 (2023-04): v14.21+ (ESM и CJS)

С v1 на v2

v2 значительно упрощает внутреннее устройство, повышает безопасность, уменьшает размер бандла и прокладывает путь в будущее. Мы постарались сделать v2 настолько обратно совместимой, насколько это возможно.

Путь обновления: сначала обновитесь до curves v1.9.x. Исправьте предупреждения об устаревании, затем переходите на v2.

Модули:

  • Пакет теперь только ESM. ESM наконец можно загружать из common.js на node v20.19+
  • Теперь требуется расширение .js: @noble/curves/ed25519 => @noble/curves/ed25519.js. Это обеспечивает нативное использование в браузере, без транспайлеров
  • p256, p384, p521 были перемещены в nist; jubjub был перемещён в misc
  • Кривые pasta и bn254_weierstrass (НЕ bn254 на основе спариваний) были удалены

Новые возможности:

  • webcrypto: удобная обёртка в стиле noble над встроенным WebCrypto
  • oprf: OPRF по RFC 9497 (oblivious pseudorandom functions) для p256, p384, p521, ristretto255 и decaf448
  • weierstrass, edwards: новые методы isValidSecretKey, isValidPublicKey
  • misc: кривые Brainpool brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • Значительно улучшенные, более информативные сообщения об ошибках

Критические изменения:

  • Большинство методов теперь принимают только Uint8Array; строковые hex-входные данные запрещены. Это упрощает рассуждения, повышает безопасность и снижает пластичность. Point.fromHex теперь принимает только строки: используйте Point.fromBytes для Uint8Array
  • ECDSA (secp256k1, p256, p384...) sign & verify:
    • Предварительно хешированные сообщения: методы теперь ожидают нехешированное сообщение вместо messageHash. Старое поведение: {prehash: false}
    • lowS-подписи по умолчанию. secp256k1 не затронут: он использовал lowS с самого начала. Старое поведение: {lowS: false}
    • Подписи Uint8Array (формат: 'compact') по умолчанию
    • verify: формат der должен быть явно указан в {format: 'der'}. Это снижает пластичность
    • verify: экземпляры Signature запрещены: сначала вызовите signature.toBytes()
  • Подписи BLS (bls12-381, bn254):
    • getPublicKey, sign, verify, signShortSignature и т.д. были перемещены в два новых пространства имён: longSignatures (публичные ключи G1, подписи G2) и shortSignatures (подписи G1, публичные ключи G2)
    • verifyBatch теперь ожидает массив входных данных {message: ..., publicKey: ...}[]

Переименования (в curves v1.9 старые имена помечены как устаревшие):

  • Точки
    • ExtendedPoint, ProjectivePoint => Point
    • Координаты точки px/ex, py/ey, pz/ez, et => X, Y, Z, T
    • toRawBytes, fromRawBytes => toBytes, fromBytes
    • Point.normalizeZ, Point.msm => отдельные методы в подмодуле abstract/curve.js
    • Point.fromPrivateKey(key) => Point.BASE.multiply(Point.Fn.fromBytes(key))
    • Свойство CURVE со всякой всячиной => Point.CURVE(), которое предоставляет только параметры кривой
    • RistrettoPoint => ristretto255.Point, DecafPoint => decaf448.Point
  • Подписи ECDSA
    • toCompactRawBytes, toDERRawBytes => toBytes('compact'), toBytes('der')
    • toCompactHex, toDERHex => toHex('compact'), toHex('der')
    • fromCompact, fromDER => fromBytes(bytes, format), fromHex(hex, format)
  • utils
    • randomPrivateKey => randomSecretKey
    • normPrivateKeyToScalar => Point.Fn.fromBytes
    • utils.precompute, Point#_setWindowSize => Point#precompute
    • edwardsToMontgomery, edwardsToMontgomeryPriv => utils.toMontgomery, utils.toMontgomerySecret
  • Методы hash-to-curve для конкретных кривых => *curve*_hasher. Пример: secp256k1.hashToCurve => secp256k1_hasher.hashToCurve()
  • Масштабные переименования и улучшения типов

Удалённые возможности: Point#multiplyAndAddUnsafe, Point#hasEvenY, Field.MASK

Участие в разработке и тестирование

npm install && npm run build && npm test соберёт код и запустит тесты.

Есть дополнительные наборы тестов: медленные тесты с большими скалярами / большими кривыми npm run test:slow, и стенд для проверки постоянства времени выполнения npm run benchmark:ct.

См. paulmillr.com/noble для полезных ресурсов, статей, документации и демо, связанных с библиотекой.

Лицензия

The MIT License (MIT)

Copyright (c) 2022 Paul Miller (https://paulmillr.com)

См. файл LICENSE.

Скачать инструмент
curve
hash-to-curve
modular
poseidon
utils
weierstrass
_shortw_utils
secp256k1
  • Аудит был профинансирован Ryan Shea
  • Пользовательские кривые:
    • Создание кривых было значительно упрощено и разделено на создание точек и создание генератора подписей: weierstrass() + ecdsa() / edwards() + eddsa(). weierstrass / edwards ожидают упрощённые параметры кривой (Fp стал p); ecdsa / eddsa ожидают класс Point и хеш
    • pippenger: удалён ненужный аргумент Fn
    • Field#fromBytes() теперь проверяет, что элементы находятся в диапазоне 0..order-1