Update of /project/crypticl/cvsroot/crypticl/src In directory clnet:/tmp/cvs-serv24210
Modified Files: sha256.lisp sha.lisp load.lisp common.lisp Log Message: Load sha256 correctly. Refactor commom code in sha-1 and sha-256.
--- /project/crypticl/cvsroot/crypticl/src/sha256.lisp 2007/01/16 23:43:12 1.6 +++ /project/crypticl/cvsroot/crypticl/src/sha256.lisp 2007/01/18 21:37:02 1.7 @@ -18,101 +18,6 @@
(in-package crypticl)
-;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; Low-level function API -;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defun sha-256-on-octet-vector (octet-vector) - "Return SHA-256 hash of byte array/octet vector" - (sha-256-encode - (make-buffer-filler - (make-byte-array-reader-function octet-vector)))) - -(defun sha-256-on-string (string) - "Return SHA-256 hash of a string. - -NB! With this function the hash value depends on the encoding of string -and implementation specific details of the Common Lisp distribution you -are using (see make-string-reader-function and its' use of char-code -for more details). For more control, decode the string to a byte array -yourself and use the byte array interface sha-256-on-octet-vector instead. -" - (sha-256-encode - (make-buffer-filler - (make-string-reader-function string)))) - -(defun sha-256-on-octet-stream (stream) - "Return SHA-256 hash of stream." - (sha-256-encode - (make-buffer-filler #'(lambda () (read-byte stream nil))))) - -(defun sha-256-file (path) - "Return SHA-256 hash of a file." - (with-open-file (str path) - (sha-256-on-octet-stream str))) - - -;;;;;;;;;;;;; -;;; -;;; CLOS API -;;; -;;;;;;;;;;;;; -(defun make-SHA-256 () - "Constructor for the SHA-256 class" - (let ((obj (make-instance 'SHA-256 :algorithm "SHA-256"))) - (reset obj) - obj)) - -(defmethod reset ((obj SHA-256)) - (initial-sha-256-hash-value (a obj) (b obj) (c obj) (d obj) - (e obj) (f obj) (g obj) (h obj)) - (setf (octet-count obj) 0 - (leftover-count obj) 0 - (called-hash obj) nil - (fresh obj) t)) - -(defmethod hash ((obj SHA-256) &optional data (start 0) (end (length data))) - "Return SHA-256 hash of all bytes added so far. - -Note that calling hash on an empty object object makes no sense but the spec -seems to be that we run algorithm on the initial state and return a full -256 bits hash even when the message length is 0. - -Calling it a second time without adding data returns the previous value. -" - (when (and (not data) (called-hash obj)) - ;; Return previous hash value when we have one and no data has been - ;; added since last call to hash. - (return-from hash (sha-256-make-octet-vector - (a obj) (b obj) (c obj) (d obj) - (e obj) (f obj) (g obj) (h obj)))) - (when data - (typecase data - (vector (sha-256-add-octet-vector obj data start end)) - (otherwise - (error "Hash on data type ~A not implemented." (type-of data))))) - - (setf (called-hash obj) t) - (sha-256-final obj)) - -(defmethod update ((obj SHA-256) (octet-vector vector) - &optional (start 0) (end (length octet-vector))) - "Add bytes to SHA-256 hash object. - -Will compute the intermediate hash value and not store the input. Useful -for hashing a large file that doesn't fit in memory or a data stream. - -When all bytes have been added you get the hash value by calling the -hash method." - ;; Reset object if we have called hash - (when (called-hash obj) - (reset obj)) - - (sha-256-add-octet-vector obj octet-vector start end) - (setf (fresh obj) nil)) - - ;;;;;;;;;;;;;;;;;;; ;;; ;;; Implementation @@ -215,30 +120,8 @@ h (32-add h hh))))
;; Return hash value as array. - (sha-256-make-octet-vector a b c d e f g h))) - -(defmacro sha-256-make-octet-vector (a b c d e f g h) - "Make byte-vector from 5 32 bits integers. - -Note that SHA 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) - (ldb (byte 8 8) ,num32) - (ldb (byte 8 0) ,num32)))) - `(let ((a ,a) (b ,b) (c ,c) (d ,d) (e ,e) (f ,f) (g ,g) (h ,h)) - (vector ,@(bytes 'a) - ,@(bytes 'b) - ,@(bytes 'c) - ,@(bytes 'd) - ,@(bytes 'e) - ,@(bytes 'f) - ,@(bytes 'g) - ,@(bytes 'h) - )))) - + (int32s-to-octet-vector a b c d e f g h))) + (defun do-sha-256-message-block (a b c d e f g h mb) "Hash one 512 bits sha-256 message block.
@@ -368,7 +251,7 @@ (sha-256-encode-block obj vec))
;; Return hash. - (sha-256-make-octet-vector (a obj) (b obj) (c obj) (d obj) + (int32s-to-octet-vector (a obj) (b obj) (c obj) (d obj) (e obj) (f obj) (g obj) (h obj))))
@@ -430,6 +313,101 @@ (+ start used)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Low-level function API +;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defun sha-256-on-octet-vector (octet-vector) + "Return SHA-256 hash of byte array/octet vector" + (sha-256-encode + (make-buffer-filler + (make-byte-array-reader-function octet-vector)))) + +(defun sha-256-on-string (string) + "Return SHA-256 hash of a string. + +NB! With this function the hash value depends on the encoding of string +and implementation specific details of the Common Lisp distribution you +are using (see make-string-reader-function and its' use of char-code +for more details). For more control, decode the string to a byte array +yourself and use the byte array interface sha-256-on-octet-vector instead. +" + (sha-256-encode + (make-buffer-filler + (make-string-reader-function string)))) + +(defun sha-256-on-octet-stream (stream) + "Return SHA-256 hash of stream." + (sha-256-encode + (make-buffer-filler #'(lambda () (read-byte stream nil))))) + +(defun sha-256-file (path) + "Return SHA-256 hash of a file." + (with-open-file (str path) + (sha-256-on-octet-stream str))) + + +;;;;;;;;;;;;; +;;; +;;; CLOS API +;;; +;;;;;;;;;;;;; +(defun make-SHA-256 () + "Constructor for the SHA-256 class" + (let ((obj (make-instance 'SHA-256 :algorithm "SHA-256"))) + (reset obj) + obj)) + +(defmethod reset ((obj SHA-256)) + (initial-sha-256-hash-value (a obj) (b obj) (c obj) (d obj) + (e obj) (f obj) (g obj) (h obj)) + (setf (octet-count obj) 0 + (leftover-count obj) 0 + (called-hash obj) nil + (fresh obj) t)) + +(defmethod hash ((obj SHA-256) &optional data (start 0) (end (length data))) + "Return SHA-256 hash of all bytes added so far. + +Note that calling hash on an empty object object makes no sense but the spec +seems to be that we run algorithm on the initial state and return a full +256 bits hash even when the message length is 0. + +Calling it a second time without adding data returns the previous value. +" + (when (and (not data) (called-hash obj)) + ;; Return previous hash value when we have one and no data has been + ;; added since last call to hash. + (return-from hash (int32s-to-octet-vector + (a obj) (b obj) (c obj) (d obj) + (e obj) (f obj) (g obj) (h obj)))) + (when data + (typecase data + (vector (sha-256-add-octet-vector obj data start end)) + (otherwise + (error "Hash on data type ~A not implemented." (type-of data))))) + + (setf (called-hash obj) t) + (sha-256-final obj)) + +(defmethod update ((obj SHA-256) (octet-vector vector) + &optional (start 0) (end (length octet-vector))) + "Add bytes to SHA-256 hash object. + +Will compute the intermediate hash value and not store the input. Useful +for hashing a large file that doesn't fit in memory or a data stream. + +When all bytes have been added you get the hash value by calling the +hash method." + ;; Reset object if we have called hash + (when (called-hash obj) + (reset obj)) + + (sha-256-add-octet-vector obj octet-vector start end) + (setf (fresh obj) nil)) + + ;;;;;;;;;;;;;;;;;; ;;;; ;;;; Tests --- /project/crypticl/cvsroot/crypticl/src/sha.lisp 2007/01/16 23:45:21 1.7 +++ /project/crypticl/cvsroot/crypticl/src/sha.lisp 2007/01/18 21:37:02 1.8 @@ -26,25 +26,6 @@ ,d #x10325476 ,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." - (flet ((bytes (num32) - `((ldb (byte 8 24) ,num32) - (ldb (byte 8 16) ,num32) - (ldb (byte 8 8) ,num32) - (ldb (byte 8 0) ,num32)))) - `(let ((a ,a) (b ,b) (c ,c) (d ,d) (e ,e)) - (vector ,@(bytes 'a) - ,@(bytes 'b) - ,@(bytes 'c) - ,@(bytes 'd) - ,@(bytes 'e))))) - - (defun sha1-length64 (message-length-in-bits) "Returns input integer as two 32-bit words, high order bits first." (values (ldb (byte 32 32) message-length-in-bits) @@ -211,7 +192,7 @@ d (32-add d dd) e (32-add e ee)))) ;; Return hash value. - (sha1-make-octet-vector a b c d e))) + (int32s-to-octet-vector a b c d e)))
@@ -325,7 +306,7 @@ (sha1-round obj vec))
;; Reset object and return hash. - (prog1 (sha1-make-octet-vector (a obj) (b obj) (c obj) (d obj) (e obj)) + (prog1 (int32s-to-octet-vector (a obj) (b obj) (c obj) (d obj) (e obj)) (reset obj))))
--- /project/crypticl/cvsroot/crypticl/src/load.lisp 2007/01/17 22:00:52 1.7 +++ /project/crypticl/cvsroot/crypticl/src/load.lisp 2007/01/18 21:37:02 1.8 @@ -25,6 +25,7 @@ "random" "keygenerator" "md5" "aes" "idea" "dsa" "rsa" "diffie-hellman" + "sha256" "keystore" "test"))) (format t "Loading the Crypticl library...") --- /project/crypticl/cvsroot/crypticl/src/common.lisp 2007/01/17 22:00:52 1.7 +++ /project/crypticl/cvsroot/crypticl/src/common.lisp 2007/01/18 21:37:02 1.8 @@ -95,9 +95,25 @@
-;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; ;;; Common functionality for hash functions. - +;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defun int32s-to-octet-vector (&rest int32s) + "Make octet vector (byte array in C terms) from 32 bits integers. + +Note that SHA 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." + (let ((res (make-array (* 4 (length int32s)) + :element-type '(unsigned-byte 8) + :fill-pointer 0))) + (dolist (int32 int32s res) + (vector-push (ldb (byte 8 24) int32) res) + (vector-push (ldb (byte 8 16) int32) res) + (vector-push (ldb (byte 8 8) int32) res) + (vector-push (ldb (byte 8 0) int32) res))))
(defun 32-add (&rest args) "Adds a 32-bit number modulo (expt 2 32)"