Funciones hash y gestión segura de contraseñas¶
Función hash¶
Una función hash es una función que transforma un dato de entrada (por ejemplo, una contraseña) en una cadena de longitud fija, llamada hash. Este proceso es unidireccional, lo que significa que no es posible recuperar el dato original a partir del hash.
Ejemplo conceptual:
Aunque el texto de entrada cambie solo un carácter, el hash resultante será completamente distinto.
Propiedades importantes de una función hash¶
Una función hash segura cumple las siguientes propiedades:
- Determinista: la misma entrada produce siempre el mismo hash.
- Unidireccional: no se puede obtener el valor original a partir del hash.
- Efecto avalancha: pequeños cambios en la entrada generan hashes totalmente diferentes.
- Longitud fija: el tamaño del hash es siempre el mismo, independientemente de la entrada.
Gestión de contraseñas en aplicaciones¶
Guardar contraseñas en texto plano (en memoria, archivos o bases de datos) es extremadamente inseguro. Si esos datos son accedidos por terceros, todas las contraseñas quedarían expuestas inmediatamente.
Incluso guardarlas cifradas no es suficiente, ya que el cifrado es reversible si se obtiene la clave. En cambio, el hash no puede revertirse.
La forma correcta de gestionar contraseñas es:
- No almacenar nunca la contraseña original.
- Calcular el hash de la contraseña.
- Guardar únicamente el hash.
- Para validar una contraseña introducida, se calcula su hash y se compara con el almacenado. Si coinciden, la contraseña es correcta.
Utilización de hashlib para gestionar contraseñas¶
El módulo estándar hashlib, que viene incluido en Python permite trabajar con hashes. Veamos un programa sencillo para crear una contraseña y verificarla.
import hashlib
# Función que calcula el hash de una contraseña
def generar_hash(contrasena):
return hashlib.sha256(contrasena.encode()).hexdigest()
# Función para registrar un usuario (guardar solo el hash)
def registrar_usuario(contrasena):
hash_contrasena = generar_hash(contrasena)
return hash_contrasena
# Función para verificar una contraseña introducida
def verificar_contrasena(contrasena_introducida, hash_guardado):
return generar_hash(contrasena_introducida) == hash_guardado
# Registro del usuario
hash_guardado = registrar_usuario("hola123")
print(hash_guardado)
# Inicio de sesión
print(verificar_contrasena("hola123", hash_guardado)) # True
print(verificar_contrasena("adios123", hash_guardado)) # False
Con el programa anterior conseguimos:
- Nunca se guarda la contraseña original (
"hola123"). - Solo se guarda su hash (
hash_guardado). - Para comprobar la contraseña, se calcula el hash de la entrada y se compara.
- En ningún momento se puede recuperar la contraseña original a partir del hash.
Este esquema es la base de cómo funcionan los sistemas reales de autenticación.