Zum Inhalt springen
ecdsa.com
C · OpenSSL · Befehlszeile

OpenSSL

OpenSSL, die C-Bibliothek und das Befehlszeilentool hinter den meisten TLS-Verbindungen und vielen Signaturen im Internet: DER-Signaturen, zufällige Nonces, auf Wunsch RFC 6979, alle gängigen Kurven und seit 3.5 ML-KEM, ML-DSA und SLH-DSA.
Lizenz
Apache-2.0
Geprüfte Version
3.5.9 ·
Quellcode
github.com/openssl/openssl
Dokumentation
docs.openssl.org/3.5/

Kompatibilität auf einen Blick

ECDSAEdDSAPost-Quanten-Verfahren

ECDSA-Kurven
P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1
EdDSA
Ed25519Ed448
Post-Quanten-Algorithmen
ML-KEMML-DSASLH-DSA
Formate privater Schlüssel
pkcs8-pempkcs8-derencrypted-pkcs8sec1-pemsec1-der

OpenSSL stellt libcrypto und libssl für C und über Bindings für Node.js, Python, PHP und Ruby bereit, dazu den Befehl openssl, dem die meisten zuerst begegnen. Die Fakten auf dieser Seite wurden mit dem Distributionspaket aus Alpine 3.24.2 geprüft, OpenSSL 3.5.9 (die Linie 3.5 mit Langzeitunterstützung); die neuesten Upstream-Releases waren damals 3.6.5 und 4.0.3, dort kann das Verhalten also abweichen.

ECDSA-Signaturen aus EVP_DigestSign und aus openssl dgst -sign sind ASN.1-DER – auf P-256 70 bis 72 Byte. Nonces sind zufällig, sofern du den Parameter nonce-type nicht auf 1 setzt (OpenSSL 3.2+); damit wurde der P-256-Testvektor aus RFC 6979 reproduziert. Auf der Befehlszeile ist dieser Parameter nur über pkeyutl erreichbar, wie das Beispiel zeigt. s wird nicht normalisiert, und die Prüfung akzeptiert High-S. EVP_PKEY_sign signiert einen Digest, den du selbst berechnet hast.

Fehlerhafte Eingabe ist ein Fehler, kein negatives Prüfergebnis: EVP_DigestVerify gab für eine rohe r‖s-Signatur mit 64 Byte -1 zurück, und die CLI meldete das auch. openssl dgst -verify gab für eine korrekte Signatur Verified OK aus, für eine gültige Signatur über andere Daten Verification failure und für 64 Byte, die kein DER sind, Error verifying data – in 3.5.9 lässt sich ein Formatproblem also am Wortlaut von einer Fälschung unterscheiden. Konvertiere rohe Signaturen mit dem Konverter DER ⇄ Raw oder lass den OpenSSL-Befehls-Builder den richtigen Aufruf zusammenstellen.

Die Kurven umfassen P-224 bis P-521, secp256k1 und die Brainpool-r1-Kurven, dazu Ed25519 und Ed448. Seit 3.5 implementiert der Standard-Provider außerdem ML-KEM, ML-DSA und SLH-DSA sowie die hybride TLS-Gruppe X25519MLKEM768. Schlüssel liegen als private Schlüssel in PKCS#8 (unverschlüsselt oder verschlüsselt) oder SEC1 vor und als öffentliche Schlüssel in SPKI oder in Zertifikaten: genpkey schreibt -----BEGIN PRIVATE KEY-----, der ältere Befehl openssl ec schreibt -----BEGIN EC PRIVATE KEY----- – eine Datei mit der Kennzeichnung EC ist immer ein privater Schlüssel.

Die meisten Fehlermeldungen, nach denen gesucht wird, entstehen beim Laden von Schlüsseln – no start line, header too long, unsupported vom Decoder – und werden auf den verlinkten Fehlerseiten behandelt.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/openssl/run.sh hat OpenSSL 3.5.9 am 20. Oktober 2026 im Container-Image alpine:3.24.2 ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • Kodierung von ECDSA-Signaturen

    der

    EVP_DigestSign und openssl dgst -sign erzeugen ASN.1-DER.

    Von der Prüfung aufgezeichnet
    fact ecdsa-signature-encoding = der
  • ECDSA-Nonce

    rfc6979-opt-in

    Standardmäßig zufällig; der Signaturparameter nonce-type mit dem Wert 1 reproduzierte RFC 6979, Anhang A.2.5.

    Von der Prüfung aufgezeichnet
    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 beim Signieren

    either

    s wird nicht normalisiert: Unter 64 Signaturen traten High-S-Werte auf.

    Von der Prüfung aufgezeichnet
    fact ecdsa-low-s-sign = either
  • High-S bei der Prüfung

    accepts-high-s

    Eine DER-Signatur, in der s durch n − s ersetzt war, bestand die Prüfung.

    Von der Prüfung aufgezeichnet
    fact ecdsa-low-s-verify = accepts-high-s
  • Was der Signaturaufruf hasht

    hashes-message-or-digest

    EVP_DigestSign hasht die Daten; EVP_PKEY_sign signiert einen vorab berechneten Digest, und diese Signatur bestand die Prüfung gegen die Nachricht.

    Von der Prüfung aufgezeichnet
    fact ecdsa-prehash = hashes-message-or-digest
  • Fehlerhafte ECDSA-Signatur

    returns-error

    EVP_DigestVerify gab für eine rohe r‖s-Signatur und für einen 3-Byte-Blob -1 zurück (einen Fehler, nicht 0).

    Von der Prüfung aufgezeichnet
    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)
  • Ausgabe bei fehlgeschlagener Prüfung

    distinguishable

    openssl dgst -verify gab für eine Signatur, die kein DER ist, Error verifying data aus und für eine gültige Signatur über andere Daten Verification failure.

    Von der Prüfung aufgezeichnet
    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-Kurven

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

    Signieren und Prüfen funktionierten mit P-224, P-256, P-384, P-521, secp256k1 und brainpoolP256r1/P384r1/P512r1.

    Von der Prüfung aufgezeichnet
    fact ecdsa-curves = P-224, P-256, P-384, P-521, secp256k1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • EdDSA

    Ed25519Ed448

    Ed25519 und Ed448.

    Von der Prüfung aufgezeichnet
    fact eddsa = Ed25519, Ed448
  • Post-Quanten-Algorithmen

    ML-KEMML-DSASLH-DSA

    Im Standard-Provider funktionierten Kapselung und Entkapselung mit ML-KEM-768 sowie Signieren und Prüfen mit ML-DSA-65 und SLH-DSA-SHA2-128s.

    Von der Prüfung aufgezeichnet
    fact pqc = ML-KEM, ML-DSA, SLH-DSA
    evidence pqc: TLS groups with ML-KEM: MLKEM512 MLKEM768 MLKEM1024 SecP256r1MLKEM768 X25519MLKEM768 SecP384r1MLKEM1024 
  • Formate öffentlicher Schlüssel

    spki-pemspki-derx509

    Mit SPKI als PEM und DER sowie mit dem öffentlichen Schlüssel eines X.509-Zertifikats bestand dieselbe Signatur die Prüfung; mit einem SPKI, das einen komprimierten Punkt enthält, ebenfalls.

    Von der Prüfung aufgezeichnet
    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
  • Formate privater Schlüssel

    pkcs8-pempkcs8-derencrypted-pkcs8sec1-pemsec1-der

    Signieren funktionierte mit PKCS#8 in PEM und DER, mit verschlüsseltem PKCS#8 und mit SEC1 in PEM und DER; genpkey schreibt PKCS#8, openssl ec schreibt SEC1.

    Von der Prüfung aufgezeichnet
    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-----

Verwendung

Erzeuge einen P-256-Schlüssel, signiere und prüfe mit dgst, signiere deterministisch über pkeyutl und erstelle eine ML-DSA-65-Signatur.
# 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"

Die Snippet-Testumgebung führt jedes Beispiel unverändert im Container-Image alpine:3.24.2 aus, und der Lauf schlägt fehl, wenn die Ausgabe nicht übereinstimmt.

Einrichtung
apk add --no-cache -q openssl=3.5.9-r0 >/dev/null
Befehl
sh usage.sh
Ausgabe muss passen (regulärer Ausdruck)
Verified OK\ndeterministic: identical signatures\nML-DSA-65 signature: 3309 bytes

Bibliotheken