Update (2016-04-02): @abeaumont pointed out that the hashing issue has already been fixed in the Github repo. As of today Quicklisp provides Ironclad version 0.33.0 which dates back to 2014. Until Quicklisp provides an updated version the information in this post is still relevant.
Few people debate whether user passwords must be securely hashed before being stored on disk. Ironclad provides the tools to easily hash and check passwords with the PBKDF2 algorithm.
One of the basic requirements of PBKDF2 is that the salt value be obtained from a cryptographically secure pseudo-random number generator.
Ironclad’s password hashing function … does not initialize the random state …
Ironclad’s password hashing function uses the standard (random)
function
which is not cryptographically secure. Worse, it does not initialize the
random state and it gives no warning or indication about this fact. The
effect is that every time the application is started it uses the same sequence
of pseudo-random numbers, i.e. after restart the same password generates the
same hash.
It is possible to initialize *random-state*
properly before using
Ironclad’s password hashing. This is still not cryptographically secure but at
least the pseudo-random sequence is different after every restart which should
be sufficient for general purpose credential protection. It will probably not
be good enough for a targeted attack.
This code initializes the random state properly:
(defparameter *package-random-state* nil)
(defun hash (password)
(unless *package-random-state*
(setf *package-random-state* (make-random-state t)))
(let* ((*random-state* (make-random-state *package-random-state*))
(hashed (ironclad:pbkdf2-hash-password-to-combined-string
password)))
(setf *package-random-state* (make-random-state nil))
hashed))
Though Ironclad’s password hashing is very easy to use, the cl-pass library makes it even easier. Cl-pass sets strong (in 2016) default parameters and it handles the random state initialization transparently.