Перейти к содержимому
ecdsa.com
C · OpenSSL · Командная строка

OpenSSL

OpenSSL — библиотека на C и инструмент командной строки, на которых держится большая часть TLS в интернете и немалая доля подписей: формат DER, случайные nonce и RFC 6979 по запросу, все распространённые кривые, а начиная с 3.5 — ML-KEM, ML-DSA и SLH-DSA.
Лицензия
Apache-2.0
Проверенная версия
3.5.9 ·
Исходный код
github.com/openssl/openssl
Документация
docs.openssl.org/3.5/

Совместимость вкратце

ECDSAEdDSAПостквантовая криптография

Кривые ECDSA
P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1
EdDSA
Ed25519Ed448
Форматы закрытых ключей
pkcs8-pempkcs8-derencrypted-pkcs8sec1-pemsec1-der

OpenSSL предоставляет libcrypto и libssl для C, а через привязки — для Node.js, Python, PHP и Ruby, а также команду openssl, с которой большинство знакомится в первую очередь. Факты на этой странице проверены на пакете дистрибутива Alpine 3.24.2 с OpenSSL 3.5.9 (ветка 3.5 с долгосрочной поддержкой); новейшими релизами проекта на тот момент были 3.6.5 и 4.0.3, поэтому в них поведение может отличаться.

EVP_DigestSign и openssl dgst -sign выдают подписи ECDSA в ASN.1 DER — от 70 до 72 байт на P-256. Nonce случайны, если не задать параметр nonce-type равным 1 (OpenSSL 3.2+); с этим значением воспроизвёлся тестовый вектор RFC 6979 для P-256. В командной строке этот параметр доступен только через pkeyutl, как показывает пример. Значение s не нормализуется, а проверка принимает high-S. EVP_PKEY_sign подписывает дайджест, который вы вычислили сами.

Некорректные входные данные дают ошибку, а не отрицательный результат: EVP_DigestVerify вернула -1 для 64-байтовой подписи raw r‖s, и CLI тоже сообщает об ошибке. Команда openssl dgst -verify вывела Verified OK для правильной подписи, Verification failure для верной подписи других данных и Error verifying data для 64 байт не в формате DER, поэтому в 3.5.9 проблему с форматом можно отличить от подделки по тексту сообщения. Преобразуйте подписи raw конвертером DER ⇄ raw или поручите конструктору команд OpenSSL собрать правильный вызов.

Поддерживаются кривые от P-224 до P-521, secp256k1 и кривые Brainpool r1, а также Ed25519 и Ed448. Начиная с 3.5 провайдер по умолчанию реализует также ML-KEM, ML-DSA и SLH-DSA и гибридную группу TLS X25519MLKEM768. Закрытые ключи бывают в форматах PKCS#8 (обычном или зашифрованном) и SEC1, открытые ключи — в SPKI или в сертификате: genpkey записывает -----BEGIN PRIVATE KEY-----, устаревшая команда openssl ec — -----BEGIN EC PRIVATE KEY-----; файл с меткой EC всегда содержит закрытый ключ.

Большинство сообщений об ошибках, которые ищут разработчики, возникают при загрузке ключей — no start line, header too long, unsupported от декодера — и разобраны на страницах ошибок по ссылкам.

Факты и проверки, на которых они основаны

Ничего из приведённого ниже не скопировано из документации. 20 октября 2026 г. проверка content/libraries/verify/openssl/run.sh запустила OpenSSL 3.5.9 в образе контейнера alpine:3.24.2; содержимое страницы должно совпадать с выводом проверки, а у каждого факта приведены соответствующие строки вывода.

  • Кодировка подписи ECDSA

    der

    EVP_DigestSign и openssl dgst -sign выдают ASN.1 DER.

    Что записала проверка
    fact ecdsa-signature-encoding = der
  • Nonce в ECDSA

    rfc6979-opt-in

    По умолчанию nonce случайный; с параметром подписи nonce-type, равным 1, воспроизвёлся тестовый вектор из приложения A.2.5 RFC 6979.

    Что записала проверка
    fact ecdsa-nonce = rfc6979-opt-in
    evidence ecdsa-nonce: default signatures repeat: no; nonce-type 1 (deterministic) reproduces the RFC 6979 A.2.5 r: yes
  • Low-S при подписи

    either

    s не нормализуется: среди 64 подписей встретились значения high-S.

    Что записала проверка
    fact ecdsa-low-s-sign = either
  • High-S при проверке

    accepts-high-s

    Подпись в DER, в которой s заменили на n − s, прошла проверку.

    Что записала проверка
    fact ecdsa-low-s-verify = accepts-high-s
  • Что хеширует вызов подписи

    hashes-message-or-digest

    EVP_DigestSign хеширует данные; EVP_PKEY_sign подписывает заранее вычисленный дайджест, и такая подпись прошла проверку по сообщению.

    Что записала проверка
    fact ecdsa-prehash = hashes-message-or-digest
  • Некорректная подпись ECDSA

    returns-error

    EVP_DigestVerify вернула -1 (ошибку, а не 0) для подписи raw r‖s и для 3-байтового фрагмента данных.

    Что записала проверка
    fact ecdsa-malformed-signature = returns-error
    evidence ecdsa-malformed-signature: EVP_DigestVerify returned -1 for raw r||s and -1 for 3 bytes (1 = valid, 0 = invalid, negative = error)
  • Вывод проверки при ошибке

    distinguishable

    Команда openssl dgst -verify вывела Error verifying data для подписи не в формате DER и Verification failure для верной подписи других данных.

    Что записала проверка
    fact cli-verify-output = distinguishable
    evidence cli-verify-output: valid: Verified OK; 64 zero bytes: Error verifying data; valid signature over other data: Verification failure
  • Кривые ECDSA

    P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1

    Подпись и проверка работают на P-224, P-256, P-384, P-521, secp256k1 и brainpoolP256r1/P384r1/P512r1.

    Что записала проверка
    fact ecdsa-curves = P-224, P-256, P-384, P-521, secp256k1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • EdDSA

    Ed25519Ed448

    Ed25519 и Ed448.

    Что записала проверка
    fact eddsa = Ed25519, Ed448
  • Постквантовые алгоритмы

    ML-KEMML-DSASLH-DSA

    В провайдере по умолчанию ML-KEM-768 выполнил инкапсуляцию и декапсуляцию, а ML-DSA-65 и SLH-DSA-SHA2-128s — подпись и проверку.

    Что записала проверка
    fact pqc = ML-KEM, ML-DSA, SLH-DSA
    evidence pqc: TLS groups with ML-KEM: MLKEM512 MLKEM768 MLKEM1024 SecP256r1MLKEM768 X25519MLKEM768 SecP384r1MLKEM1024 
  • Форматы открытых ключей

    spki-pemspki-derx509

    Одна и та же подпись прошла проверку открытыми ключами SPKI в PEM и DER и открытым ключом из сертификата X.509; проверка прошла и с SPKI, содержащим сжатую точку.

    Что записала проверка
    fact public-key-formats = spki-pem, spki-der, x509
    evidence public-key-formats: SPKI carrying a compressed point (openssl ec -conv_form compressed) verifies: yes
  • Форматы закрытых ключей

    pkcs8-pempkcs8-derencrypted-pkcs8sec1-pemsec1-der

    Подпись работает с ключами PKCS#8 в PEM и DER, с зашифрованным PKCS#8 и с SEC1 в PEM и DER; genpkey записывает PKCS#8, openssl ec — SEC1.

    Что записала проверка
    fact private-key-formats = pkcs8-pem, pkcs8-der, encrypted-pkcs8, sec1-pem, sec1-der
    evidence private-key-formats: genpkey writes -----BEGIN PRIVATE KEY-----; openssl ec writes -----BEGIN EC PRIVATE KEY-----

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

Сгенерируйте ключ P-256, подпишите и проверьте данные через dgst, создайте детерминированную подпись через pkeyutl, а затем подпись ML-DSA-65.
# P-256 key as PKCS#8, public key as SPKI.
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out key.pem
openssl pkey -in key.pem -pubout -out pub.pem

printf 'order #1042 approved' > msg.txt
openssl dgst -sha256 -sign key.pem -out sig.der msg.txt   # ASN.1 DER, 70-72 bytes
openssl dgst -sha256 -verify pub.pem -signature sig.der msg.txt

# Deterministic RFC 6979 signing (OpenSSL 3.2+) goes through pkeyutl.
openssl pkeyutl -sign -inkey key.pem -rawin -digest sha256 -pkeyopt nonce-type:1 -in msg.txt -out det1.der
openssl pkeyutl -sign -inkey key.pem -rawin -digest sha256 -pkeyopt nonce-type:1 -in msg.txt -out det2.der
cmp -s det1.der det2.der && echo "deterministic: identical signatures"

# Post-quantum: ML-DSA-65 key and signature.
openssl genpkey -algorithm ML-DSA-65 -out mldsa.pem
openssl pkeyutl -sign -inkey mldsa.pem -rawin -in msg.txt -out mldsa.sig
echo "ML-DSA-65 signature: $(wc -c < mldsa.sig) bytes"

Тестовый стенд для фрагментов кода запускает каждый пример без изменений в образе контейнера alpine:3.24.2, и запуск завершается ошибкой, если вывод не совпадает.

Подготовка
apk add --no-cache -q openssl=3.5.9-r0 >/dev/null
Команда
sh usage.sh
Вывод должен совпадать (регулярное выражение)
Verified OK\ndeterministic: identical signatures\nML-DSA-65 signature: 3309 bytes

Инструменты

Термины

Библиотеки

Статьи

Рецепты

Ошибки

Библиотеки