Aller au contenu
ecdsa.com
C · OpenSSL · Ligne de commande

OpenSSL

OpenSSL, la bibliothèque C et l’outil en ligne de commande sur lesquels reposent la majeure partie du TLS d’Internet et une bonne part de ses signatures : signatures DER, nonces aléatoires ou RFC 6979 sur demande, toutes les courbes courantes, et ML-KEM, ML-DSA et SLH-DSA depuis la 3.5.
Licence
Apache-2.0
Version vérifiée
3.5.9 ·
Code source
github.com/openssl/openssl
Documentation
docs.openssl.org/3.5/

Compatibilité en un coup d’œil

ECDSAEdDSAPost-quantique

Courbes ECDSA
P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1
EdDSA
Ed25519Ed448
Algorithmes post-quantiques
ML-KEMML-DSASLH-DSA
Formats de clé publique
spki-pemspki-derx509
Formats de clé privée
pkcs8-pempkcs8-derencrypted-pkcs8sec1-pemsec1-der

OpenSSL fournit libcrypto et libssl pour C et, via des liaisons, pour Node.js, Python, PHP et Ruby, ainsi que la commande openssl, celle que la plupart des gens rencontrent en premier. Les faits présentés ici ont été vérifiés sur le paquet de distribution Alpine 3.24.2, OpenSSL 3.5.9 (la branche 3.5 à support long terme) ; les versions amont les plus récentes à ce moment-là étaient la 3.6.5 et la 4.0.3, dont le comportement peut donc différer.

Les signatures ECDSA produites par EVP_DigestSign et par openssl dgst -sign sont en ASN.1 DER, de 70 à 72 octets sur P-256. Les nonces sont aléatoires, sauf si vous réglez le paramètre nonce-type sur 1 (OpenSSL 3.2+), ce qui a reproduit le vecteur de test P-256 de la RFC 6979 ; en ligne de commande, ce paramètre n’est accessible que via pkeyutl, comme le montre l’exemple. s n’est pas normalisé et la vérification accepte high-S. EVP_PKEY_sign signe un condensat que vous avez calculé.

Une entrée mal formée produit une erreur, pas un résultat négatif : EVP_DigestVerify a renvoyé -1 pour une signature r‖s brute de 64 octets, et la CLI l’a signalé. openssl dgst -verify a affiché Verified OK pour une bonne signature, Verification failure pour une signature valide portant sur d’autres données et Error verifying data pour 64 octets qui ne sont pas du DER : dans la 3.5.9, le libellé permet donc de distinguer un problème de format d’une falsification. Convertissez les signatures brutes avec le convertisseur DER ⇄ brut, ou laissez le générateur de commandes OpenSSL assembler la bonne invocation.

Les courbes prises en charge vont de P-224 à P-521 et comprennent secp256k1 et les courbes Brainpool r1, ainsi qu’Ed25519 et Ed448. Depuis la 3.5, le fournisseur par défaut implémente aussi ML-KEM, ML-DSA et SLH-DSA, ainsi que le groupe hybride TLS X25519MLKEM768. Les clés se présentent comme clés privées PKCS#8 (en clair ou chiffrées) ou SEC1, et comme clés publiques SPKI ou de certificat : genpkey écrit -----BEGIN PRIVATE KEY-----, l’ancien openssl ec écrit -----BEGIN EC PRIVATE KEY----- ; un fichier dont l’étiquette contient EC est toujours une clé privée.

La plupart des messages d’erreur que les développeurs recherchent viennent du chargement des clés (no start line, header too long, unsupported venant du décodeur) et sont traités dans les pages d’erreur en lien.

Les faits et les vérifications qui les fondent

Rien de ce qui suit n’est copié d’une documentation. La vérification content/libraries/verify/openssl/run.sh a exécuté OpenSSL 3.5.9 dans l’image de conteneur alpine:3.24.2 le 20 octobre 2026 ; la page doit correspondre à ce que la vérification a affiché, et chaque fait cite les lignes en question.

  • Encodage des signatures ECDSA

    der

    EVP_DigestSign et openssl dgst -sign produisent de l’ASN.1 DER.

    Relevé par la vérification
    fact ecdsa-signature-encoding = der
  • Nonce ECDSA

    rfc6979-opt-in

    Aléatoire par défaut ; le paramètre de signature nonce-type réglé sur 1 a reproduit l’annexe A.2.5 de la RFC 6979.

    Relevé par la vérification
    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 à la signature

    either

    s n’est pas normalisé : des valeurs high-S sont apparues parmi 64 signatures.

    Relevé par la vérification
    fact ecdsa-low-s-sign = either
  • High-S à la vérification

    accepts-high-s

    Une signature DER dont s avait été remplacé par n − s a passé la vérification.

    Relevé par la vérification
    fact ecdsa-low-s-verify = accepts-high-s
  • Ce que l’appel de signature hache

    hashes-message-or-digest

    EVP_DigestSign hache les données ; EVP_PKEY_sign signe un condensat précalculé, et cette signature a été vérifiée sur le message.

    Relevé par la vérification
    fact ecdsa-prehash = hashes-message-or-digest
  • Signature ECDSA mal formée

    returns-error

    EVP_DigestVerify a renvoyé -1 (une erreur, pas 0) pour une signature r‖s brute et pour un blob de 3 octets.

    Relevé par la vérification
    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)
  • Sortie de la vérification en cas d’échec

    distinguishable

    openssl dgst -verify a affiché Error verifying data pour une signature non DER et Verification failure pour une signature valide portant sur d’autres données.

    Relevé par la vérification
    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
  • Courbes ECDSA

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

    Signature et vérification réussies avec P-224, P-256, P-384, P-521, secp256k1 et brainpoolP256r1/P384r1/P512r1.

    Relevé par la vérification
    fact ecdsa-curves = P-224, P-256, P-384, P-521, secp256k1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • EdDSA

    Ed25519Ed448

    Ed25519 et Ed448.

    Relevé par la vérification
    fact eddsa = Ed25519, Ed448
  • Algorithmes post-quantiques

    ML-KEMML-DSASLH-DSA

    Dans le fournisseur par défaut, encapsulation et décapsulation réussies avec ML-KEM-768, signature et vérification réussies avec ML-DSA-65 et SLH-DSA-SHA2-128s.

    Relevé par la vérification
    fact pqc = ML-KEM, ML-DSA, SLH-DSA
    evidence pqc: TLS groups with ML-KEM: MLKEM512 MLKEM768 MLKEM1024 SecP256r1MLKEM768 X25519MLKEM768 SecP384r1MLKEM1024 
  • Formats de clé publique

    spki-pemspki-derx509

    Le SPKI en PEM et en DER et la clé publique d’un certificat X.509 ont vérifié la même signature ; un SPKI contenant un point compressé l’a vérifiée aussi.

    Relevé par la vérification
    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
  • Formats de clé privée

    pkcs8-pempkcs8-derencrypted-pkcs8sec1-pemsec1-der

    PKCS#8 PEM et DER, PKCS#8 chiffré et SEC1 PEM et DER ont tous permis de signer ; genpkey écrit du PKCS#8, openssl ec écrit du SEC1.

    Relevé par la vérification
    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-----

Utilisation

Générer une clé P-256, signer et vérifier avec dgst, signer de façon déterministe via pkeyutl, et créer une signature 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"

Le banc de test des extraits de code exécute chaque exemple tel quel dans l’image de conteneur alpine:3.24.2, et l’exécution échoue si la sortie ne correspond pas.

Mise en place
apk add --no-cache -q openssl=3.5.9-r0 >/dev/null
Commande
sh usage.sh
La sortie doit correspondre à cette expression régulière
Verified OK\ndeterministic: identical signatures\nML-DSA-65 signature: 3309 bytes

Bibliothèques