Por diversos motivos, necesito usar la autenticación de resumen para un servidor REST que he creado.
Se me ocurrió una "mejora" que creo que fortalece el algoritmo contra los ataques MD5 sin ser una carga para los clientes. ¿Qué problemas puedes ver con mi algoritmo?
Introducción
- El cliente es una aplicación personalizada escrita en C #.
- El servidor es un servidor REST basado en JAX-RS escrito en Java y ejecutándose en Tomcat.
- Todo el tráfico entre el cliente y el servidor se cifra mediante SSL / TLS.
-
La base de datos contiene una tabla_de_usuario con las siguientes columnas:
- id_usuario: clave principal
- password_hash: varchar no nulo
- sal: varchar no nulo
- iteration_count: integer
Autenticación de resumen (RFC2617)
La autenticación implícita utiliza los siguientes cálculos:
nonce: server-generated number used once
nonceCount: server-generated increasing value (prevents replay attacks)
cnonce: client-generated number used once
qop: quality of protection ("auth")
method: typically one of "GET", "POST", "PUT", etc.
HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)
El valor HA1
se almacena en la base de datos como el valor hash de la contraseña. Durante la autenticación, el cliente calcula el valor de response
a partir de los encabezados http WWW-authenticate
. El servidor también calcula el valor response
usando su versión almacenada de HA1
y compara el valor recibido del cliente. Si son iguales, el cliente está autenticado.
MD5 ya no se considera seguro. Las colisiones se pueden encontrar en unas pocas horas utilizando el hardware básico.
Uso de PBKDF2 para fortalecer el resumen
- El cliente obtiene el nombre de usuario y la contraseña de texto sin formato del usuario.
- El cliente solicita el número de sal y iteración para el user_id del servidor. El servidor también envía el recuento de iteración predeterminado actual (que puede ser diferente del utilizado por este usuario).
- El cliente calcula una clave secreta de 128 bits utilizando PBKDF2 (contraseña, sal, cuenta de iteración específica del usuario). La clave secreta se codifica como una cadena hexadecimal.
- El cliente calcula
HA1
usando el nombre de usuario, el dominio y la clave codificada en hexadecimal. Este valorHA1
se usa en una autenticación de resumen estándar. - El servidor obtiene el hash de la contraseña de la base de datos. El hash de la contraseña es el
HA1
calculado previamente utilizando la misma clave secreta derivada de PBKDF2. El servidor compara elresponse
calculado con el valorresponse
enviado por el cliente (autenticación de resumen estándar). Si los dos valores deresponse
son iguales, el cliente se autentica. - Si el recuento de iteraciones específico del usuario devuelto al cliente es diferente del recuento de iteraciones predeterminado, el cliente calcula un nuevo
HA1
utilizando PBKDF2 y el nuevo recuento de iteraciones. El cliente llama a un métodoPUT
en el servidor REST para actualizar la columna de hash de contraseña con el nuevo valor. Este paso permite que el algoritmo se actualice con mayores recuentos de iteración a medida que el hardware se acelera.
El algoritmo modificado no se basa en la fuerza de MD5 para proteger el hash de contraseña, ya que la dificultad de calcular el hash de contraseña depende de PBKDF2 (que puede usar un hash SHA-1 o SHA-256).
¿Hay fallas de seguridad obvias en este algoritmo modificado?