Coverage report: /home/ellis/comp/core/lib/cry/password.lisp

KindCoveredAll%
expression2830 93.3
branch00nil
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;; password.lisp --- Reasonably Safe User Passwords
2
 
3
 ;; 
4
 
5
 ;;; Code:
6
 (in-package :cry/password)
7
 
8
 (defclass password ()
9
   ((hash :initarg :hash
10
          :reader password-hash)
11
    (salt :initarg :salt
12
          :initform
13
          ;; Use /dev/urandom seed for portability.
14
          (let ((ironclad:*prng* (ironclad:make-prng :fortuna :seed :urandom)))
15
            (ironclad:make-random-salt 20))
16
          :reader password-salt)))
17
 
18
 (defun make-password-hash (password salt)
19
   (ironclad:byte-array-to-hex-string
20
    (ironclad:digest-sequence
21
     :sha256
22
     (concatenate '(vector (unsigned-byte 8))
23
                  (sb-ext:string-to-octets password)
24
                  salt))))
25
 
26
 (defgeneric (setf password) (password auth)
27
   (:method (password (object password))
28
     (let ((hash (make-password-hash 
29
                  password
30
                  (slot-value object 'salt))))
31
       (setf (slot-value object 'hash) hash))))
32
 
33
 (defmethod initialize-instance :after ((object password) &rest initargs
34
                                                          &key password &allow-other-keys)
35
   (declare (ignore initargs))
36
   (when password
37
     (setf (password object) password)))
38
 
39
 (defmethod auth (object password)
40
   (string= (password-hash object)
41
            (make-password-hash password
42
                                (password-salt object))))