Estaba tratando de diseñar un sistema de autenticación que hiciera que sea mucho más difícil adivinar una contraseña a través de la fuerza bruta, y reducir el riesgo para un usuario si la contraseña de hash fue robada a través de un ataque basado en espionaje. Además, dado que el código del lado de mi cliente será fácilmente visible para aquellos que deseen verlo (está en un lenguaje interpretado, sin embargo, sí cifro y ofusco al cliente distribuido), quería poder evitar que un atacante mirara La fuente para hacerse pasar por un usuario fácilmente. La seguridad a través de la oscuridad es la seguridad NO .
Aquí está el algoritmo que pensé. Quería someterlo a examen público porque los algoritmos de criptografía siempre funcionan mejor cuando están sujetos a tantas opiniones como sea posible, IMHO.
(Todos los hashes se calculan con el SHA-2 y un tamaño de bloque de 512 bits. No se sabe que este algoritmo sea vulnerable a cualquier ataque de colisión o pre-imagen, y es una función de hash criptográfica segura.)
[LADO DEL CLIENTE]
-
El usuario proporciona un nombre de usuario de cualquier carácter / símbolo / número con menos de 30 caracteres y una contraseña de cualquier carácter / símbolo / número que tenga entre 8 y 200 caracteres de longitud.
-
El nombre de usuario está hasheado.
-
El hash del nombre de usuario se agrega al final de la contraseña del usuario como una sal.
-
La contraseña con sal está en hash, y luego ese hash está en hash.
-
La fecha y la hora actuales se solicitan al servidor de autenticación y, a continuación, se recortan.
-
El hash de la marca de tiempo se agrega al hash de nombre de usuario / contraseña como lo que llamaré 'sal dependiente del tiempo'. Esta última combinación se procesa para generar el hash de autenticación final.
-
El nombre de usuario, el hash con marca de tiempo, la contraseña con sal y el tiempo utilizado para generar el sal dependiente del tiempo se envían al servidor a través de una conexión TLS / SSL.
[LADO DEL SERVIDOR]
-
El servidor verifica que la marca de tiempo recibida está en el último minuto. Si no es así, el servidor indicará que la autenticación falló.
-
El servidor hace un hash del nombre de usuario / contraseña con sal y compara eso con la base de datos almacenada con sal / hash de contraseña. Si no coinciden la autenticación falla. (Para aclarar, el servidor tiene un hash de hash de contraseña con sal. Verifica que contra un hash del hash de contraseña con sal dado por el cliente).
-
El servidor calcula un hash de la marca de tiempo enviada por el cliente.
-
El servidor separa el hash de marca de tiempo generado y el hash de contraseña con sal para formar el hash de autenticación.
-
Compara el hash de autenticación que produjo con el hash de autenticación enviado por el cliente. Si son iguales, se reporta autenticación. De lo contrario, informa de un error de autenticación.
Si estoy en lo cierto, creo que este esquema de autenticación hace que el hecho de forzar una contraseña bruta sea casi imposible, y hace que una contraseña robada a través de espionaje solo sea útil por un minuto entero.
Sin embargo, contra lo que no protege, ya que creo que es imposible, son las contraseñas robadas al usuario cuando se ingresan en el cliente. Spyware podría robar el nombre de usuario y la contraseña reales.
EDIT 1 :: Se corrigió el proceso de autenticación para que el servidor no almacene el hash de contraseña con sal, solo un hash de ese valor. Esto evita que un atacante con acceso a la base de datos sepa la contraseña original. La razón por la que se debe hacer esto es el valor de hash del hash de contraseña con sal. es la contraseña desde el punto de vista del servidor. Almacenar el hash de contraseña con sal en la base de datos sería lo mismo que almacenar las contraseñas de todos los usuarios en texto sin formato.
EDIT 2 : se corrigió el esquema para que la autenticación dependiera de la hora del servidor, no del cliente.
EDITAR 3 : hizo que la longitud de la contraseña fuera menos restrictiva, pero la mantuvo razonable.