TLS & Perfect Forward Secrecy

Vincent Bernat

Une fois la clé pri­vée d’un site HTTPS quel­conque com­pro­mise, un at­ta­quant est ca­pable de mon­ter une at­taque par in­ter­cep­tion (MITM) afin de dé­chif­frer toutes les com­mu­ni­ca­tions avec le site com­pro­mis. Si l’at­taque est dé­tec­tée, le cer­ti­fi­cat sera ré­vo­qué via une CRL ou un pro­to­cole tel que OCSP. Mal­heu­reu­se­ment, l’at­ta­quant peut aussi avoir en sa po­si­tion une co­pie des com­mu­ni­ca­tions pas­sées de clients avec le ser­veur. Il est alors ca­pable de dé­chif­frer celles-ci et y trou­ver des in­for­ma­tions sensibles.

La pro­priété de for­ward se­crecy1 per­met à une in­for­ma­tion chif­frée au­jourd’hui de res­ter confi­den­tielle en cas de com­pro­mis­sion fu­ture de la clé pri­vée d’un cor­res­pon­dant. C’est un mé­ca­nisme as­sez coû­teux en cal­culs et de nom­breux ser­veurs font donc l’im­passe sur ce­lui-ci. Google a ré­cem­ment an­noncé le sup­port du for­ward se­crecy pour tous ses sites ac­ces­sibles en HTTPS. Adam Lan­gley a ré­digé un ar­ticle plus dé­taillé sur ce qui a été réa­lisé pour amé­lio­rer l’ef­fi­ca­cité d’un tel mé­ca­nisme : avec quelques col­lègues, il a écrit une im­plé­men­ta­tion plus ef­fi­cace pour OpenSSL, ba­sée sur la cryp­to­gra­phie sur les courbes el­liptiques.

Mise à jour (08.2019)

Bien que le contenu de cet ar­ticle soit tou­jours per­ti­nent, il est im­por­tant de com­prendre qu’il a été ré­digé en 2011 et qu’il ne prend pas en compte cer­tains as­pects contem­po­rains, no­tam­ment la chute de RC4 en tant qu’al­go­rithme ap­pro­prié et l’om­ni­pré­sence du for­ward se­crecy dans les dé­ploie­ments actuels.

Sans forward secrecy#

Pour com­prendre ce que le for­ward se­crecy tente de ré­soudre, re­gar­dons ce qui se passe lors d’une poi­gnée de mains TLS en uti­li­sant une suite de chif­fre­ment telle que AES128-SHA. Du­rant celle-ci, le ser­veur va pré­sen­ter son cer­ti­fi­cat au client et les deux par­ties vont s’ac­cor­der sur la construc­tion d’un se­cret maître uti­lisé par la suite pour pro­té­ger la connexion.

Déroulement d'une poignée de mains TLS
Poignée de mains TLS complète

Un pre­mier se­cret de 48 oc­tets est gé­néré et chif­fré par le client avec la clé pu­blique du ser­veur. Il est en­voyé du­rant la troi­sième étape de la poi­gnée de mains, lors de l’en­voi du mes­sage Client Key Ex­change. Le se­cret maître est cal­culé à par­tir de ce­lui-ci et des va­leurs aléa­toires qui ont été trans­mises dans les mes­sages Client Hello et Ser­ver Hello.

Ce pro­cédé est sûr à condi­tion que seul le ser­veur puisse dé­chif­frer le pre­mier se­cret (à l’aide de sa clé pri­vée) en­voyé par le client. Sup­po­sons main­te­nant qu’un at­ta­quant en­re­gistre tous les échanges entre le ser­veur et ses nom­breux clients pen­dant plu­sieurs mois. Deux ans plus tard, le ser­veur est dé­com­mis­sionné et jeté à la benne. L’at­ta­quant en pro­fite pour sub­ti­li­ser le disque et y trouve la clé pri­vée. Il est dé­sor­mais ca­pable de dé­chif­frer toutes les com­mu­ni­ca­tions qu’il a pu in­ter­cep­ter. Cela lui per­met de ré­cu­pé­rer, par exemple, des mots de passe en­core va­lides au­jourd’hui.

Le pro­blème prin­ci­pal est que la clé pri­vée est à la fois uti­li­sée pour l’au­then­ti­fi­ca­tion du ser­veur et pour le chif­fre­ment du se­cret par­tagé. Alors que l’au­then­ti­fi­ca­tion n’est réel­le­ment im­por­tante que pen­dant le laps de temps où la com­mu­ni­ca­tion entre les deux par­ties est éta­blie, le chif­fre­ment doit être ca­pable de pro­té­ger un se­cret pen­dant plu­sieurs années.

Algorithme de Diffie-Hellman#

Une so­lu­tion consiste à n’uti­li­ser la clé pri­vée que pour l’au­then­ti­fi­ca­tion et né­go­cier un se­cret par­tagé to­ta­le­ment in­dé­pen­dant de celle-ci. Il existe un pro­to­cole à cet ef­fet : l’al­go­rithme de Dif­fie-Hell­man. Il s’agit d’une mé­thode d’échange de clefs ne né­ces­si­tant au­cune connais­sance préa­lable entre les deux par­ties. Voici com­ment cela fonc­tionne dans le cadre de TLS :

  1. Le ser­veur doit ini­tia­le­ment dis­po­ser de (avec l’aide d’une com­mande comme openssl dhparam par exemple) :

  2. Le ser­veur choi­sit un nombre aléa­toire aa et cal­cule ga mod pg^a \bmod p. Après l’en­voi du mes­sage Cer­ti­fi­cate, il en­voie un mes­sage Ser­ver Key Ex­change (in­clus lors de l’étape 3 mais non re­pré­senté dans la poi­gnée de mains dé­crite pré­cé­dem­ment) conte­nant, en clair mais au­then­ti­fié avec sa clé pri­vée :

    • la va­leur aléa­toire is­sue du mes­sage Client Hello,
    • la va­leur aléa­toire is­sue du mes­sage Ser­ver Hello,
    • pp, gg,
    • ga mod p=Ag^a\bmod p=A.
  3. Le client vé­ri­fie la si­gna­ture et choi­sit un nombre aléa­toire bb. Il en­voie alors gb mod p=Bg^b \bmod p=B dans un mes­sage Client Key Ex­change. Il cal­cule Ab mod p=gab mod pA^b\bmod p=g^{ab}\bmod p qui consti­tue le pre­mier se­cret du­quel est dé­rivé le se­cret maître.

  4. Le ser­veur re­çoit BB et cal­cule Ba mod p=gab mod pB^a\bmod p=g^{ab}\bmod p qui est iden­tique au pre­mier se­cret cal­culé par le client.

La clé pri­vée n’a été uti­li­sée qu’à des fins d’au­then­ti­fi­ca­tion. Un es­pion ne pourra connaître que pp, gg, ga mod pg^a\bmod p et gb mod pg^b\bmod p. Cal­cu­ler gab mod pg^{ab}\bmod p à par­tir de ces va­leurs est connu sous le nom du pro­blème du lo­ga­rithme dis­cret. Au­cune so­lu­tion ef­fi­cace à ce pro­blème n’a été dé­cou­verte pour le mo­ment.

Tel que dé­crit ci-des­sus, l’échange de Dif­fie-Hell­man uti­lise sys­té­ma­ti­que­ment de nou­velles va­leurs pour aa et bb. On parle alors d’échange de Dif­fie-Hell­man éphé­mère (Ephe­me­ral Dif­fie-Hell­man, EDH ou DHE). Des suites de chif­fre­ment telles que DHE-RSA-AES128-SHA l’uti­lisent pour ob­te­nir la pro­priété de per­fect for­ward se­crecy2.

Afin d’ob­te­nir un bon ni­veau de sé­cu­rité, les pa­ra­mètres uti­li­sés doivent être de la même taille que la clé pri­vée (la sé­cu­rité du lo­ga­rithme dis­cret est en­vi­ron équi­va­lente à celle four­nie par la fac­to­ri­sa­tion de deux grands nombres pre­miers). Les opé­ra­tions d’ex­po­nen­tia­tion sur de tels grands nombres sont alors par­ti­cu­liè­re­ment longues et im­pactent la per­for­mance de la poi­gnée de mains comme on peut le voir sur le bench­mark ci-dessous :

Graphique de comparaison de la vitesse avec et sans Diffie-Hellman
Performances de stud sur 6 cœurs, avec et sans Diffie-Hellman pour une clé de 1024 bits

Mise à jour (05.2015)

L’at­taque « Log­jam » a dé­mon­tré que la sé­cu­rité de Dif­fie-Hell­man est plus faible que pré­vue. No­tam­ment, la réuti­li­sa­tion du même nombre pre­mier par de nom­breux ser­veurs per­met de pré­cal­cu­ler une at­taque pour cas­ser les connexions pro­té­gées par ce même nombre. Il est donc im­por­tant que la taille du nombre pre­mier choisi soit équi­va­lente à la taille de la clé RSA (au moins 2048 bits).

Diffie-Hellman et les courbes elliptiques#

L’échange de Dif­fie-Hell­man peut éga­le­ment s’ef­fec­tuer à l’aide de la cryp­to­gra­phie sur les courbes el­lip­tiques, ba­sée sur la struc­ture des courbes el­lip­tiques sur un corps fini. Pour com­prendre com­ment tout cela fonc­tionne en dé­tail, l’ar­ticle de Wi­ki­pé­dia sur les courbes el­lip­tiques est un bon point de dé­part. Les courbes el­lip­tiques per­mettent d’ob­te­nir un ni­veau de sé­cu­rité équi­valent à RSA en uti­li­sant des clefs plus pe­tites. Par exemple, une courbe el­lip­tique de 224 bits per­met d’ob­te­nir un ni­veau de sé­cu­rité si­mi­laire à une clé RSA de 2048 bits.

Un peu de théorie#

L’échange de Dif­fie-Hell­man dé­crit au­pa­ra­vant peut fa­ci­le­ment être adapté pour uti­li­ser les courbes el­lip­tiques. Au lieu d’uti­li­ser deux en­tiers pp et gg, on part d’une courbe el­lip­tique, y2=x3+αx+βy^2=x^3+\alpha x+\beta, d’un en­tier pre­mier pp et d’un point de base GG. Tous ces pa­ra­mètres sont pu­blics. En fait, même s’ils peuvent être gé­né­rés par le ser­veur, ils sont gé­né­ra­le­ment choi­sis dans un ca­ta­logue.

L’uti­li­sa­tion des courbes el­lip­tiques est nor­ma­li­sée comme une ex­ten­sion de TLS et dé­crite dans la RFC 4492. Contrai­re­ment à l’échange de Dif­fie-Hell­man clas­sique, le client et le ser­veur doivent se mettre d’ac­cord sur les di­vers pa­ra­mètres à uti­li­ser. Cet ac­cord se ma­té­ria­lise es­sen­tiel­le­ment dans les mes­sages Client Hello et Ser­ver Hello. Bien qu’il soit pos­sible d’uti­li­ser une courbe el­lip­tique ar­bi­traire, les na­vi­ga­teurs se contentent d’in­di­quer le sup­port de quelques courbes pré­dé­fi­nies telles que NIST P-256, P-384 et P-521. L’échange de clefs est en­suite très si­mi­laire au cas classique :

  1. Le ser­veur choi­sit un en­tier aléa­toire aa et cal­cule aGaG qui sera en­voyé en clair, mais si­gné avec la clé pri­vée du ser­veur, dans un mes­sage Ser­ver Key Ex­change.
  2. Le client vé­ri­fie la si­gna­ture et choi­sit un nombre aléa­toire bb. Il cal­cule et en­voie bGbG dans un mes­sage Client Key Ex­change. Il cal­cule éga­le­ment b⋅aG=abGb\cdot aG=abG qui est le pre­mier se­cret à par­tir du­quel est cal­culé le se­cret maître.
  3. Le ser­veur re­çoit bGbG et cal­cule a⋅bG=abGa\cdot bG=abG. Il peut alors dé­ri­ver le même se­cret maître que le client.

Un es­pion verra pas­ser les va­leurs aGaG et bGbG. Il n’existe au­cun moyen connu de cal­cu­ler ef­fi­ca­ce­ment abGabG à par­tir de ces va­leurs et des pa­ra­mètres de la courbe.

Uti­li­ser une suite de chif­fre­ment telle que ECDHE-RSA-AES128-SHA (avec la courbe NIST P-256 par exemple) consti­tue déjà une amé­lio­ra­tion no­table des per­for­mances par rap­port à la suite DHE-RSA-AES128-SHA grâce aux nombres plus pe­tits mis en jeu.

Les na­vi­ga­teurs ne sup­portent qu’une poi­gnée de courbes el­lip­tiques et ces der­nières ont été choi­sies entre autres pour leurs struc­tures fa­ci­li­tant des im­plé­men­ta­tions ef­fi­caces. Le tra­vail ef­fec­tué par Bodo Möl­ler, Emi­lia Käs­per et Adam Lan­gley consiste à four­nir une im­plé­men­ta­tion op­ti­mi­sée pour les pro­ces­seurs 64 bits des courbes NIST P-224, P-256 et P-521 pour OpenSSL. Pour ob­te­nir plus de dé­tails sur le su­jet, vous pou­vez lire la fin de l’in­tro­duc­tion aux courbes el­lip­tiques d’Adam Lan­gley puis le court pa­pier d’Emi­lia Käs­per sur l’op­ti­mi­sa­tion de l’im­plé­men­ta­tion de la courbe NIST P-224.

En pratique#

Tout d’abord, le sup­port des courbes el­lip­tiques n’est pas pré­sent dans tous les na­vi­ga­teurs. Les ver­sions ré­centes de Fi­re­fox et de Chrome sup­portent les courbes NIST P-256, P-384 et P-521 mais en ce qui concerne In­ter­net Ex­plo­rer sous Win­dows XP, il n’y a rien pour le mo­ment. Il faut donc conti­nuer à ac­cep­ter des suites de chif­fre­ment classiques.

Une ver­sion ré­cente d’OpenSSL est né­ces­saire. Le sup­port pour les suites ECDHE est ap­paru dans OpenSSL 1.0.0. Il est simple de vé­ri­fier leur pré­sence avec openssl ciphers ECDH. Pour uti­li­ser la ver­sion op­ti­mi­sée pour 64 bits, il faut se tour­ner vers la fu­ture ver­sion 1.0.1 en la confi­gu­rant avec l’op­tion enable-ec_nistp_64_gcc_128. Une ver­sion ré­cente de GCC est alors éga­le­ment requise.

En­suite, il faut choi­sir les suites de chif­fre­ment ap­pro­priées. Si le for­ward se­crecy est op­tion­nel, vous pou­vez par­tir sur ECDHE-RSA-AES128-SHA:AES128-SHA:RC4-SHA qui est com­pa­tible avec la plu­part des na­vi­ga­teurs. Si le for­ward se­crecy est obli­ga­toire, il fau­dra par­tir sur quelque chose comme ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:EDH-DSS-DES-CBC3-SHA.

Éga­le­ment, il faut s’as­su­rer que l’ordre des suites de chif­fre­ment est res­pecté. Pour nginx, il s’agit de la di­rec­tive ssl_prefer_server_ciphers on tan­dis que pour Apache, c’est SSLHonorCipherOrder on.

Mise à jour (11.2011)

Il est éga­le­ment né­ces­saire de vé­ri­fier que le sup­port pour ECDHE est pré­sent dans le ser­veur web que vous sou­hai­tez uti­li­ser. Pour nginx, le sup­port a été ajouté dans la ver­sion 1.0.6 et dans la ver­sion 1.1.0. La courbe el­lip­tique sé­lec­tion­née par dé­faut est NIST P-256 et il est pos­sible d’en choi­sir une autre avec la di­rec­tive ssl_ecdh_curve. Pour Apache, le sup­port existe de­puis la ver­sion 2.3.3 mais n’est pas pré­sent dans la branche stable. Ajou­ter le sup­port pour ECDHE n’est pas très dif­fi­cile. À titre d’exemple, vous pou­vez consul­ter com­ment j’ai ajouté son sup­port dans stud. Le pro­blème est si­mi­laire pour les suites ba­sées sur DHE ; dans ce cas, il peut aussi être né­ces­saire de spé­ci­fier les pa­ra­mètres DH à uti­li­ser (gé­né­rés avec openssl dhparam) à l’aide de la di­rec­tive adé­quate ou en les in­cluant après le cer­ti­fi­cat. Un ar­ticle de Im­merda Tech­blog four­nit quelques in­for­ma­tions sup­plé­men­taires sur ce point précis.

L’im­plé­men­ta­tion des ti­ckets de ses­sion TLS peut être in­com­pa­tible avec le for­ward se­crecy se­lon leur im­plé­men­ta­tion. Quand la clé pro­té­geant les ti­ckets est gé­né­rée aléa­toi­re­ment au dé­mar­rage du ser­veur, la même clé peut être uti­li­sée pen­dant des mois. Cer­taines im­plé­men­ta­tions 3 optent pour une clé dé­ri­vée de la clef pri­vée. Dans ce cas, le for­ward se­crecy est rendu to­ta­le­ment in­ef­fi­cace. Il est alors pré­fé­rable de désac­ti­ver tickets.

La com­mande openssl s_client -tls1 -cipher ECDH -connect 127.0.0.1:443 per­met de vé­ri­fier que tout fonc­tionne comme attendu.

Quelques benchmarks#

En uti­li­sant l’ou­til de mi­cro-bench­mark uti­lisé lors de mon pré­cé­dent ar­ticle, il est pos­sible de com­pa­rer l’ef­fi­ca­cité de cha­cune des suites de chif­fre­ment per­met­tant d’ob­te­nir le for­ward secrecy :

Graphique de comparaison avec/sans DHE/ECDHE
Performance de 1000 poignées de mains avec différentes suites de chiffrement (RSA 2048, DHE, ECDHE, ECDHE optimisé)

J’ai uti­lisé une pré-ver­sion d’OpenSSL 1.0.1 da­tant du 25 no­vembre 2011. La ver­sion op­ti­mi­sée d’ECDHE est celle ob­te­nue en uti­li­sant l’op­tion enable-ec_nistp_64_gcc_128 en confi­gu­rant OpenSSL.

Concen­trons-nous sur la par­tie ser­veur. Ac­ti­ver la suite DHE-RSA-AES128-SHA grève les per­for­mances d’un fac­teur 3 tan­dis que l’uti­li­sa­tion de ECDHE-RSA-AES128-SHA n’im­plique qu’une pé­na­lité de 27 %. La ver­sion op­ti­mi­sée per­met de ré­duire la pé­na­lité à 15 % par rap­port à AES128-SHA. À no­ter qu’il convient de pon­dé­rer de telles pé­na­li­tés en fonc­tion du nombre de poi­gnées de mains com­plè­te­ment ef­fec­tuées par les clients. Ainsi, si ceux-ci uti­lisent trois fois sur quatre une poi­gnée de main rac­cour­cie (re­prise d’une an­cienne ses­sion TLS), il faut di­vi­ser par quatre l’im­pact sur les per­formances.

Le coût d’une suite uti­li­sant ECDHE semble donc être plu­tôt rai­son­nable par rap­port au gain de sé­cu­rité ap­porté. Il s’agit donc d’une op­tion à consi­dé­rer at­ten­ti­ve­ment lors du choix des suites de chif­fre­ment au­torisées.