Si está preocupado por un escenario de "base de datos filtrada" (en lugar del vector de craqueo en línea, que puede ser mitigado por usuario, por IP, por limitación de velocidad por sitio y por bloqueo), tiene razón al hacer hashing no es suficiente.
Incluso utilizando la secuencia más compleja de hashes & salado por ejemplo bcrypt (pbkdf2 (sha256 (pin), salt1), salt2) usted seguirá siendo vulnerable a cualquier persona que pueda ver (p. ej., desde un código fuente / pérdida de documentos) qué algoritmos se utilizan y quién puede encontrar sus sales (normalmente almacenadas en la misma base de datos / tabla): solo pueden ejecutar la misma serie de hashes, e incluso si toma un minuto para cada uno, es solo 7 días probarlos todos. Básicamente, estarías confiando en la seguridad por oscuridad.
En este caso, valdría la pena cifrar los hashes de contraseña con una clave secreta (que se puede mantener por separado del código fuente, solo accesible para usuarios de "operaciones de seguridad de producción" confiables, nunca reutilizados en entornos previos a la producción, cambiado regularmente, etc.). Esa clave secreta deberá estar presente en el servidor que valida / actualiza los códigos PIN, pero se puede mantener por separado de la base de datos de usuario / pin (por ejemplo, en un archivo de configuración cifrado), lo que significa que Little Bobby Tables no se obtendrá automáticamente acceda a él cuando atrape la totalidad de T_USERS mediante inyección de SQL, o cuando alguien tome un DVD con una copia de seguridad de la base de datos en el escritorio de su administrador de sistemas.
[Normalmente no se recomienda cifrar los hashes, porque es mejor utilizar un hash seguro, una buena sal y una contraseña / frases seguras, y cifrar los hashes puede dar una falsa sensación de seguridad. Pero si no puede tener contraseñas seguras, entonces no hay muchas otras opciones: los mendigos no pueden elegir ...]
Puede combinar el PIN con una contraseña, pero en ese caso, ¿por qué molestarse con el PIN? Solo requiere una contraseña alfanumérica fuerte. (Si el PIN se utiliza en combinación con una tarjeta inteligente o un token o similar, por supuesto, puede agregarse a la seguridad general).
Podríamos usar un PIN más grande (6/8 dígitos). No es posible hacer que un PIN de solo dígitos esté a salvo de la fuerza bruta: a 1B hashes por segundo, necesitaríamos 16 o más dígitos para impulsar el tiempo de fuerza bruta más allá de un año. Pero agregar unos cuantos dígitos más podría ser suficiente para hacer que el ataque en línea sea más fácil de detectar y bloquear. Con solo 10K combinaciones, será difícil establecer umbrales de "fuerza lenta" lo suficientemente bajos para hacer que un ataque no sea factible. Desafortunadamente, es probable que tenga restricciones físicas (selección de hardware) que impiden PIN más largos.