Aller au contenu
ecdsa.com
Ligne de commande

GnuPG (gpg)

GnuPG 2.4, l’implémentation OpenPGP derrière la commande gpg : des clés Ed25519 qui expirent par défaut au bout de trois ans, un ECDSA déterministe (RFC 6979) sur les courbes NIST, Brainpool et secp256k1, des signatures Ed25519 portant sur un condensat, et pas encore d’algorithmes post-quantiques.
Licence
GPL-3.0-or-later
Version vérifiée
2.4.9 ·
Code source
dev.gnupg.org/source/gnupg/
Documentation
www.gnupg.org/documentation/manuals/gnupg/

Compatibilité en un coup d’œil

ECDSAEdDSA

Courbes ECDSA
P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1
EdDSA
Ed25519Ed448

GnuPG implémente OpenPGP pour la signature et le chiffrement de fichiers et d’e-mails, la signature des paquets dans de nombreuses distributions Linux et la signature des commits git. Les faits présentés ici ont été vérifiés sur le paquet Alpine 3.24.2, soit GnuPG 2.4.9 avec libgcrypt 1.12.2. gpg --quick-gen-key avec un simple ID utilisateur crée une clé primaire Ed25519 pour la signature et la certification, ainsi qu’une sous-clé de chiffrement Curve25519 (cv25519), toutes deux en clés de version 4, et la clé primaire expire au bout de 1095 jours (trois ans), sauf si une expiration est indiquée. Examinez les clés et les signatures avec l’inspecteur OpenPGP.

Des clés ECDSA peuvent être créées sur P-256, P-384, P-521, secp256k1 et les trois courbes Brainpool r1 ; nistp224 échoue avec « Unknown elliptic curve ». Le paquet de signature transporte r et s sous forme de deux MPI OpenPGP, ni en DER ni en r‖s de largeur fixe. Les signatures P-256 utilisent SHA-256 par défaut ; demander SHA-256 avec une clé P-384 échoue avec « signing failed: Invalid length », alors que SHA-512 avec une clé P-256 est accepté.

Les nonces sont déterministes : avec l’horloge figée (--faked-system-time), deux signatures d’un même fichier étaient identiques octet par octet, et r correspondait à une implémentation indépendante de la RFC 6979 ; signer deux fois les mêmes données ne réutilise donc pas un nonce de manière dangereuse. s n’est pas normalisé, et une signature dont s a été remplacé par n − s a été reconnue comme bonne, ce qui importe partout où les signatures sont censées être uniques.

Les signatures Ed25519 utilisent l’ancien format EdDSA (algorithme 22) : R et S sont des MPI, et ce que signe Ed25519 est le condensat SHA-512 du fichier et des champs hachés de la signature, non le fichier lui-même. Une fois R et S complétés à gauche jusqu’à 32 octets chacun, R‖S a été vérifié avec OpenSSL sur ce condensat et a échoué sur le fichier : pour vérifier des signatures gpg avec une bibliothèque Ed25519 généraliste, il faut d’abord calculer le condensat OpenPGP. Les clés Ed448 sont créées sous forme de paquets de clé de version 5, le format du brouillon LibrePGP que suit GnuPG, alors que les clés par défaut, ECDSA et Ed25519 testées étaient toutes en version 4 ; assurez-vous que l’autre partie lit la version 5 avant de choisir Ed448. Cette version ne comporte aucun algorithme post-quantique : la liste des algorithmes à clé publique est RSA, ELG, DSA, ECDH, ECDSA et EDDSA, et ky768_cv25519 est rejeté comme courbe inconnue.

Dans les scripts, lisez la sortie lisible par machine de --status-fd plutôt que le texte : une signature valide a donné GOODSIG et VALIDSIG avec le code de sortie 0, une signature portant sur d’autres données BADSIG avec le code de sortie 1, et un paquet tronqué NODATA avec le code de sortie 2. gpg --export-ssh-key suivi d’une empreinte et de ! écrit une ligne de clé publique OpenSSH pour les clés ECDSA et Ed25519, alors que --export et --export-secret-keys écrivent des paquets OpenPGP.

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/gnupg/run.sh a exécuté GnuPG (gpg) 2.4.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.

  • Type de clé par défaut

    ed25519cv25519

    --quick-gen-key avec un simple ID utilisateur a créé une clé primaire ed25519 (usage sc) et une sous-clé cv25519 (usage e).

    Relevé par la vérification
    fact default-key-type = ed25519, cv25519
    evidence default-key-type: pub ed25519 (algorithm 22, usage scESC); sub cv25519 (algorithm 18, usage e)
  • Expiration des clés par défaut

    1095d

    L’expiration de la clé primaire était fixée à 1095 jours après sa création.

    Relevé par la vérification
    fact default-key-expiry = 1095d
    evidence default-key-expiry: expiration minus creation of the primary key: 1095 days
  • Version des clés OpenPGP

    v4

    La clé par défaut a été exportée sous forme de paquet de clé de version 4.

    Relevé par la vérification
    fact openpgp-key-version = v4
  • Version des clés Ed448

    v5

    Une clé ed448 a été exportée sous forme de paquet de clé de version 5 ; la clé par défaut et les clés ECDSA et ed25519, en version 4.

    Relevé par la vérification
    fact ed448-key-version = v5
    evidence ed448-key-version: key packet versions: default v4, nistp256 v4, nistp384 v4, nistp521 v4, secp256k1 v4, brainpoolP256r1 v4, brainpoolP384r1 v4, brainpoolP512r1 v4, ed25519 v4, ed448 v5
  • Courbes ECDSA

    P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1

    Les sept courbes ont toutes généré des clés avec lesquelles la signature et la vérification ont réussi ; nistp224 a renvoyé « Unknown elliptic curve ».

    Relevé par la vérification
    fact ecdsa-curves = P-256, P-384, P-521, secp256k1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
    evidence ecdsa-curves: nistp224: gpg: Key generation failed: Unknown elliptic curve
  • EdDSA

    Ed25519Ed448

    Signature et vérification réussies avec des clés ed25519 et ed448.

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

    none

    La ligne Pubkey: de gpg --version ne mentionne aucun algorithme post-quantique, et la génération d’une clé ky768_cv25519 a échoué.

    Relevé par la vérification
    fact pqc = none
    evidence pqc: --quick-gen-key with ky768_cv25519: gpg: Key generation failed: Unknown elliptic curve
  • Encodage des signatures ECDSA

    openpgp-mpi

    Le paquet de signature P-256 (algorithme 19) se termine par deux MPI, r et s.

    Relevé par la vérification
    fact ecdsa-signature-encoding = openpgp-mpi
    evidence ecdsa-signature-encoding: P-256 detached signature: version=4 pubkey-algo=19 hash-algo=8 mpis=2
  • Fonction de hachage par défaut

    sha256

    La signature P-256 par défaut indique l’algorithme de hachage 8, SHA-256.

    Relevé par la vérification
    fact ecdsa-default-hash = sha256
  • Nonce ECDSA

    rfc6979

    Deux signatures faites avec l’horloge figée étaient identiques, et r correspondait à celui de l’implémentation de référence de la RFC 6979.

    Relevé par la vérification
    fact ecdsa-nonce = rfc6979
    evidence ecdsa-nonce: two signatures of one file with a frozen clock are identical; r equals the RFC 6979 reference signer's r: yes
  • Low-S à la signature

    either

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

    Relevé par la vérification
    fact ecdsa-low-s-sign = either
    evidence ecdsa-low-s-sign: signatures with s > n/2 among 32: yes
  • High-S à la vérification

    accepts-high-s

    Une signature dont s a été remplacé par n − s a été vérifiée avec GOODSIG et le code de sortie 0.

    Relevé par la vérification
    fact ecdsa-low-s-verify = accepts-high-s
    evidence ecdsa-low-s-verify: s replaced by n - s: exit 0, status NEWSIG KEY_CONSIDERED SIG_ID GOODSIG VALIDSIG TRUST_ULTIMATE
  • Hachage lié à la courbe

    enforced

    --digest-algo SHA256 avec une clé P-384 a échoué avec « Invalid length » ; SHA-512 avec une clé P-256 a permis de signer.

    Relevé par la vérification
    fact ecdsa-hash-curve-binding = enforced
    evidence ecdsa-hash-curve-binding: --digest-algo SHA256 with a P-384 key: gpg: signing failed: Invalid length; --digest-algo SHA512 with a P-256 key: signed
  • Sortie de la vérification en cas d’échec

    distinguishable

    BADSIG et code de sortie 1 pour un mauvais message ; NODATA et code de sortie 2 pour un paquet tronqué.

    Relevé par la vérification
    fact cli-verify-output = distinguishable
    evidence cli-verify-output: valid: exit 0, status NEWSIG KEY_CONSIDERED SIG_ID GOODSIG VALIDSIG TRUST_ULTIMATE
    evidence cli-verify-output: wrong message: exit 1, status NEWSIG KEY_CONSIDERED BADSIG FAILURE
    evidence cli-verify-output: truncated signature packet: exit 2, status NODATA FAILURE
  • Ce que couvre la signature Ed25519

    digest

    R‖S a été vérifié avec openssl pkeyutl sur le condensat de signature OpenPGP et a échoué sur le fichier.

    Relevé par la vérification
    fact ed25519-signed-input = digest
    evidence ed25519-signed-input: version=4 pubkey-algo=22 hash-algo=10 mpis=2; R || S checked by openssl pkeyutl over the signature digest: Signature Verified Successfully; over the file: Signature Verification Failure
  • Formats de clé publique

    opensshopenpgp

    gpg --export écrit des paquets OpenPGP ; --export-ssh-key a écrit des lignes ecdsa-sha2-nistp256 et ssh-ed25519.

    Relevé par la vérification
    fact public-key-formats = openssh, openpgp
    evidence public-key-formats: gpg --export: public key packet; gpg --export-ssh-key: P-256 key ecdsa-sha2-nistp256, Ed25519 key ssh-ed25519
  • Formats de clé privée

    openpgp

    gpg --export-secret-keys écrit des paquets de clé secrète OpenPGP.

    Relevé par la vérification
    fact private-key-formats = openpgp
    evidence private-key-formats: gpg --export-secret-keys: secret key packet

Utilisation

Créer une clé par défaut, produire une signature détachée avec armure ASCII et la vérifier via la sortie d’état.
export GNUPGHOME="$(mktemp -d)"
# With only a user ID: an Ed25519 signing key plus a Curve25519 encryption subkey, expiring in 3 years.
gpg --batch --pinentry-mode loopback --passphrase '' --quick-gen-key 'Alice <alice@example.com>'

printf 'order #1042 approved\n' > order.txt
gpg --batch --yes --armor --detach-sign order.txt   # writes order.txt.asc

# Scripts should read --status-fd: GOODSIG and VALIDSIG for a valid signature, BADSIG otherwise.
gpg --batch --status-fd 1 --verify order.txt.asc order.txt 2>/dev/null | grep -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)' | cut -d' ' -f2

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 gnupg=2.4.9-r1 >/dev/null
Commande
sh sign.sh
La sortie doit correspondre à cette expression régulière
GOODSIG\nVALIDSIG

Bibliothèques