Québec, Canada

403-1381 1re Avenue

+1 581.849.27.96

bdgouthiere@gmail.com

Go 1.27 signe en post-quantique : faut-il déjà passer à ML-DSA ?

Ou : Comment signer pour un ordinateur qui n’existe pas encore

Go 1.27, sorti le 19 août 2026, a ajouté à sa bibliothèque standard le paquet crypto/mldsa : la signature ML-DSA, que le NIST a normalisée en août 2024 sous le nom FIPS 204 pour résister aux futurs ordinateurs quantiques1. Le réflexe serait de tout migrer. Sauf que ton code Go fait déjà de la cryptographie post-quantique sans te l’avoir demandé : depuis Go 1.24, chaque connexion TLS négocie par défaut un échange de clés hybride, X25519MLKEM768, qui mêle la courbe classique et ML-KEM2. La signature est l’autre moitié du chantier. C’est aussi celle qui, pour la plupart des projets, peut attendre. J’ai mesuré ce qu’elle coûte, pour savoir qui ne devrait pas attendre.

La même version qui a apporté les méthodes génériques en Go branche ML-DSA partout : crypto/x509 lit et produit des certificats ML-DSA, crypto/tls accepte les trois variantes dans TLS 1.3, et la liste des algorithmes de signature que Go annonce par défaut commence désormais par elles3. Rien à configurer. La question n’est donc pas « comment l’activer », mais « à quoi ça sert chez moi ».

Signature post-quantique en Go : ce que ML-DSA protège, et ce qu’il ne protège pas

Le coffre volé et la signature imitée

Imagine deux malfaiteurs. Le premier vole un coffre aujourd’hui, n’arrive pas à l’ouvrir, le range dans son garage et attend quinze ans l’outil qui le forcera. C’est la menace « stocker maintenant, déchiffrer plus tard » : quelqu’un enregistre ton trafic chiffré et patiente. Le coffre, c’est l’échange de clés. Go l’a blindé en premier, et il a eu raison.

Le second est un faussaire. En 2040, il imite ta signature à la perfection. Il peut signer de nouveaux documents à ton nom. Il ne peut pas remonter le temps : la poignée de main TLS que ton serveur a signée en 2026 a duré quelques millisecondes, et plus personne ne la vérifiera. Cloudflare le résumait dès 2022 : « authentication is less urgent », puisqu’il suffit de remplacer les signatures « by the time a sufficiently large quantum computer is built »4.

L’urgence d’une signature dépend donc d’une seule chose : combien de temps quelqu’un la vérifiera encore.

SignatureVérifiée pendantUrgence post-quantique
Poignée de main TLSquelques millisecondesnulle
Certificat de sitequelques semaines (45 jours chez Let’s Encrypt en 2028)faible
Mise à jour signée, clé gravée dans l’appareiltoute la vie de l’appareilréelle
Document archivédes décenniesréelle

Ce que pèse une signature post-quantique

ML-DSA existe en trois tailles. La documentation de Go tranche : « Most applications should use MLDSA44 ». Face à Ed25519, la signature classique la plus compacte, l’écart se lit d’un coup d’œil5 :

AlgorithmeClé publiqueSignature
Ed2551932 octets64 octets
ML-DSA-441 312 octets2 420 octets
ML-DSA-651 952 octets3 309 octets
ML-DSA-872 592 octets4 627 octets

Côté code, l’API tient en quelques lignes. Le paramètre Context mérite qu’on s’y arrête : il lie la signature à un usage, si bien qu’une signature de mise à jour ne pourra jamais passer pour une signature de facture.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// La clé privée tient dans une graine de 32 octets.
sk, err := mldsa.GenerateKey(mldsa.MLDSA44())
if err != nil {
	log.Fatal(err)
}
pk := sk.PublicKey()

maj := []byte("contenu de mise-a-jour-v2.4.1.tar.gz")
opts := &mldsa.Options{Context: "maj-logiciel"}

sig, err := sk.Sign(nil, maj, opts) // le premier argument est ignoré
if err != nil {
	log.Fatal(err)
}

fmt.Println(mldsa.Verify(pk, maj, sig, opts))                               // <nil>
fmt.Println(mldsa.Verify(pk, maj, sig, &mldsa.Options{Context: "facture"})) // mldsa: invalid signature

Exécuté sous Go 1.27.3 : clé privée de 32 octets, clé publique de 1 312, signature de 2 420. La même signature présentée avec un autre contexte est refusée, tout comme le fichier modifié d’un seul bit.

Et la vitesse ? J’ai mesuré la création de clé, la signature et la vérification d’un message de 1 Ko, en médiane de cinq passes6 :

OpérationEd25519ML-DSA-44ML-DSA-65ML-DSA-87
Création de clé17 µs168 µs322 µs372 µs
Signature24 µs379 µs624 µs719 µs
Vérification49 µs114 µs166 µs294 µs

Signer coûte seize fois plus cher, et ça n’a aucune importance pour une mise à jour signée une fois par version. Vérifier ne coûte que 2,3 fois plus, et c’est la seule opération que l’appareil répète. Le vrai prix n’est pas le processeur. Ce sont les octets.

Pourquoi ton certificat HTTPS restera classique

Pour voir ce que pèsent ces octets sur le réseau, j’ai monté un serveur TLS en Go 1.27 avec un certificat autosigné, puis compté ce que le client reçoit pendant la poignée de main. Avec ECDSA P-256 : 1 790 octets. Avec ML-DSA-44 : 7 736 octets, pour un seul certificat. Une vraie chaîne ajoute un certificat intermédiaire, donc une clé publique et une signature de plus. Le client Go s’est connecté sans le moindre réglage : les deux bouts parlent ML-DSA d’office.

C’est précisément ce surpoids qui retient les navigateurs. Le 27 février 2026, l’équipe de Chrome a écrit qu’elle n’avait « no immediate plan » pour accepter des certificats X.509 post-quantiques dans son magasin racine. Elle mise sur les Merkle Tree Certificates, en cours de normalisation à l’IETF, qui remplacent la chaîne de signatures par une preuve d’appartenance compacte. Depuis Chrome 150, ML-DSA n’est accepté que dans les PKI privées7. Pour ton site public, il n’y a donc rien à faire, et rien de possible.

DevOps Dave : J’ai passé tous nos certificats internes en ML-DSA-87. On est prêts pour le quantique.

Security Sarah : Ils sont valables combien de temps ?

DevOps Dave : Quatre-vingt-dix jours, renouvelés tout seuls.

Security Sarah : Donc tu as protégé pour vingt ans une signature que personne ne vérifiera après le prochain trimestre.

Qui devrait s’y mettre dès maintenant

Restent les signatures qui durent. Celui qui fabrique des appareils et grave dans leur mémoire la clé publique qui validera les mises à jour pendant dix ans devrait y penser aujourd’hui : cette clé ne changera pas avant la fin de vie du matériel. Même chose pour l’archivage de documents signés, et pour une PKI interne entre services Go, où les deux bouts sont sous ton contrôle et peuvent passer en ML-DSA dès la mise à jour de Go. Pour tout le reste, garder Go à jour suffit : l’échange de clés, celui qui compte vraiment contre le stockage massif, est déjà hybride.

Go lui-même illustre bien la nuance. La base de sommes de contrôle qui protège tes modules, dont l’article sur le ver de npm détaille le rôle, signe encore en Ed25519, avec une clé publique écrite en dur dans la commande go8. Le jour où il faudra la remplacer, ce sera une vraie migration, précisément parce que cette signature-là est vérifiée par chaque développeur, à chaque téléchargement, depuis des années.

La seule question à te poser tient en une ligne : dans combien d’années quelqu’un vérifiera-t-il encore cette signature ? Si la réponse est « jamais », Ed25519 te suffit, et il pèse 64 octets. Si la réponse dépasse la durée de vie de tes certificats, tu signes déjà pour un ordinateur qui n’existe pas encore.



  1. Les notes de version de Go 1.27 : « The new crypto/mldsa package implements the post-quantum ML-DSA signature scheme specified in FIPS 204. » La page des versions date Go 1.27.0 du 19 août 2026. La page de FIPS 204 au NIST et le texte de la norme portent la date de publication du 13 août 2024, le même jour que FIPS 203 (ML-KEM) et FIPS 205 (SLH-DSA). ML-DSA dérive de CRYSTALS-Dilithium. ↩︎

  2. La documentation des réglages GODEBUG : « Go 1.24 enabled the post-quantum key exchange mechanism X25519MLKEM768 by default », avec le réglage tlsmlkem=0 pour revenir en arrière. Go 1.26 a ajouté par défaut SecP256r1MLKEM768 et SecP384r1MLKEM1024. Mon test de la section sur HTTPS le confirme : les trois poignées de main ont négocié X25519MLKEM768 sans configuration. Go 1.24 est sorti le 11 février 2025. ↩︎

  3. Les notes de version de Go 1.27 indiquent que « crypto/x509 now supports ML-DSA private keys, public keys, and signatures » et que crypto/tls accepte les valeurs MLDSA44, MLDSA65 et MLDSA87. L’ordre par défaut se lit dans le fichier defaults.go de crypto/tls, où les trois variantes ML-DSA précèdent RSA-PSS, ECDSA et Ed25519. ↩︎

  4. Billet de Cloudflare du 3 octobre 2022, « Post-quantum for all » : « The reason is that authentication is less urgent: we only need to have them replaced by the time a sufficiently large quantum computer is built, whereas any data secured by a vulnerable key agreement today can be stored and decrypted in the future. » ↩︎

  5. Tailles tirées de la documentation de crypto/mldsa et du tableau 2 de FIPS 204, et de la documentation de crypto/ed25519 pour Ed25519. Une nuance sur la clé privée : FIPS 204 donne 2 560 octets pour ML-DSA-44, parce qu’elle y est stockée sous forme développée. Go ne garde que la graine de 32 octets d’où tout se recalcule, et Bytes() renvoie cette graine. FIPS 204 classe ML-DSA-44, 65 et 87 dans les catégories de sécurité 2, 3 et 5 du NIST. ↩︎

  6. Mesures avec go test -bench et b.Loop(), cinq passes, sous Go 1.27.3 sur un portable AMD Ryzen 7 5800H (Linux, amd64). Message de 1 024 octets, signature aléatoire par défaut (la variante SignDeterministic existe aussi). Les temps de signature de ML-DSA varient d’une passe à l’autre, parce que l’algorithme recommence tant qu’une signature candidate ne remplit pas ses conditions. Ces chiffres valent pour la bibliothèque standard de Go sur cette machine, pas pour ML-DSA en général. ↩︎

  7. Le billet de Google « Cultivating a robust and efficient quantum-safe HTTPS », du 27 février 2026, signé par la Chrome Secure Web Networking Team : « Chrome has no immediate plan to add traditional X.509 certificates containing post-quantum cryptography » au magasin racine. La page de test du programme racine post-quantique de Chrome, mise à jour le 16 octobre 2026, ajoute : « Beginning in Chrome 150, Chrome supports ML-DSA in private PKI hierarchies », et confirme que Chrome s’appuiera sur les Merkle Tree Certificates. Le test de poignée de main : serveur et client Go 1.27.3 sur la même machine, un seul certificat autosigné, octets comptés côté client. ↩︎

  8. La documentation du paquet golang.org/x/mod/sumdb/note, qui définit le format des textes signés par la base de sommes : « There is only one key type, Ed25519 with algorithm identifier 1 », avec la précision que « New key types may be introduced in the future as needed ». La clé de sum.golang.org figure dans le fichier src/cmd/go/internal/modfetch/key.go des sources de Go. ↩︎