Data Encryption Standard: Part 3
September 7, 2010
All of the hard work has been done in previous exercises, making this simple. Here is Triple DES:
(define (triple-encipher ks1 ks2 ks3 block)
(encipher ks3 (decipher ks2 (encipher ks1 block))))
(define (triple-decipher ks1 ks2 ks3 block)
(decipher ks1 (encipher ks2 (decipher ks3 block))))
Hashing is a simple variant of cbc-encipher
, in which the intermediate calculations are performed but the encrypted output isn’t written. When the last block is computed, the requested number of leading bits is output:
(define (hash encipher n port)
(define (encode prev txt) (encipher (vector-xor (ascii->bits txt) prev)))
(let loop ((prev (make-vector 64 0)) (txt (read8 port)))
(cond ((eof-object? txt)
(bits->hex (vector-slice (encode prev (pad "")) 0 n)))
((hex (vector-slice (encode prev (pad txt)) 0 n)))
(else (let ((next (encode prev txt)))
(loop next (read8 port)))))))
Converting a password to a key is a simple application of hashing:
(define (password->key encipher passwd)
(define (make-odd bits)
(let ((bs (vector->list bits)))
(append bs (list (if (even? (apply + bs)) 1 0)))))
(let ((p (with-input-from-string passwd (lambda ()
(hex->bits (hash encipher 56 (current-input-port)))))))
(bits->hex (list->vector (apply append (map make-odd (vector-slice-by 7 p)))))))
You can see the code at http://programmingpraxis.codepad.org/hI295Aff, including all the contributions from previous exercises.