本文へスキップ
ecdsa.com
C · OpenSSL · コマンドライン

OpenSSL

OpenSSL は、インターネット上の TLS の大半と署名処理の多くを支える C ライブラリ兼コマンドラインツールです。署名は 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
公開鍵の形式
spki-pemspki-derx509
秘密鍵の形式
pkcs8-pempkcs8-derencrypted-pkcs8sec1-pemsec1-der

OpenSSL は、C 向けに、またバインディングを通じて Node.js、Python、PHP、Ruby 向けに libcrypto と libssl を提供しており、多くの人が最初に触れる 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 で、P-256 では 70〜72 バイトです。nonce-type パラメーターを 1 に設定しない限り(OpenSSL 3.2 以降)nonce はランダムで、1 に設定すると RFC 6979 の P-256 テストベクトルを再現できました。コマンドラインでは、サンプルのとおり、このパラメーターは pkeyutl からしか指定できません。s は正規化されず、検証は high-S も受け入れます。EVP_PKEY_sign は自分で計算したダイジェストに署名します。

不正な形式の入力は、偽という結果ではなくエラーになります。EVP_DigestVerify は 64 バイトの生の r‖s 署名に対して -1 を返し、CLI もそれをエラーとして示しました。openssl dgst -verify は、正しい署名には Verified OK を、別のデータに対する有効な署名には Verification failure を、DER ではない 64 バイトのデータには Error verifying data を出力しました。そのため 3.5.9 では、形式の問題と偽造とを文言で区別できます。生の署名は DER ⇄ 生形式の変換ツールで変換するか、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)で、リンク先のエラーページで解説しています。

事実とその根拠となるチェック

以下の内容はドキュメントからの転記ではありません。2026年10月20日に、チェック content/libraries/verify/openssl/run.sh がコンテナイメージ alpine:3.24.2 内で OpenSSL 3.5.9 を実行しました。このページの内容はその出力と一致していなければならず、各事実には該当する出力行を示しています。

  • ECDSA 署名のエンコーディング

    der

    EVP_DigestSign と openssl dgst -sign は ASN.1 DER を生成します。

    チェックによる記録
    fact ecdsa-signature-encoding = der
  • ECDSA の nonce

    rfc6979-opt-in

    デフォルトはランダムです。署名パラメーター nonce-type を 1 に設定すると、RFC 6979 の付録 A.2.5 を再現できました。

    チェックによる記録
    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

    s を n − s に置き換えた DER 署名も検証を通りました。

    チェックによる記録
    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 は、生の r‖s 署名と 3 バイトのデータに対して -1(0 ではなくエラー)を返しました。

    チェックによる記録
    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 は、DER でない署名に対して Error verifying data を、別のデータに対する有効な署名に対して 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

ライブラリ