Me han asignado la tarea de mejorar la seguridad del almacenamiento de contraseña de un sitio que actualmente utiliza PHPass de Openwall . Todos los hashes se convertirán a la vez, i. mi. no queremos esperar a que el usuario inicie sesión para volver a aplicar su contraseña.
Para lograr esto, pensé que podríamos usar bcrypt sobre los hashes PHPass existentes , de esta manera: bcrypt(phpass(password))
Pero necesitamos un paso intermedio importante: al igual que bcrypt, PHPass tiene su propia sal incrustada en el hash, así que tenemos que "cargar" esa sal en bcrypt si queremos que la operación sea repetible al verificar los hashes.
Afortunadamente, el tamaño de la sal de PHPass es más pequeño (6 bytes) que el de bcrypt (16 bytes), por lo que podemos "compartir" los primeros 6 bytes de la sal y agregar 10 bytes aleatorios adicionales para bcrypt.Imagina algo como esto en pseudo-PHP:
$password = 'somestring123';
$hash = phpass($password)
// $hash is now '$H$9Uvsrbh2Wxo3SebfGb4xVtODMmD2K70',
// where 'Uvsrbh2W' is an encoded, random salt of 6 'raw' bytes
$raw_salt = decode(substr($hash, 4, 8));
$hash = bcrypt_with_custom_salt($hash, $raw_salt . random_bytes(10));
// $hash is now '$2y$12$Uvsrbh2WzN9HrapVpnmu2OYOdJ2jnjHt2LTwIYQPJe.BUJQKezKuO'
// whose salt uses the first 6 bytes we had in phpass,
// so that we can repeat the process when veryfing the password
// since we have all the salts available in only one hash
Salvo cualquier error de implementación y asumiendo que las fuentes aleatorias son criptográficamente seguras, ¿es esta una forma teóricamente segura de usar bcrypt en un contexto heredado? Desde mi entendimiento, el resultado debería ser tan seguro ( Si no es más ...? ) solo estoy haciendo bcrypt(password)
, pero no soy un experto y es posible que me falten algunos detalles oscuros.