Article de reference

Protocole de mot de passe distant sécurisé

Le protocole Secure Remote Password ( SRP ) est un protocole d'échange de clés authentifié par mot de passe (PAKE) augmenté, spécifiquement conçu pour contourner les brevets exi...

Le protocole Secure Remote Password ( SRP ) est un protocole d'échange de clés authentifié par mot de passe (PAKE) augmenté, spécifiquement conçu pour contourner les brevets existants.

Comme tous les protocoles PAKE, un espion ou une attaque de l'homme du milieu ne peut obtenir suffisamment d'informations pour deviner un mot de passe par force brute ou effectuer une attaque par dictionnaire sans interactions supplémentaires avec les parties pour chaque tentative. De plus, étant un protocole PAKE augmenté, le serveur ne stocke pas de données équivalentes au mot de passe. Cela signifie qu'un attaquant qui vole les données du serveur ne peut se faire passer pour le client que s'il effectue au préalable une recherche par force brute du mot de passe.

En termes simples, lors d'une authentification SRP (ou tout autre protocole PAKE), une partie (le « client » ou « utilisateur ») prouve à une autre partie (le « serveur ») qu'elle connaît le mot de passe, sans transmettre ce dernier ni aucune autre information permettant de le déduire. Le mot de passe reste toujours sur le client et est inconnu du serveur.

De plus, le serveur doit connaître le mot de passe (mais pas le mot de passe lui-même) pour établir la connexion sécurisée. Cela signifie que le serveur s'authentifie également auprès du client, ce qui empêche le phishing sans que l'utilisateur ait à analyser des URL complexes.

La seule propriété de sécurité mathématiquement prouvée de SRP est son équivalence à Diffie-Hellman face à un attaquant passif . Bien que mature et largement déployé, SRP est une conception ancienne dont certaines variantes présentent des faiblesses subtiles ; il n’est pas sécurisé contre les communications unifiées , ne résiste pas à toutes les attaques par précalcul , ses preuves formelles sont plus faibles et il n’offre aucune protection contre certains modèles d’attaques modernes. Pour ces raisons, SRP est aujourd’hui largement considéré comme obsolète. OPAQUE est le PAKE augmenté privilégié, tandis que CPace ou SPAKE2 sont préférés pour les scénarios de PAKE équilibrés où les deux parties partagent le mot de passe.

attaques par dictionnaire et il ne nécessite pas de tiers de confiance . Il garantit ainsi une preuve de mot de passe à divulgation nulle de connaissance de l’utilisateur au serveur. Dans la révision 6 du protocole, un seul mot de passe peut être deviné par tentative de connexion. L’une des propriétés intéressantes du protocole est que même si une ou deux de ses primitives cryptographiques sont compromises, il reste sécurisé. Le protocole SRP a été révisé à plusieurs reprises et est actuellement en version 6a.

Le protocole SRP crée une clé privée de grande taille partagée entre les deux parties, de manière similaire à l'échange de clés Diffie-Hellman. Le client possède le mot de passe de l'utilisateur, tandis que le serveur dispose d'un vérificateur cryptographique dérivé de ce mot de passe. La clé publique partagée est générée à partir de deux nombres aléatoires, l'un produit par le client et l'autre par le serveur, et uniques pour chaque tentative de connexion. Lorsque des communications chiffrées et une authentification sont requises, le protocole SRP est plus sûr que le protocole SSH et plus rapide que l'échange de clés Diffie-Hellman avec signature. De plus, contrairement à Kerberos , il est indépendant des tiers .

Le protocole SRP, version 3, est décrit dans la RFC 2945. La version 6a de SRP est également utilisée pour l'authentification par mot de passe fort dans SSL/TLS (dans TLS-SRP ) et d'autres normes telles que EAP et SAML , et fait partie de l'IEEE 1363.2 et de l'ISO/IEC 11770-4.

Protocole

La notation suivante est utilisée dans cette description du protocole, version 6 :

  • On choisit q et N = 2q + 1 de sorte qu'ils soient premiers ( q est donc un nombre premier de Sophie Germain et N un nombre premier sûr ). N doit être suffisamment grand pour que le calcul des logarithmes discrets modulo N soit impossible.
  • Tous les calculs arithmétiques sont effectués dans l' anneau des entiers modulo N. Cela signifie que ci-dessous, g x
  • H () est une fonction de hachage ; par exemple, SHA-256.
  • Le paramètre k est déterminé conjointement ; dans SRP-6, k = 3, tandis que dans SRP-6a, il est déterminé à partir de N et g : k = H ( N , g ). Il sert à empêcher une tentative de devinette à deux candidats lorsqu’un attaquant actif usurpe l’identité du serveur.
  • s est un sel .
  • p )) . L'utilisation de sel aléatoire s et calcule x = H ( s , p ) et v = gx équivalent au mot de passe en clair p . Cette étape est terminée avant que le système ne soit utilisé pour l'inscription de l'utilisateur auprès de Steve. Il est à noter que le sel s est partagé et échangé ultérieurement pour négocier une clé de session ; sa valeur pourrait donc être choisie par l'une ou l'autre partie, mais c'est Carol qui le fait afin de pouvoir enregistrer XOR H ( g ) | H ( I ) | s | A | B | K Carol ] . Steve vérifie M 1 .
  • Steve → Carol : def H ( * args ) -> int : Une fonction de hachage unidirectionnelle.""" a = ":" . join ( str ( a ) for a in args ) return int ( hashlib . sha256 ( a . encode ( "utf-8" )) . hexdigest (), 16 )def cryptrand ( n : int = 1024 ) : return random.SystemRandom ( ) . getrandbits ( n ) % N# Un grand nombre premier sûr (N = 2q+1, où q est premier) # Tous les calculs arithmétiques sont effectués modulo N # (généré à l'aide de "openssl dhparam -text 1024") N = 00:c0:37:c3:75:88:b4:32:98:87:e6:1c:2d: a3:32: 4b:1b:a4:b8:1a:63:f9:74:8f:ed:2d:8a:41:0c: 2f: c2:1b:12:32:f0:d3:bf:a0:24:27:6c:fd:88:44:81: 97:aa:e4:86:a6:3b:fc:a7:b8:bf:77:54:df:b3:27: c7:20:1f:6f:d1:7f:d7:fd:74:15:8b:d3:1c:e7:72: c9:f5:f8:ab:58:45:48:a9:9a:75:9b:5a:2c:05:32: 16:2b:7b:62:18:e8:f1:42:bc:e2:c3:0d:77:84:68: 9a:48:3e:09:5e:70:16:18:43:79:13:a8:c3:9c:3d : d0:d4:ca:3c:50:0b:88:5f:e3"""N = int ( . join ( N.split ( )) . replace ( ":" , " " ), 16 ) g = 2 # Générateur modulo Nk = H ( N , g ) # Paramètre multiplicateur (k=3 dans l'ancien SRP-6)F = '#0x' # Spécificateur de formatprint ( "#. H, N, g et k sont connus à l'avance du client et du serveur :" ) print ( f ' { H = } { N = :{ F }} { g = :{ F }} { k = :{ F }} ' )print ( " 0. Le serveur stocke (I, s, v) dans sa base de données de mots de passe" )# Le serveur doit d'abord générer le vérificateur de mot de passe I = "person" # Nom d'utilisateur p = "password1234" # Mot de passe s = cryptrand ( 64 ) # Sel pour l'utilisateur x = H ( s , I , p ) # Clé privée v = pow ( g , x , N ) # Vérificateur de mot de passeprint ( f ' { I = } { p = } { s = :{ F }} { x = :{ F }} { v = :{ F }} ' )# 0. Le serveur stocke (I, s, v) dans sa base de données de mots de passe # I = 'personne' # p = 'password1234' # s = 0x67bc8932cfd26a49 # x = 0x98a4bce8dde877762a90222f1a1161eba9248590a47eb83aa9e5bd7ecda5368d # v = 0xa7e2038e675d577ac0f318999cab67bba7ec2daf45d2d09f7911b1b78d2fc7f963cd0ac8f17851e0516f059e453672c3b70fcecf5f6843180b271a bdd01f552ccda7b24fe4719336409cbc1352f8517be651b8935cc0b74ff2819fa07a3f031537d4cfd9f8df7b788a5f2f88e1cd4106b35c38b3d7205a# <démo> --- arrêt ---print ( " 1. Le client envoie le nom d'utilisateur I et la valeur éphémère publique A au serveur" ) a = cryptrand () A = pow ( g , a , N ) print ( f " { I =} { A = :{ F }} " ) # client->serveur (I, A)# 1. Le client envoie au serveur le nom d'utilisateur I et la valeur publique éphémère A # I = 'personne' # A = 0x678556a7e76581e051af656e8cee57ae46df43f1fce790f7750a3ec5308a85da4ec4051e5cb74d3e463685ee975a2747cf49035be67c931b56e793 f23ea3524af8909dcfbc8675d872361025bf884778587ac49454a57c53a011ac2be2839bfb51bf7847a49a483aba870dc7a8b467a81cec91b8ae7813# <démo> --- arrêt ---print ( " 2. Le serveur envoie le sel s de l'utilisateur et la valeur éphémère publique B au client" ) b = cryptrand () B = ( k * v + pow ( g , b , N )) % N print ( f " { s = :{ F }} { B = :{ F }} " ) # serveur->client(s, B)# 2. Le serveur envoie au client le sel s de l'utilisateur et sa valeur éphémère publique B # s = 0x67bc8932cfd26a49 # B = 0xb615a0a5ea6abf138077bbd869f6a8da37dfc0b7e06a9f5fac5c1e4109c6302cb3e94dcc2cc76da7b3d87d7e9b68a1db998ab239cfde609f3f7a1e ce4a491ce3d9a665c20cf4e4f06730daaa8f52ed61e45bbb67cdc337bf648027ffa7f0f215d5ebe43f9f51832518f1142266aae0dfa960e0082b5154# <démo> --- arrêt ---print ( " 3. Le client et le serveur calculent le paramètre de brouillage aléatoire" ) u = H ( A , B ) # Paramètre de brouillage aléatoire print ( f " { u = :{ F }} " )# 3. Le client et le serveur calculent le paramètre de brouillage aléatoire # u = 0x796b07e354c04f672af8b76a46560655086355a9bbce11361f01b45d991c0c52# <démo> --- arrêt ---print ( " 4. Le client calcule la clé de session" ) x = H ( s , I , p ) S_c = pow ( B - k * pow ( g , x , N ), a + u * x , N ) K_c = H ( S_c ) print ( f " { S_c = :{ F }} { K_c = :{ F }} " )# 4. Le client calcule la clé de session # S_c = 0x699170aff6e9f08ed09a1dff432bf0605b8bcba05aadcaeea665757d06dbda4348e211d16c10ef4678585bcb2809a83c62b6c19d97901274ddafd4075f90604c06baf036af587af8540342b47867eaa22b9ca5e35ac14c8e85a0c4e623bd855828dffd513cea4d829c407137a0dd81ab4cde8a904c45cc # K_c = 0x43f8df6e1d2ba762948c8316db5bf03a7af49391742f5f51029630711c1671e# <démo> --- arrêt ---print ( " 5. Le serveur calcule la clé de session" ) S_s = pow ( A * pow ( v , u , N ), b , N ) K_s = H ( S_s ) print ( f " { S_s = :{ F }} { K_s = :{ F }} " )# 5. Le serveur calcule la clé de session # S_s = 0x699170aff6e9f08ed09a1dff432bf0605b8bcba05aadcaeea665757d06dbda4348e211d16c10ef4678585bcb2809a83c62b6c19d97901274ddafd4075f90604c06baf036af587af8540342b47867eaa22b9ca5e35ac14c8e85a0c4e623bd855828dffd513cea4d829c407137a0dd81ab4cde8a904c45cc # K_s = 0x43f8df6e1d2ba762948c8316db5bf03a7af49391742f5f51029630711c1671e# <démo> --- arrêt ---print ( " 6. Le client envoie la preuve de la clé de session au serveur" ) M_c = H ( H ( N ) ^ H ( g ), H ( I ), s , A , B , K_c ) print ( f " { M_c = :{ F }} " ) # client->serveur(M_c) ; le serveur vérifie M_c# 6. Le client envoie une preuve de clé de session au serveur # M_c = 0x75500df4ea36e06406ac1f8a8241429b8e90a8cba3adda3405c07f19ea3101e8# <démo> --- arrêt ---print ( " 7. Le serveur envoie la preuve de la clé de session au client" ) M_s = H ( A , M_c , K_s ) print ( f " { M_s = :{ F }} " ) # serveur->client(M_s) ; ​​le client vérifie M_s# 7. Le serveur envoie une preuve de clé de session au client # M_s = 0x182ed24d1ad2fb55d2268c46b42435d1ef02e0fc49f647c03dab8b2a48b0bd3d

Pièges liés à la mise en œuvre

Attaque par force brute hors ligne avec messagerie serveur en l'absence de vérification de clé

Si le serveur envoie un message chiffré sans attendre la vérification du client, un attaquant peut mener une attaque par force brute hors ligne, similaire au cassage de hachage. Cela peut se produire si le serveur envoie un message chiffré dans le deuxième paquet, en même temps que le sel et B , ou si la vérification de la clé est ignorée et que c'est le serveur (et non le client) qui envoie le premier message chiffré . Cette approche est tentante car, dès le premier paquet, le serveur dispose de toutes les informations nécessaires pour calculer la clé partagée K.

L'attaque se déroule comme suit :

  1. Carol → Steve : générer une valeur aléatoire a ; envoyer OpenSSL version 1.0.1 ou ultérieure.
  2. Botan (la bibliothèque de cryptographie C++) contient une implémentation de SRP-6a
  3. TLS-SRP est un ensemble de suites de chiffrement pour la sécurité de la couche transport qui utilise SRP.
  4. srp-client Implémentation SRP-6a en JavaScript (compatible avec RFC 5054), open source, sous licence Mozilla Public License (MPL).
  5. La bibliothèque JavaScript Crypto inclut une implémentation JavaScript du protocole SRP, open source et sous licence BSD .
  6. Gnu Crypto fournit une implémentation Java sous licence GNU General Public License avec l'« exception bibliothèque », qui autorise son utilisation comme bibliothèque en conjonction avec des logiciels non libres.
  7. La Légion du Château Bouncy propose des implémentations Java et C# sous licence MIT .
  8. Nimbus SRP est une bibliothèque Java fournissant un générateur de vérificateurs, ainsi que des sessions côté client et côté serveur. Elle inclut des interfaces pour les clés de mot de passe personnalisées et les routines de gestion des messages de preuve côté client et serveur. Sans dépendances externes, elle est distribuée sous licence Apache 2.0 .
  9. srplibcpp est une implémentation C++ basée sur DragonSRP est une implémentation modulaire C++ qui fonctionne actuellement avec OpenSSL .
  10. Json2Ldap assure l'authentification SRP-6a auprès des serveurs d'annuaire LDAP .
  11. Implémentation de csrp SRP-6a en C.
  12. Implémentation de Crypt-SRP SRP-6a en Perl .
  13. Implémentation de pysrp SRP-6a en Python (compatible avec csrp ).
  14. Implémentation de py3srp SRP-6a en Python 3 pur .
  15. srptools Outils pour implémenter l'authentification par mot de passe distant sécurisé (SRP) en Python . Bibliothèques compatibles vérifiées .
  16. Le système de comptes du framework web Meteor implémente le SRP pour l'authentification par mot de passe.
  17. Implémentation de SRP-6a en Ruby (srp-rb ) .
  18. falkmueller démonstration SRP-6a implémentation de la conception du protocole Stanford SRP en JavaScript et PHP sous la licence MIT .
  19. srp-6a-demo Implémentation SRP-6a en PHP et JavaScript .
  20. thinbus-srp-js est une implémentation JavaScript de SRP-6a . Elle inclut des classes Java compatibles utilisant Nimbus SRP. Une application de démonstration utilisant Spring Security est le 22 février 2014 sur la Wayback Machine) . Une autre application de démonstration, permettant l'authentification auprès d'un serveur PHP , est également fournie . Ce package est distribué sous licence Apache .
  21. La bibliothèque cryptographique JavaScript de Stanford (SJCL) implémente le SRP pour l'échange de clés.
  22. node-srp est une implémentation JavaScript client et serveur (node.js) de SRP.
  23. Implémentation de SRP6 pour C# et Java en C# et Java.
  24. ALOSRPAuth est une implémentation Objective-C de SRP-6a.
  25. go-srp est une implémentation Go de SRP-6a.
  26. tssrp6a est une implémentation TypeScript de SRP-6a.
  27. La bibliothèque Java IceNet Cryptography permet de développer des applications Spring Boot basées sur la cryptographie. Elle implémente la norme SRP-6a et est distribuée sous licence Apache .
  28. Implémentation SRP -6a en .NET
  29. Apple HomeKit utilise le protocole SRP lors de l'association avec des accessoires et appareils domotiques « intelligents ».
  30. Authentification Proton Mail pour le chiffrement des e-mails
  31. SRP est une implémentation Go de SRP, utilisée pour authentifier les utilisateurs sur Posterity .

Histoire

Le projet SRP a débuté en 1997. Deux approches différentes pour corriger une faille de sécurité dans SRP-1 ont abouti à SRP-2 et SRP-3. SRP-3 a été présenté pour la première fois en 1998 lors d'une conférence. La RFC 2945, qui décrit SRP-3 avec SHA1, a été publiée en 2000. SRP-6, qui corrige les attaques par devinette « deux pour un » et par inversion de l'ordre des messages, a été publié en 2002. SRP-6a est apparu dans la bibliothèque officielle « libsrp » dans sa version 2.1.0, datée de 2005. SRP-6a est référencé dans les normes sous la forme :

  • ISO/IEC 11770-4:2006 « Mécanisme d'accord clé 2 » (appelle la méthode « SRP-6 », mais a le calcul k de 6a)
  • RFC 5054 TLS-SRP de 2007 (à nouveau appelé « SRP-6 », mais corrigé dans l'erratum )
  • IEEE Std 1363.2-2008 « DLAPKAS-SRP6 » (également appelé « SRP-6 »)

IEEE 1363.2 inclut également une description de « SRP5 », une variante remplaçant le logarithme discret par une courbe elliptique proposée par Yongge Wang en 2001. Elle décrit également SRP-3 tel qu'il se trouve dans RFC 2945.