¿Puedo usar la misma contraseña tanto para SRP como para el cifrado del lado del cliente?

13

Supongamos que se utiliza un servidor que no es de confianza para almacenar los datos confidenciales de los usuarios (cifrados en el lado del cliente), y ambas tareas, la autenticación y el cifrado / descifrado, deberían poder realizarse con una sola contraseña. ¿Sería suficiente con:

  1. Reforzar la contraseña con una función de derivación de clave lenta y una sal trivial [1] , que produce k ;
  2. Utilice k como la "contraseña" de SRP, autenticándose con el servidor y recibiendo el texto cifrado;
  3. Descifre el texto cifrado para obtener la (s) clave (s) real (es) que se usarán para firmar, encriptar, etc.

Un servidor malintencionado (bajo riesgo) tendría que realizar un ataque de diccionario sin conexión: en el verificador o en el texto cifrado: para recuperar k , mientras que un atacante externo (mayor riesgo) solo podría realizar ataques en línea (ya que no tiene acceso ni al verificador ni al texto cifrado), a menos que obtenga una copia de la base de datos, lo que solo póngalo en una situación similar del servidor [2] .

¿Es correcto este razonamiento? ¿Alguna falla que no haya anticipado? Algunas notas:

  1. Yo digo que la sal es "trivial" porque es: a) vacía; b) derivado del nombre de usuario; c) Aleatorio, pero el servidor se lo dará a quien lo solicite. Normalmente eso sería una preocupación , pero aquí la clave nunca abandona la máquina cliente, por lo que no importa si dos usuarios tienen la misma clave.
  2. Una de mis preocupaciones es que un atacante podría crear una tabla de arco iris dirigida a un usuario en particular, luego obtener la base de datos e iniciar sesión casi de inmediato como ese usuario, ya que forzar de manera brutal al verificador o el texto cifrado es más rápido si tiene una lista de claves candidatas en lugar de una lista de contraseñas candidatas (que aún deben estirarse antes de convertirse en claves).

    Por supuesto, si un atacante tiene esa capacidad de computación (o si la contraseña era débil), eventualmente se descifrará cualquier texto cifrado filtrado, pero se podrían evitar daños futuros si el servidor fuera más fuerte en este escenario (antes de aprender sobre el SRP que diseñé un protocolo más enrevesado que tuvo esto en cuenta, pero fue más inútil y tuvo preguntas abiertas).

  3. [Para mi caso particular] Todo esto está fuera del alcance de la pregunta (suponga que ya se ha resuelto): toda la comunicación se realizará a través de TLS, se dará la opción de usar las claves adecuadas y se otorgará la autenticación de 2 factores (pero no es obligatorio) , el código del cliente no provendrá del servidor que no sea de confianza, se usarán los MAC, etc.
pregunta mgibsonbr 14.06.2013 - 11:08
fuente

3 respuestas

6

Como ejercicio de prudencia saludable, recomendaría lo siguiente:

  • Cuando obtenga su clave k de la contraseña del usuario, hágala más larga y divídala en dos. Utilice la primera mitad para SRP, la segunda mitad para el cifrado. Una forma sencilla de lograrlo es mediante el hash k con SHA-256, que ofrece 256 bits que luego se pueden dividir en dos claves finas de 128 bits. Alternativamente, use una función de derivación de clave con un tamaño de salida ajustable, como PBKDF2 .

    El punto aquí es que queremos evitar cualquier "interacción" no deseada, aunque sea inverosímil, entre el cifrado simétrico y los cálculos realizados en SRP. La intercalación de una capa de un solo sentido entre las dos subclaves debería evitar tales problemas (suponiendo que SHA-256 se comporte más o menos como un random oracle ).

  • Usted encripta por una razón: entonces debe asumir que un atacante puede observar, en algún momento, el blob de datos encriptados simétricamente. De lo contrario, ¿cuál sería el punto de cifrado? Pero si tal espionaje es posible, entonces la sal debe ser adecuada. Una sal vacía no lo cortaría, porque todos los usuarios usarían la misma sal, lo que permitiría optimizaciones de ataque (a saber, tablas de arco iris).

    Ahora hay un punto interesante, que es que el propio SRP incluye un poco de procesamiento de sal. Eche un vistazo de cerca a RFC 5054 , que describe cómo se integrará el SRP en un protocolo de enlace TLS. En el paso inicial, el cliente (en su ClientHello ) envía la identidad del usuario ( I ). El servidor responde con algunos mensajes, incluido el ServerKeyExchange que contiene (entre otros valores) la sal s . Así que tienes, aquí mismo, tu "servidor que envía la sal a todos los que la solicitan".

El procesamiento de la contraseña real, en SRP, es el cálculo de x = SHA1(s | SHA1(I | ":" | P)) . Esta es una función de hashing de contraseña con sal, pero con una iteración insuficiente. Este es un defecto conocido en SRP tal como está definido actualmente. Sin embargo, sería trivial reemplazar esta operación con una función de hashing de contraseña segura , siempre que el cliente y el servidor estén de acuerdo.

Esto produce el siguiente esquema:

  • En el momento del registro, el usuario elige su contraseña P , y se genera un valor aleatorio de sal s (por ejemplo, 128 bits de un PRNG criptográficamente fuerte).
  • Desde P y s , se aplica una función de hashing de contraseña segura (como bcrypt ), produciendo algún valor intermedio z , que luego procesamos con SHA-512, produciendo 512 bits. Estos 512 bits se dividen en dos mitades de 256 bits; la primera mitad será el valor x para SRP, mientras que la segunda mitad (llamémosla y ) se usará para el cifrado simétrico.
  • Al iniciar sesión, el cliente primero envía el nombre de usuario ( I ) al servidor y obtiene la sal s . El mismo cálculo de x y y se realiza de nuevo. La parte x se usa para SRP, la parte y para descifrar el blob almacenado en el servidor.

Este esquema combina todos los puntos discutidos anteriormente. La derivación de contraseña a clave utiliza una función adecuada con una buena sal aleatoria; hay una capa de aislamiento de SHA-512 entre los dos usos de la contraseña; no es necesario un intercambio de mensajes adicional en comparación con el SRP básico. En efecto, lo que sugiero aquí es un fortalecimiento del hashing de contraseña realizado en SRP, con una lectura adicional de una clave derivada de contraseña para su necesidad de cifrado simétrico.

Tenga en cuenta que si bien puede establecer primero un túnel SSL / TLS y luego realizar el SRP, también puede seguir la carretera RFC 5054 y usar el SRP para el protocolo de enlace TLS. Esto requeriría el control del código del cliente y del servidor, incluida la implementación de SRP, ya que sugiero aquí la modificación del proceso de derivación de contraseña a clave (a saber, para fortalecerlo). En consecuencia, el cliente ya debe tener el código necesario. En un contexto Web-Javascript, primero necesitaría un SSL / TLS "normal", aunque en ese punto los beneficios de SRP se vuelven bastante pequeños.

Permitir que el servidor envíe el valor de sal a quien lo solicite, como es inherente a SRP, no es un problema grave. Las sales no necesitan secreto. Mantener los valores de sal en secreto no daña , pero este es solo un objetivo secundario. El punto principal de las sales es singularidad . No permita que una pizca injustificada de secreto se ponga en el camino de la singularidad.

    
respondido por el Thomas Pornin 01.07.2013 - 23:40
fuente
5

Voy a suponer que quiere decir que los datos se cifran con la clave k (el mismo valor que se usa para la contraseña de SRP). No especificó esto, así que si esto no es lo que tenía en mente, edite su pregunta.

Sí, este es un esquema razonable.

Sugeriría usar el nombre de usuario del usuario más el identificador del servidor (por ejemplo, el nombre de dominio) como la sal de su función de derivación de clave lenta, si es posible. También puede hacer que sea un valor aleatorio que sea público y diferente para cada usuario.

Tablas de arco iris: Las tablas de arco iris no ayudan mucho al atacante, ya que el costo de crear las tablas de arco iris es tanto como intentar un montón de contraseñas candidatas. Las tablas Rainbow solo ayudan cuando está atacando varias veces (por ejemplo, atacando a múltiples usuarios) y desea amortizar el costo. Si crees que un nombre de usuario es muy común (por ejemplo, alice ), sería posible crear una tabla de arco iris específica para alice (un cálculo de una sola vez) y luego usarla para atacar múltiples servidores, con la esperanza de que haya una cuenta llamada alice en todos esos servidores. Sin embargo, esto solo le proporciona una aceleración si encuentra varios usuarios con el mismo nombre de usuario (presumiblemente, en varios servidores diferentes). No creo que sea una gran amenaza en la práctica. Si le preocupa esto, puede evitarlo utilizando como sal un valor aleatorio que sea diferente para cada usuario, o utilizando la combinación del nombre de usuario del usuario y el identificador del servidor como la sal.

Otro: La mayor debilidad es probablemente donde el cliente obtendrá el código para descifrar el texto cifrado. Si se trata de una aplicación del lado del cliente dedicada, puede integrarla en el código del programa cliente. Pero si el cliente está accediendo a algún sitio web a través de un navegador web, y el servidor proporciona el código de descifrado como Javascript (por ejemplo), entonces realmente no ha adquirido tanta seguridad como cree que tiene, ya que un archivo malicioso / comprometido / El servidor falso puede enviar un Javascript malicioso que roba la contraseña del usuario.

    
respondido por el D.W. 30.06.2013 - 04:09
fuente
2

Hay otro enfoque que deberías considerar. Tome la contraseña de usuario p, aplique un salt y presione la derivación de la clave para generar una clave más larga k. Luego divide k en dos partes a y b. La primera parte, a, se utiliza para cifrar los datos y la segunda parte, b, se utiliza para autenticar en el servidor.

¿Eso satisface sus requisitos de seguridad y facilidad de uso?

    
respondido por el u2702 01.07.2013 - 19:12
fuente

Lea otras preguntas en las etiquetas