Salted passwords with CL-MD5

Simple snippet of code to implement string password hashes with random salt for CL-MD5.

;;; This program is free software. It comes without any warranty, to
;;; the extent permitted by applicable law. You can redistribute it
;;; and/or modify it under the terms of the Do What The Fuck You Want
;;; To Public License, Version 2, as published by Sam Hocevar. See
;;; http://sam.zoy.org/wtfpl/COPYING for more details.
(defparameter +hash-salt-chars+ "qwertyuiopasdfghjklzxcvbnm")
(defparameter +salt-length+ 5)

(defun md5str (password)
  "Return string form of PASSWORD's MD5sum."
  (format nil "~{~2,'0x~}"
          (concatenate 'list (md5:md5sum-sequence password))))

(defun random-string (character-set length)
  (coerce (loop
             for i from 0 to length
             collect (aref character-set
                           (random (length character-set))))
          'string))

(defun hash-password (password
                      &optional (salt (random-string +hash-salt-chars+ +salt-length+)))
  (concatenate 'string salt "~"
               (md5str (concatenate 'string salt "~" password))))

(defun check-password-hash (password hash)
  (destructuring-bind (salt md5)
      (split-sequence:split-sequence #\~ hash)
    (string= md5 (md5str (concatenate 'string salt "~" password)))))