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
    (setf *package-random-state* (make-random-state nil))

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.