Update of /project/crypticl/cvsroot/crypticl/src In directory clnet:/tmp/cvs-serv10354
Modified Files: sha.lisp Log Message: Reformat comments. Add optional debug function to state machine.
--- /project/crypticl/cvsroot/crypticl/src/sha.lisp 2007/01/06 12:56:16 1.5 +++ /project/crypticl/cvsroot/crypticl/src/sha.lisp 2007/01/07 00:44:12 1.6 @@ -2,7 +2,7 @@ ;;;; The Crypticl cryptographic library. ;;;; ;;;; Description: The SHA-1 message digest algorithm. -;;;; Author: Taale Skogan tasko@frisurf.no +;;;; Author: Taale Skogan ;;;; Distribution: See the accompanying file LICENSE.
@@ -13,14 +13,13 @@ ;;; [1] FIPS 180-2 "Secure Hash Standard" ;;; [2] Schneier,B. 1996. "Applied Cryptography"
-;;To do: +;;TODO: ;; -repeating code in sha1-round and sha1-encode (difficult because of objects)
- (in-package crypticl)
(defmacro initialize-sha1-state (a b c d e) - "Initializes the state of the hash algorithm" + "Initializes the state of the hash algorithm." `(setf ,a #x67452301 ,b #xefcdab89 ,c #x98badcfe @@ -28,7 +27,11 @@ ,e #xc3d2e1f0))
(defmacro sha1-make-octet-vector (a b c d e) - "Make byte-vector from 5 32 bits integers. Note that SHA-1 uses the big-endian convention so the least significant byte of an integer is stored in the rightmost position in the byte array. This is the opposite of MD5" + "Make byte-vector from 5 32 bits integers. + +Note that SHA-1 uses the big-endian convention so the least significant byte +of an integer is stored in the rightmost position in the byte array. +This is the opposite of MD5." (flet ((bytes (num32) `((ldb (byte 8 24) ,num32) (ldb (byte 8 16) ,num32) @@ -43,12 +46,13 @@
(defun sha1-length64 (message-length-in-bits) - "Returns input integer message-length-in-bits as two 32-bit words, high order bits first" + "Returns input integer as two 32-bit words, high order bits first." (values (ldb (byte 32 32) message-length-in-bits) (ldb (byte 32 0) message-length-in-bits)))
(defun new-sha1-length64 (mess-len octet-vector start) - "Returns octet-vector after the interger mess-len has been encoded as eight bytes, high order bits first, starting at start" + "Returns octet-vector after the interger mess-len has been encoded as eight +bytes, high order bits first, starting at start." (do ((char 56 (- char 8))) ((> 0 char) octet-vector) @@ -73,23 +77,42 @@ (defun make-buffer-filler (reader-function &optional (octet-count 0)) "Returns buffer-filler function for use as argument to sha1-encode. + The buffer-filler fills a buffer with 16 32 bits words and returns true if there is more data. It returns nil if all data including padding and data length has been returned.
Note that MD5 and SHA-1 uses the same padding scheme.
-The buffer-filler is a state-machine with four states. :done, :data, :length and :zeropad. The initial state is :data. When there is no more data, #x80 is returned and the new state is either :write-length (if current word is 13 and current byte is 3) else :zeropad. If we enter :write-length we write the length in the last two 32 bit words and enter :done. In state :zeropad we write zeros until we reach word 13 and byte 3 and then enter :write-length. When we reach the :done state, the next call will return nil." +The buffer-filler is a state-machine with the four states +:data +:done +:length +:zeropad + +The initial state is :data. When there is no more data, #x80 is returned +and the new state is either :write-length (if current word is 13 and +current byte is 3) else :zeropad. If we enter :write-length we write the +length in the last two 32 bit words and enter :done. In state :zeropad we +write zeros until we reach word 13 and byte 3 and then enter :write-length. +When we reach the :done state, the next call will return nil." (let ((state :data) - (byte-count octet-count) ;counts number of bytes read + (byte-count octet-count) ;counts number of bytes read (byte-num -1)) ;0,1,2 or 3 afterwards (flet ((buffer-filler (buffer) (dotimes (word 16 t) ;16*32 = 512 - (flet ((gb () ;helper to get the next byte + (flet ( + (gb () ;helper to get the next byte + (flet ((db () + ;; (format t "state ~A word ~D ~%" state word) + nil)) (setf byte-num (mod (1+ byte-num) 4)) (ecase state - (:done (return-from buffer-filler nil)) + (:done + (db) + (return-from buffer-filler nil)) (:data + (db) (let ((a-byte (funcall reader-function))) (cond (a-byte @@ -99,17 +122,19 @@ (setf state :write-length) #x80) (t (setf state :zeropad) #x80)))) (:zeropad + (db) (if (and (= word 13) (= byte-num 3)) (setf state :write-length)) 0) (:write-length + (db) (multiple-value-bind (hi low) (sha1-length64 (* 8 byte-count)) (setf (aref buffer 14) hi) ;opposite order of MD5 (setf (aref buffer 15) low);opposite order of MD5 (setf state :done) - (return-from buffer-filler t)))))) + (return-from buffer-filler t))))))) ;;Get a word. Note that again the order is the opposite of MD5 (let ((b3 (gb))