No hay ninguna debilidad de seguridad evidente con tus esquemas. El original (aparte de posiblemente no almacenar un número de versión con sus hash para que pueda actualizar su esquema a más rondas o un nuevo pimiento si es necesario), o el nuevo con capas de bcrypt. Bcrypt puede tomar 72 bytes de entrada, por lo que no hay problema al usar sha256 como hash.
Tendría cuidado si codificas la salida de tu sha256hash reforzado con clave antes de alimentarlo a bcrypt. En principio, es probable que sea mejor mantenerlo en forma binaria; si estuviera usando sha512, eso permitiría que se usaran todos los bytes (como 72 bytes = 576 bits). Concedido con sha-256, no importa mientras lo hagas correctamente. Un hash sha256 tiene 32 bytes de largo (en binario con letras no imprimibles), 44 bytes de largo después de la codificación base64, 64 bytes de largo (en hexadecimal), pero 88 bytes si codifica en base al hash codificado en hexadecimal (que sería parcialmente seguridad truncada y ligeramente debilitada: por ejemplo, en lugar de 256 bits de seguridad inherente, tiene 72/88 * 256 ~ 209 bits).
Tenga en cuenta que si un usuario tiene una contraseña de entropía extremadamente alta (por ejemplo, 400 bits de entropía) que en principio requeriría ~ 2 ^ 400 de tiempo para descifrar, usando sha256 como paso intermedio, solo tomará tiempo ~ 2 ^ 256 antes de que sea probable encontrar alguna contraseña que funcione. Concedido 2 ^ 256 es completamente seguro en estos días (ya que es algo significativamente mayor que ~ 2 ^ 80, por lo que esta diferencia no tiene relevancia práctica)
Se vuelve más complicado y potencialmente más molesto de mantener (dado que puede argumentar que esto es algo bueno, si alguna vez se filtró su base de datos, sería más difícil para un atacante obtener una GPU para forzar la fuerza bruta). Si alguna vez actualiza su sistema y las cosas no funcionan perfectamente, hay muchos más puntos en los que las cosas podrían salir mal. Si aparece un nuevo desarrollador y los hashes aparecen en la forma de bcrypt, pueden asumir que solo son bcrypt y cambiar algo que rompe el sistema.
Una alternativa sería mantener ambos sistemas en su lugar y actualizar a los usuarios a bcrypt en su próximo inicio de sesión exitoso.
def login(username, password):
user = get_user(username)
if user.uses_old_hash():
calculated_old_hash = sha256_1000_round(password, salt=user.salt)
if constant_time_string_compare(user.hash, calculated_old_hash):
calculated_new_hash = bcrypt.hashpw(password, salt=bcrypt.gensalt(12))
user.hash = calculated_new_hash
print "Login Successful"
return True
else:
print "Login Failed"
return False
else:
hash = user.hash
calculated_new_hash = bcrypt.hashpw(password, salt=hash)
if constant_time_string_compare(hash, calculated_new_hash):
print "Login Successful"
return True
else:
print "Login Failed"
return False