stringtranslate.com

Protocolo de contraseña remota segura

El protocolo de contraseña remota segura ( SRP ) es un protocolo de intercambio de claves autenticadas por contraseña (PAKE) aumentado, diseñado específicamente para evitar patentes existentes. [1]

Al igual que todos los protocolos PAKE, un espía o intermediario no puede obtener suficiente información para poder adivinar una contraseña por fuerza bruta o aplicar un ataque de diccionario sin más interacciones con las partes para cada intento de adivinación. Además, al ser un protocolo PAKE aumentado, el servidor no almacena datos equivalentes a las contraseñas. [2] Esto significa que un atacante que roba los datos del servidor no puede hacerse pasar por el cliente a menos que primero realice una búsqueda de contraseña por fuerza bruta.

En términos sencillos, durante la autenticación SRP (o cualquier otro protocolo PAKE), una de las partes (el "cliente" o "usuario") demuestra a la otra parte (el "servidor") que conoce la contraseña, sin enviar la contraseña en sí ni ninguna otra información de la que se pueda derivar la contraseña. La contraseña nunca sale del cliente y es desconocida para el servidor.

Además, el servidor también necesita conocer la contraseña (pero no la contraseña en sí) para poder iniciar la conexión segura. Esto significa que el servidor también se autentica ante el cliente, lo que evita el phishing sin depender de que el usuario analice URL complejas.

La única propiedad de seguridad matemáticamente probada de SRP es que es equivalente a Diffie-Hellman contra un atacante pasivo . [3] Los PAKE más nuevos como AuCPace [4] y OPAQUE ofrecen garantías más sólidas. [5]

Descripción general

El protocolo SRP tiene varias propiedades deseables: permite que un usuario se autentique a sí mismo en un servidor, es resistente a ataques de diccionario montados por un espía y no requiere un tercero de confianza . Transmite de manera efectiva una prueba de contraseña de conocimiento cero del usuario al servidor. En la revisión 6 del protocolo, solo se puede adivinar una contraseña por intento de conexión. Una de las propiedades interesantes del protocolo es que incluso si uno o dos de los primitivos criptográficos que utiliza son atacados, sigue siendo seguro. El protocolo SRP ha sido revisado varias veces y actualmente se encuentra en la revisión 6a.

El protocolo SRP crea una clave privada grande compartida entre las dos partes de una manera similar al intercambio de claves Diffie-Hellman, en el que el lado del cliente tiene la contraseña del usuario y el lado del servidor tiene un verificador criptográfico derivado de la contraseña. La clave pública compartida se deriva de dos números aleatorios, uno generado por el cliente y el otro generado por el servidor, que son únicos para el intento de inicio de sesión. En los casos en los que se requieren comunicaciones cifradas y autenticación, el protocolo SRP es más seguro que el protocolo SSH alternativo y más rápido que el uso del intercambio de claves Diffie-Hellman con mensajes firmados. También es independiente de terceros, a diferencia de Kerberos .

El protocolo SRP, versión 3, se describe en RFC 2945. La versión 6a de SRP también se utiliza para la autenticación de contraseñas seguras en SSL/TLS [6] (en TLS-SRP ) y otros estándares como EAP [7] y SAML , y es parte de IEEE 1363.2 e ISO/IEC 11770-4.

Protocolo

En esta descripción del protocolo, versión 6, se utiliza la siguiente notación:

Todas las demás variables se definen en términos de éstas.

Primero, para establecer una contraseña p con el servidor Steve, el cliente Carol elige una sal aleatoria s y calcula x = H ( s , p ), v = g x . Steve almacena v y s , indexados por I , como el verificador de contraseña y sal de Carol. Carol no debe compartir x con nadie y debe borrarlo de forma segura en este paso, porque es equivalente a la contraseña de texto simple p . Este paso se completa antes de que el sistema se use como parte del registro de usuario con Steve. Tenga en cuenta que la sal s se comparte e intercambia para negociar una clave de sesión más tarde, por lo que el valor podría ser elegido por cualquiera de las partes, pero lo hace Carol para poder registrar I , s y v en una sola solicitud de registro. La transmisión y autenticación de la solicitud de registro no está cubierta en SRP.

Luego, para realizar una prueba de contraseña en una fecha posterior se produce el siguiente protocolo de intercambio:

  1. Carol → Steve: genera un valor aleatorio a ; envía I y A = g a
  2. Steve → Carol: genera un valor aleatorio b ; envía s y B = kv + g b
  3. Ambos: u = H ( A , B )
  4. Villancico: S Villancico = ( Bkg x ) ( a + ux ) = ( kv + g bkg x ) ( a + ux ) = ( kg xkg x + g b ) ( a + ux ) = ( g b ) ( a + ux )
  5. Villancico: K Villancico = H ( S Villancico )
  6. Steve: S Steve = ( Av u ) b = ( g a v u ) b = [ g a ( g x ) u ] b = ( g a + ux ) b = ( g b ) (a + ux)
  7. Steve: K Steve = H ( S Steve ) = K Carol

Ahora, las dos partes tienen una clave de sesión segura y compartida K. Para completar la autenticación, deben demostrarse mutuamente que sus claves coinciden. Una forma posible es la siguiente:

  1. Carol → Steve: M 1 = H [ H ( N ) XOR H ( g ) | H ( I ) | s | A | B | K Carol ] . Steve verifica M 1 .
  2. Steve → Carol: M 2 = H ( A | M 1 | K Steve ) . Carol verifica M 2 .

Este método requiere adivinar más del estado compartido para tener éxito en la suplantación que solo la clave. Si bien la mayor parte del estado adicional es público, se podría agregar información privada de manera segura a las entradas de la función hash, como la clave privada del servidor. [ Aclaración necesaria ]

Alternativamente, en una prueba que solo requiere contraseña, se puede omitir el cálculo de K y probar la S compartida con:

  1. Carol → Steve: M 1 = H ( A | B | S Carol ) . Steve verifica M 1 .
  2. Steve → Carol: M 2 = H ( A | M 1 | S Steve ) . Carol verifica M 2 .

Al utilizar SRP para negociar una clave compartida K que se utilizará inmediatamente después de la negociación, resulta tentador omitir los pasos de verificación de M 1 y M 2 . El servidor rechazará la primera solicitud del cliente que no pueda descifrar. Sin embargo, esto puede ser peligroso, como se demuestra en la sección Problemas de implementación a continuación.

Ambas partes también emplean las siguientes garantías:

  1. Carol abortará si recibe B = 0 (mod N ) o u = 0.
  2. Steve abortará si recibe A (mod N ) = 0.
  3. Carol debe mostrar primero su prueba de K (o S ). Si Steve detecta que la prueba de Carol es incorrecta, debe abortar sin mostrar su propia prueba de K (o S ).

Código de ejemplo en Python

""" Un ejemplo de autenticación SRPADVERTENCIA: No lo use con fines criptográficos reales más allá de las pruebas. ADVERTENCIA: El código que aparece a continuación no cumple con importantes medidas de seguridad. No verifica que A, B y U no sean cero.basado en http://srp.stanford.edu/design.html """ importar  hashlib importar  aleatorio# Nota: str se convierte tal como está, str([1,2,3,4]) se convertirá a "[1,2,3,4]" def  H ( * args )  ->  int : """Una función hash unidireccional.""" a = : " . join ( str ( a ) for a in args ) return int ( hashlib . sha256 ( a . encode ( "utf-8" )) . hexdigest (), 16 )           def  cryptrand ( n :  int  =  1024 )  : devuelve  aleatorio.SystemRandom ( ) . getrandbits ( n ) % N  # Un primo seguro grande (N = 2q+1, donde q es primo) # Toda la aritmética se realiza módulo N # (generado usando "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:0 d: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  # Un generador módulo Nk  =  H ( N ,  g )  # Parámetro multiplicador (k=3 en el SRP-6 heredado)F  =  '#0x'  # Especificador de formatoprint ( "#. H, N, g y k son conocidos de antemano tanto por el cliente como por el servidor:" ) print ( f ' { H = } \n { N = :{ F }} \n { g = :{ F }} \n { k = :{ F }} ' )    print ( " \n0 . el servidor almacena (I, s, v) en su base de datos de contraseñas" )# El servidor primero debe generar el verificador de contraseña I  =  "persona"  # Nombre de usuario p  =  "contraseña1234"  # Contraseña s  =  cryptrand ( 64 )  # Sal para el usuario x  =  H ( s ,  I ,  p )  # Clave privada v  =  pow ( g ,  x ,  N )  # Verificador de contraseñaimprimir ( f ' { I = } \n { p = } \n { s = :{ F }} \n { x = :{ F }} \n { v = :{ F }} ' )     # 0. el servidor almacena (I, s, v) en su base de datos de contraseñas # I = 'persona' # p = 'contraseña1234' # s = 0x67bc8932cfd26a49 # x = 0x98a4bce8dde877762a90222f1a1161eba9248590a47eb83aa9e5bd7ecda5368d # v = 0xa7e2038e675d577ac0f318999cab67bba7ec2daf45d2d09f7911b1b78d2fc7f963cd0ac8f17851e0516f059e453672c3b70fcecf5f6843180b271abdd01f552ccda7b2 4fe4719336409cbc1352f8517be651b8935cc0b74ff2819fa07a3f031537d4cfd9f8df7b788a5f2f88e1cd4106b35c38b3d7205a# <demo> --- detener ---print ( " \n1 . el cliente envía el nombre de usuario I y el valor efímero público A al servidor" ) a  =  cryptrand () A  =  pow ( g ,  a ,  N ) print ( f " { I =} \n { A =:{ F }} " ) # cliente->servidor(I, A)   # 1. El cliente envía el nombre de usuario I y el valor efímero público A al servidor # I = 'persona' # A = 0x678556a7e76581e051af656e8cee57ae46df43f1fce790f7750a3ec5308a85da4ec4051e5cb74d3e463685ee975a2747cf49035be67c931b56e793f23ea3524af8909 dcfbc8675d872361025bf884778587ac49454a57c53a011ac2be2839bfb51bf7847a49a483aba870dc7a8b467a81cec91b8ae7813# <demo> --- detener ---print ( " \n 2. el servidor envía la sal s del usuario y el valor efímero público B al cliente" ) b  =  cryptrand () B  =  ( k  *  v  +  pow ( g ,  b ,  N ))  %  N print ( f " { s = :{ F }} \n { B = :{ F }} " ) # servidor->cliente(s, B)   # 2. El servidor envía la sal s del usuario y el valor efímero público B al cliente # s = 0x67bc8932cfd26a49 # B = 0xb615a0a5ea6abf138077bbd869f6a8da37dfc0b7e06a9f5fac5c1e4109c6302cb3e94dcc2cc76da7b3d87d7e9b68a1db998ab239cfde609f3f7a1ece4a491ce3d9a665c 20cf4e4f06730daaa8f52ed61e45bbb67cdc337bf648027ffa7f0f215d5ebe43f9f51832518f1142266aae0dfa960e0082b5154# <demo> --- detener ---print ( " \n3 . El cliente y el servidor calculan el parámetro de codificación aleatoria" ) u  =  H ( A ,  B )  # Parámetro de codificación aleatoria print ( f " { u =:{ F }} " ) # 3. El cliente y el servidor calculan el parámetro de codificación aleatoria # u = 0x796b07e354c04f672af8b76a46560655086355a9bbce11361f01b45d991c0c52# <demo> --- detener ---print ( " \n 4. el cliente calcula la clave de sesión" ) 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 }} \n { K_c =:{ F }} " )  # 4. El cliente calcula la clave de sesión # S_c = 0x699170aff6e9f08ed09a1dff432bf0605b8bcba05aadcaeea665757d06dbda4348e211d16c10ef4678585bcb2809a83c62b6c19d97901274ddafd4075f90604c06baf036af587af8540342b47867eaa22b9ca5e35ac14c8e85a0c4e623bd855828dffd513cea4d829c407137a0dd81ab4cde8a904c45cc # K_c = 0x43f8df6e1d2ba762948c8316db5bf03a7af49391742f5f51029630711c1671e# <demo> --- detener ---print ( " \n 5. el servidor calcula la clave de sesión" ) S_s  =  pow ( A  *  pow ( v ,  u ,  N ),  b ,  N ) K_s  =  H ( S_s ) print ( f " { S_s =:{ F }} \n { K_s =:{ F }} " )  # 5. El servidor calcula la clave de sesión # S_s = 0x699170aff6e9f08ed09a1dff432bf0605b8bcba05aadcaeea665757d06dbda4348e211d16c10ef4678585bcb2809a83c62b6c19d97901274ddafd4075f90604c06baf036af587af8540342b47867eaa22b9ca5e35ac14c8e85a0c4e623bd855828dffd513cea4d829c407137a0dd81ab4cde8a904c45cc # K_s = 0x43f8df6e1d2ba762948c8316db5bf03a7af49391742f5f51029630711c1671e# <demo> --- detener ---print ( " \n 6. el cliente envía prueba de la clave de sesión al servidor" ) M_c  =  H ( H ( N )  ^  H ( g ),  H ( I ),  s ,  A ,  B ,  K_c ) print ( f " { M_c =:{ F }} " ) # cliente->servidor(M_c); el servidor verifica M_c # 6. El cliente envía prueba de la clave de sesión al servidor # M_c = 0x75500df4ea36e06406ac1f8a8241429b8e90a8cba3adda3405c07f19ea3101e8# <demo> --- detener ---print ( " \n7 . el servidor envía prueba de la clave de sesión al cliente" ) M_s  =  H ( A ,  M_c ,  K_s ) print ( f " { M_s =:{ F }} " ) # servidor->cliente(M_s); el cliente verifica M_s # 7. El servidor envía prueba de la clave de sesión al cliente # M_s = 0x182ed24d1ad2fb55d2268c46b42435d1ef02e0fc49f647c03dab8b2a48b0bd3d


Dificultades en la implementación

Ataque de fuerza bruta sin conexión con mensajería dirigida al servidor en ausencia de verificación de clave

Si el servidor envía un mensaje cifrado sin esperar la verificación del cliente, un atacante puede lanzar un ataque de fuerza bruta sin conexión similar al descifrado de hash. Esto puede suceder si el servidor envía un mensaje cifrado en el segundo paquete junto con la sal y B o si se omite la verificación de la clave y el servidor (en lugar del cliente) envía el primer mensaje cifrado. Esto es tentador ya que después del primer paquete, el servidor tiene toda la información para calcular la clave compartida K.

El ataque se desarrolla de la siguiente manera:

  1. Carol → Steve: genera un valor aleatorio a ; envía I y A = g a
  2. Steve: u = H ( A , B ); S = Av u ; K = H ( S )
  3. Steve: genera el mensaje m y lo encripta para producir c = ENC ( K , m )
  4. Steve → Carol: generar valor aleatorio b ; enviar s , B = kv + g b y c

Carol no conoce x ni v , pero dada cualquier contraseña p, puede calcular:

K p es la clave que Steve usaría si p fuera la contraseña esperada. Todos los valores necesarios para calcular K p están controlados por Carol o se conocen a partir del primer paquete de Steve. Carol puede ahora intentar adivinar la contraseña, generar la clave correspondiente e intentar descifrar el mensaje cifrado de Steve c para verificar la clave. Como los mensajes de protocolo tienden a estar estructurados, se supone que identificar que c se descifró correctamente es fácil. Esto permite la recuperación de la contraseña sin conexión.

Este ataque no habría sido posible si Steve hubiera esperado a que Carol demostrara que podía calcular la clave correcta antes de enviar un mensaje cifrado. Las implementaciones adecuadas de SRP no se ven afectadas por este ataque, ya que el atacante no podría pasar el paso de verificación de la clave.

Ataque de fuerza bruta sin conexión basado en tiempo

En 2021, Daniel De Almeida Braga, Pierre-Alain Fouque y Mohamed Sabt publicaron PARASITE [10] , un artículo en el que demuestran la explotación práctica de un ataque de sincronización a través de la red. Este ataque explota implementaciones no constantes de exponenciación modular de números grandes y afectó a OpenSSL en particular.

Implementaciones

Historia

El proyecto SRP se inició en 1997. [11] Dos enfoques diferentes para solucionar un agujero de seguridad en SRP-1 dieron como resultado SRP-2 y SRP-3. [12] SRP-3 se publicó por primera vez en 1998 en una conferencia. [13] RFC 2945, que describe SRP-3 con SHA1, se publicó en 2000. [14] SRP-6, que soluciona ataques de adivinación y ordenación de mensajes "dos por uno", se publicó en 2002. [8] SRP-6a apareció en la "libsrp" oficial en la versión 2.1.0, con fecha de 2005. [15] SRP-6a se encuentra en los estándares como:

IEEE 1363.2 también incluye una descripción de "SRP5", una variante que reemplaza el logaritmo discreto con una curva elíptica aportada por Yongge Wang en 2001. [18] También describe SRP-3 como se encuentra en RFC 2945.

Véase también

Referencias

  1. ^ "¿Qué es SRP?". Universidad de Stanford .
  2. ^ Sherman, Alan T.; Lanus, Erin; Liskov, Moses; Zieglar, Edward; Chang, Richard; Golaszewski, Enis; Wnuk-Fink, Ryan; Bonyadi, Cyrus J.; Yaksetig, Mario (2020), Nigam, Vivek; Ban Kirigin, Tajana; Talcott, Carolyn; Guttman, Joshua (eds.), "Análisis de métodos formales del protocolo de contraseña remota segura", Lógica, lenguaje y seguridad: ensayos dedicados a Andre Scedrov con motivo de su 65.º cumpleaños , Lecture Notes in Computer Science, Cham: Springer International Publishing, págs. 103–126, arXiv : 2003.07421 , doi :10.1007/978-3-030-62077-6_9, ISBN 978-3-030-62077-6
  3. ^ Green, Matthew (18 de octubre de 2018). "¿Deberías usar SRP?". Algunas reflexiones sobre ingeniería criptográfica .NB: la fuente se refiere a SRP-6 como SRPv4 por motivo desconocido.
  4. ^ Haase, Björn (22 de enero de 2023). «(strong) AuCPace, un PAKE aumentado [draft-haase-aucpace-07]». Grupo de trabajo de ingeniería de Internet . Consultado el 10 de junio de 2023 .
  5. ^ Stanislaw Jarecki; Hugo Krawczyk; Jiayu Xu. OPAQUE: Un protocolo PAKE asimétrico seguro contra ataques de precomputación (PDF) . Eurocrypt 2018.
  6. ^ Taylor, David; Tom Wu; Nikos Mavrogiannopoulos; Trevor Perrin (noviembre de 2007). "Uso del protocolo de contraseña remota segura (SRP) para la autenticación TLS".RFC 5054
  7. ^ Carlson, James; Bernard Aboba; Henry Haverinen (julio de 2001). "Protocolo de autenticación EAP SRP-SHA1". IETF.Borrador.
  8. ^ ab Wu, Tom (29 de octubre de 2002). SRP-6: Mejoras y refinamientos del Protocolo de contraseña remota segura (informe técnico).
  9. ^ "Diseño del protocolo SRP".
  10. ^ "PARASITE: Ataque de recuperación de contraseña contra implementaciones de Srp en la naturaleza" . Consultado el 8 de noviembre de 2023 .
  11. ^ "SRP: Acerca del proyecto". srp.stanford.edu .
  12. ^ "SRP-2: Especificaciones de diseño". srp.stanford.edu .
  13. ^ Wu, T., "El protocolo de contraseña remota segura", Actas del Simposio de seguridad de redes y sistemas distribuidos de Internet Society de 1998, págs. 97-111, marzo de 1998.
  14. ^ "SRP: Especificaciones de diseño". srp.stanford.edu .
  15. ^ Archivo CAMBIOS en srp-2.1.2.tar.gz, disponible en http://srp.stanford.edu/download.html
  16. ^ Wang, Mingye. "Informe de erratas de RFC n.° 7538". Editor de RFC . Consultado el 15 de octubre de 2023 .
  17. ^ IEEE 1363.2-2008: Especificación estándar IEEE para técnicas criptográficas de clave pública basadas en contraseñas
  18. ^ Wang, Y., "IEEE P1363.2 Submission / D2001-06-21", [P1363.2-ecsrp-06-21.doc] Una contribución de Yongge Wang para P1363.2 que ofrece una versión de curva elíptica del protocolo SRP, 21 de junio de 2001.

Enlaces externos

Páginas del manual

RFC (Requerimientos de comentarios)

Otros enlaces