<?xml version="1.0" encoding="utf-8"?>
<rfcdesc title="The SSLKEYLOGFILE Format for TLS" num="9850" status="informational" wg="tls">
  <authors><author>M. Thomson (Mozilla)</author><author>Y. Rosomakho
  (Zscaler)</author><author>H. Tschofenig (H-BRS)</author></authors>
  <rfcdate><month>July</month><year>2026</year></rfcdate>
  <date>2026-07-16</date>
<content>
  <p><wikipedia name="Déboguage">Déboguer</wikipedia> une application
  réseau qui utilise le <wikipedia>chiffrement</wikipedia> est
  difficile. Le but du chiffrement est justement d'empêcher un tiers
  (par exemple l'<wikipedia name="Analyseur de paquets">analyseur de
  paquets</wikipedia>) de regarder ce qui se passe. Une approche
  possible est de demander gentiment à l'application d'exporter ses
  clés de chiffrement dans un fichier que l'analyseur pourra importer
  pour ensuite déchiffrer la communication. Ce <wikipedia
  name="Request for comments">RFC</wikipedia> décrit le format le plus
  répandu pour exporter ses clés, connu sous le nom de SSLKEYLOGFILE
  et très commun aujourd'hui.</p>
  <p>Le nom est trompeur car <wikipedia name="Secure Sockets Layer"
  anchor="Protocole_SSL">SSL</wikipedia> est abandonné depuis
  longtemps (<rfc num="7568" local="true"/>), ce format est en fait
  pour <wikipedia name="Transport Layer Security">TLS</wikipedia> mais
  l'ancien nom est resté. Il vient d'une convention courante, définir
  une <wikipedia name="Variable d'environnement">variable
  d'environnement</wikipedia> nommée
  <computer>SSLKEYLOGFILE</computer>, qui va indiquer à l'application
  qu'on demande à recevoir les clés dans un fichier dont le nom est la
  valeur de la variable <computer>SSLKEYLOGFILE</computer>. Mais ce
  <wikipedia name="Request for comments">RFC</wikipedia> n'indique pas
  comment activer cette fonction d'exportation de clés, il documente
  juste le format résultant.</p>
  <p>Un petit rappel de <wikipedia>cryptographie</wikipedia> telle
  qu'elle est faite dans <wikipedia name="Transport Layer
  Security">TLS</wikipedia> (<rfc num="8446" local="true"/>) :
  l'<wikipedia>authentification</wikipedia> est faite avec de la
  <wikipedia name="Cryptographie asymétrique">cryptographie
  asymétrique</wikipedia> puis un <wikipedia name="Échange de
  clé">échange de clés</wikipedia> a lieu, permettant aux deux parties
  de se mettre d'accord sur des clés utilisés en <wikipedia
  name="Cryptographie symétrique">cryptographie
  symétrique</wikipedia>. Ce sont ces clés, qui sont évidemment
  secrètes (seules les deux parties qui communiquent les connaissent)
  qui nous intéressent ici. Sans elles, l'analyseur de paquets ne peut
  que baisser les bras et dire « ici, il y a des données chiffrées
  mais je ne peux pas te les montrer ». Ici, par exemple,
  <wikipedia>Wireshark</wikipedia> peut juste dire que c'est du TLS et
  que c'est chiffré : <image
  name="wireshark-elysee-tls-nokeys.png"/></p>
  <p>Donc, le format du fichier des clés est simple (section 2 du
  RFC) : un fichier <wikipedia name="Texte brut">texte</wikipedia> en
  <wikipedia>UTF-8</wikipedia> (la partie signifiante est forcément en
  <wikipedia name="American Standard Code for Information
  Interchange">ASCII</wikipedia> mais il peut y avoir des commentaires
  qui n'ont pas cette restriction). La fin de ligne n'est pas
  normalisée (on aurait pu exiger le respect du <rfc num="5198"
  local="true"/> mais, bon, ces fichiers ne sont typiquement pas
  échangés entre machines différentes). Les commentaires commencent
  par le <wikipedia name="Croisillon
  (signe)">croisillon</wikipedia>. Chaque secret enregistré tient sur
  une ligne, le nom du secret, la valeur d'un champ TLS aléatoire qui
  permet d'identifier la connexion (il peut y avoir des secrets de
  plusieurs connexions distinctes dans le fichier) et enfin la valeur
  du secret, en <wikipedia name="Système
  hexadécimal">hexadécimal</wikipedia>. Ces trois champs sont séparés
  par des espaces. Par contre, aucune indication sur les paramètres
  cryptographiques de la connexion, comme l'algorithme de
  cryptographie utilisé donc, si on n'a pas le début de la session
  TLS, le fichier peut être inutilisable. Le RFC suggère d'être
  indulgent dans l'analyse du fichier et d'ignorer les lignes
  incorrectes, ce qui permet d'extraire des secrets d'un fichier
  abimé.</p>
  <p>Le RFC liste ensuite les noms possibles pour les secrets. Ils
  dépendent de la version de TLS. Essayons avec <wikipedia
  name="cURL">curl</wikipedia> et une connexion TLS 1.3 :
  <code>
% export SSLKEYLOGFILE=./keys.sslkeylogfile

% curl https://www.example.com

% cat keys.sslkeylogfile 
SERVER_HANDSHAKE_TRAFFIC_SECRET 09d… 2d7d2e4090c6…
EXPORTER_SECRET 09d… 21cbb457ee72aa…
SERVER_TRAFFIC_SECRET_0 09d… 7e0027e87…
CLIENT_HANDSHAKE_TRAFFIC_SECRET 09d… 7ef813bf0…
CLIENT_TRAFFIC_SECRET_0 09d… f4a7ab14e…
  </code>
  Lisez le RFC et la norme TLS pour avoir des explications sur chaque
  secret. Un <link
  url="https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-sslkeylogfile-labels">registre
  IANA</link> des valeurs possibles a été créé et de nouveaux noms
  pourront y être ajoutés en suivant la procédure « Spécification
  nécessaire » du <rfc num="8126" local="true"/>.</p>
  <p>De toute façon, ce n'est pas vous qui allez le lire mais un
  logiciel comme <wikipedia>Wireshark</wikipedia>. En parlant de
  Wireshark, si on le configure pour lire ce fichier de secrets (dans
  le fichier <computer>~/.config/wireshark/preferences</computer>,
  mettre <computer>tls.keylog_file:
  /some/where/tmp/keys.sslkeylogfile</computer>), Wireshark saura
  déchiffrer la session TLS vue plus haut (même
  <wikipedia>pcap</wikipedia>). Vous voyez les requêtes <wikipedia
  name="Hypertext Transfer Protocol">HTTP</wikipedia> complètes, qui
  étaient masquées par le chiffrement : <image
  name="wireshark-elysee-tls-withkeys.png"/></p>
  <p>L'ordre des secrets dans le fichier n'est pas pertinent. Ah et,
  sinon, les noms de secret se terminant par un <wikipedia name="Tiret
  bas">tiret bas</wikipedia> et un chiffre sont là pour le cas où TLS
  génère plusieurs clés pendant une session (<rfc num="8446"
  local="true"/>, section 7.2). « nomDuSecret_0 » est la première.</p>
  <p>On peut aussi obtenir ainsi les clés <wikipedia xml:lang="en"
  name="Server Name Indication"
  anchor="Encrypted_Client_Hello">ECH</wikipedia> (<rfc num="9849"
  local="true"/>), celles du <foreign>outer ClientHello</foreign>.</p>
  <p>Évidemment, l'usage de cette possibilité d'écrire les clés
  secrètes annule tout l'intérêt de TLS. La section 3 du RFC insiste
  sur ce point. Cette possibilité est très pratique pour le déboguage
  mais ne doit surtout pas être utilisée avec des vraies sessions TLS
  sensibles. La lecture du fichier permet de tout déchiffrer et même
  la <wikipedia name="Confidentialité persistante">confidentialité
  persistante</wikipedia> est compromise si on a ce fichier. Il faut
  faire attention à ce que les fichiers SSLKEYLOGFILE ne circulent pas
  et ne soient pas accessibles par tout le monde (bien des programmes
  les créent avec les autorisations d'accès par défaut, qui peuvent
  être assez laxistes). Et, de manière tout aussi évidente, un
  programme ne doit pas écrire ces secrets s'il n'est pas certain que
  la demande vient du vrai utilisateur. (L'utilisation d'une
  <wikipedia name="Variable d'environnement">variable
  d'environnement</wikipedia> dans l'exemple avec curl satisfait cette
  condition.) Le RFC suggère aussi une option de compilation
  permettant de compiler l'application sans gestion de
  SSLKEYLOGFILE.</p>
  <p>Une note amusante : si la session TLS est de longue durée, un
  attaquant qui mettrait la main sur le fichier SSLKEYLOGFILE pourrait
  non seulement lire les données chiffrées mais également interférer
  avec la session tant qu'elle est en cours.</p>
  <p>Le format ainsi normalisé peut marcher avec diverses versions de
  TLS, y compris dépassées (<rfc num="8996" local="true"/>). Il
  fonctionne avec d'autres protocoles, s'ils utilisent le mécanisme de
  génération de clés de TLS, ce qui est le cas de <wikipedia
  name="Datagram Transport Layer Security">DTLS</wikipedia> (<rfc
  num="9147" local="true"/>) ou de <wikipedia>QUIC</wikipedia> (<rfc
  num="9000" local="true"/>).</p>
  <p>Le <wikipedia name="Type de médias">type de média</wikipedia>
  <computer><link
  url="https://www.iana.org/assignments/media-types/application/sslkeylogfile">application/sslkeylogfile</link></computer>
  a été ajouté au <link
  url="https://www.iana.org/assignments/media-types/media-types.xml#application">registre
  IANA</link>.</p>
  <p>Ce format SSLKEYLOGFILE est largement adopté par de nombreuses
  applications depuis des années, par exemple tous les <wikipedia
  name="Navigateur web">navigateurs Web</wikipedia>. (J'ai bien dit
  des applications ; contrairement à ce qu'on lit parfois, ce ne sont
  pas les <wikipedia name="Bibliothèque
  logicielle">bibliothèques</wikipedia> TLS comme
  <wikipedia>OpenSSL</wikipedia> qui le mettent en œuvre. Certains
  programmes utilisant OpenSSL ont cette fonction d'exportation de
  clés et d'autres pas.) Un exemple avec mon client <wikipedia
  name="Gemini (protocole)">Gemini</wikipedia> <link
  url="https://framagit.org/bortzmeyer/agunua/">Agunua</link> :
<code>
% export SSLKEYLOGFILE=./keys.sslkeylogfile
% agunua gemini.bortzmeyer.org
% cat keys.sslkeylogfile 
SERVER_HANDSHAKE_TRAFFIC_SECRET 724f8f07224… 8bcf43772bc21b45ad…
…
</code>
 Agunua est écrit en <wikipedia name="Python (langage)">Python</wikipedia> et activer cette
 fonction est simple, on s'appuie sur le fait
 qu'<wikipedia>OpenSSL</wikipedia> fournit une fonction pour demander
 à recevoir notification de la génération des clés :
<code>
def write_keys(conn, keys):
    keylogfile.write(keys.decode() + "\n")
    
if "SSLKEYLOGFILE" in os.environ:
    keylogfile = open(os.environ["SSLKEYLOGFILE"], "a")
    context.set_keylog_callback(write_keys)                               
</code>
  (Pour curl, cité plus haut, regarde le fichier
  <computer>lib/vtls/keylog.c</computer>.)
</p>
  <p>La question plus générale du déboguage des applications dans un
  monde où tout est chiffré avait fait l'objet de <link
  local="capitole-du-libre-2022">mon exposé à Capitole du Libre
  2022</link> dont voici <file
  name="capitole-libre-2022-tout-chiffre.pdf">mes supports</file>.
  </p>
</content>
</rfcdesc>
