Coverage report: /home/ellis/comp/ext/ironclad/src/kdf/password-hash.lisp
Kind | Covered | All | % |
expression | 3 | 83 | 3.6 |
branch | 0 | 0 | nil |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;;; password-hash.lisp
4
(defun make-random-salt (&optional (size 16))
5
"Generate a byte vector of SIZE (default 16) random bytes, suitable
6
for use as a password salt."
9
(defun pbkdf2-hash-password (password &key (salt (make-random-salt))
12
"Given a PASSWORD as a byte vector, a SALT as a byte
13
vector (MAKE-RANDOM-SALT is called to generate a random salt if none
14
is provided), a digest function (SHA256 by default), and a number of
15
iterations (1000), returns the PBKDF2-derived hash of the
16
password (byte vector) as the first value, and the SALT (byte vector)
18
(values (pbkdf2-derive-key digest password salt iterations (digest-length digest))
21
(defun pbkdf2-hash-password-to-combined-string (password &key
22
(salt (make-random-salt))
25
"Given a PASSWORD byte vector, a SALT as a byte vector (MAKE-RANDOM-SALT
26
is called to generate a random salt if none is provided), a digest
27
function (SHA256 by default), and a number of iterations (1000),
28
returns the salt and PBKDF2-derived hash of the password encoded in a
29
single ASCII string, suitable for use with PBKDF2-CHECK-PASSWORD."
30
(with-standard-io-syntax
31
(format nil "PBKDF2$~a:~a$~a$~a" digest iterations
32
(byte-array-to-hex-string salt)
33
(byte-array-to-hex-string
34
(pbkdf2-hash-password password :iterations iterations
35
:salt salt :digest digest)))))
37
(defun pbkdf2-check-password (password combined-salt-and-digest)
38
"Given a PASSWORD byte vector and a combined salt and digest string
39
produced by PBKDF2-HASH-PASSWORD-TO-COMBINED-STRING, checks whether
40
the password is valid."
41
;; can we have a dependency on regular expressions, please?
42
(let* ((positions (loop with start = 0 repeat 3 collect
43
(setf start (position #\$ combined-salt-and-digest
45
(digest-separator-position
46
(position #\: combined-salt-and-digest :start (first positions))))
50
:digest (find-symbol (subseq combined-salt-and-digest
51
(1+ (first positions))
52
digest-separator-position)
54
:iterations (parse-integer combined-salt-and-digest
55
:start (1+ digest-separator-position)
56
:end (second positions))
57
:salt (hex-string-to-byte-array combined-salt-and-digest
58
:start (1+ (second positions))
59
:end (third positions)))
60
(hex-string-to-byte-array combined-salt-and-digest
61
:start (1+ (third positions))))))