Curve25519 — это эллиптическая кривая, специально спроектированная для выполнения операций криптографии с высокой скоростью и устойчивостью к множеству известных атак, возникающих в классических реализациях Diffie-Hellman на конечных полях и старых эллиптических кривых. В контексте JavaScript-библиотек TweetNaCl.js и nacl.js она используется через реализацию X25519 — стандартизированного алгоритма обмена ключами на основе скалярного умножения точек на кривой.
Основная идея заключается в том, что вместо работы с большими простыми числами, как в классическом Diffie-Hellman, используются точки на эллиптической кривой и операция скалярного умножения:
k × G = P
где:
k — приватный ключ (скаляр)G — базовая точка кривой Curve25519P — публичный ключОбратная операция (нахождение k по P)
вычислительно неосуществима при корректных параметрах кривой, что
обеспечивает криптографическую стойкость.
Curve25519 определена над конечным полем:
?p, где p = 2²⁵⁵ − 19
Её уравнение в классической форме Эдвардса или Монтгомери специально оптимизировано для быстрых вычислений и защиты от побочных каналов. В библиотечных реализациях, включая TweetNaCl.js, используется форма Монтгомери, позволяющая эффективно выполнять только одну операцию — скалярное умножение.
Ключевые свойства:
Вместо операций с координатами точек используется только координата
u (Montgomery ladder). Это делает алгоритм проще и
безопаснее.
Функция скалярного умножения в TweetNaCl.js:
nacl.scalarMult(n, p)
где:
n — 32-байтовый приватный ключp — публичный ключ другой стороныДля генерации публичного ключа из приватного используется:
nacl.scalarMult.base(n)
Диффи-Хеллман позволяет двум сторонам создать общий секрет через открытый канал без предварительного обмена ключами.
Алгоритм в упрощённом виде:
Сторона A генерирует приватный ключ a
Сторона B генерирует приватный ключ b
Обе стороны вычисляют публичные ключи:
A_pub = a × GB_pub = b × GОбмен публичными ключами
Вычисление общего секрета:
S = a × B_pubS = b × A_pubВ результате:
a × (b × G) = b × (a × G)
что гарантирует совпадение общего секрета.
TweetNaCl.js предоставляет низкоуровневый API, где все ключи
представлены как Uint8Array длиной 32 байта.
import nacl from 'tweetnacl';
import { randomBytes } from 'crypto';
const alicePrivateKey = randomBytes(32);
const alicePublicKey = nacl.scalarMult.base(alicePrivateKey);
const bobPrivateKey = randomBytes(32);
const bobPublicKey = nacl.scalarMult.base(bobPrivateKey);
const aliceSharedSecret = nacl.scalarMult(alicePrivateKey, bobPublicKey);
const bobSharedSecret = nacl.scalarMult(bobPrivateKey, alicePublicKey);
aliceSharedSecret и bobSharedSecret будут
идентичны.
Сам по себе результат X25519 не является ключом для симметричного шифрования в чистом виде. Обычно он проходит через KDF (Key Derivation Function), например HKDF.
Простейшее применение — использование как ключ для
nacl.secretbox:
const nonce = randomBytes(24);
const message = Buffer.from("secret message");
const key = aliceSharedSecret;
const ciphertext = nacl.secretbox(message, nonce, key);
const decrypted = nacl.secretbox.open(ciphertext, nonce, key);
Отсутствие работы с координатами точек
32-байтовые ключи
Монтгомери-лестница
Полная детерминированность операций
Curve25519/X25519 устраняет целый класс проблем классических DH:
Однако остаются требования:
Внутренне scalarMult.base реализует фиксированное
умножение:
publicKey = scalarMult(basePoint, privateKey)
Base point в Curve25519 является фиксированной константой, заданной стандартом, и используется для генерации всей группы публичных ключей.
| Параметр | DH (Finite Fields) | X25519 (Curve25519) |
|---|---|---|
| Математика | модульная арифметика | эллиптические кривые |
| Размер ключа | 2048+ бит | 256 бит |
| Скорость | ниже | выше |
| Безопасность | зависит от параметров | стандартизирована |
| Реализация | сложнее | проще |
Uint8ArraysecretboxCurve25519 в TweetNaCl.js часто используется как базовый слой для:
nacl.box — аутентифицированное шифрование (Curve25519 +
Salsa20 + Poly1305)nacl.sign — Ed25519 (связанный, но другой
алгоритм)nacl.box фактически инкапсулирует X25519:
nacl.box(message, nonce, theirPublicKey, mySecretKey)
внутри происходит:
Все ключи и секреты в TweetNaCl.js имеют фиксированное представление:
Uint8Array как единственный допустимый форматДля хранения часто используют base64 или hex, но только вне криптографических операций.
Curve25519 обеспечивает свойства:
В реальных системах каждый сеанс обычно использует новый ключевой набор, что делает компрометацию одного сеанса независимой от других.