Knodium's pbkdf2 added by andyjpb on Tue Feb 19 15:20:50 2013
(module pbkdf2
(pbkdf2
make-salt)
(import scheme chicken)
(use srfi-1)
(use srfi-4 srfi-27 entropy-unix)
(use
sha2
message-digest
hmac
loops
base64
string-utils
)
(define dklen 32)
(define password "spider")
(define salt "salty")
(define iterations 10000)
(define digest sha256-primitive)
(define hlen (string-length (message-digest-string (digest) "x")))
(if (not dklen) (set! dklen hlen) '())
(if (> dklen (* 4294967295 hlen)) (error 'dklen "Overflow, dklen too large") '()) ;ensures dklen < 2^32
(define l (inexact->exact (ceiling (/ dklen hlen)))) ;determines the number of blocks dklen will be broken into
(define r (- dklen (* (- l 1) hlen))) ;determines the length of the remainder block
(define (hmac-sha256 key message)
((hmac key (sha256-primitive)) message)) ;slower implementation (that actually works)
; (if (> (string-length key) 64)
; (set! key (sha256 key))
; (set! key (string-pad-right key 64 #\x00))
; )
;
;
; (define o-key-pad (string-map (lambda (x) (integer->char (bitwise-xor 92 (char->integer x)))) key))
; (define i-key-pad (string-map (lambda (x) (integer->char (bitwise-xor 54 (char->integer x)))) key))
; (sha256 (string-append o-key-pad (sha256 (string-append i-key-pad message))))
;)
(define (sha256 x) (message-digest-string (sha256-primitive) x))
(define (U u xor count)
(if (= count iterations) xor
(let* ((new-u (hmac-sha256 password u)))
(U new-u (string-xor xor new-u) (+ count 1))
)
)
)
(define (F i)
(let* ((salt-i (string-append salt (int->4bytestring i)))
(u1 (hmac-sha256 password salt-i)))
(U u1 u1 1)
)
)
(define (T)
(let* ((tlist '()))
(do-times x l (set! tlist (append tlist (list (F (+ x 1))))))
tlist
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FOR CONVERTING INTEGERS TO 4 BYTE STRINGS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;supports encoding ints up to 2^32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (int->dhex x)
(if (< x 256)
(list x)
(append
(int->dhex (quotient x 256))
(list (modulo x 256)))
)
)
(define (pad x) (if (< (length x) 4) (pad (append (list 0) x)) x))
(define (int->padhex x) (pad (int->dhex x)))
(define (int->4bytestring x)
(let*
((padhex (int->padhex x))
(charlist (map integer->char padhex)))
(apply string charlist))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;For XORing strings together;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (char-xor x y)
(let* ((num (bitwise-xor (char->integer x) (char->integer y))))
(integer->char num)
)
)
(define (string-xor x y)
(list->string (map char-xor (string->list x) (string->list y)))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (pbkdf2 _password _salt _iterations );_dklen)
(set! password _password)
(set! salt _salt)
(set! iterations _iterations)
(let* ((tlist (T))
(listlen (length tlist))
(last-elem (list-ref tlist (- listlen 1)))
(almost-list (apply string-append (take tlist (- listlen 1))))
(last-elem-list (string->list last-elem))
(tstring (string-append almost-list (list->string (take last-elem-list r)))))
(base64-encode tstring)
)
)
;(do-times _ 10 (pbkdf2 "spider" "salt" 10000)) ;for benchmarking
; Randomness for password algorithms
(define (u8vectors->base64 vec)
(base64-encode (blob->string (u8vector->blob/shared vec))))
(define (make-secret-generator)
(let ((source (make-entropy-source-urandom-device)))
(lambda (byte-width)
(u8vectors->base64
(entropy-source-u8vector source byte-width)))))
(define make-salt
(make-secret-generator))
)