Update of /project/crypticl/cvsroot/crypticl/src In directory clnet:/tmp/cvs-serv3801
Modified Files: utilities.lisp sha256.lisp Log Message: Added test code for the SHAVS tests. They run successfully.
--- /project/crypticl/cvsroot/crypticl/src/utilities.lisp 2007/01/07 00:45:33 1.4 +++ /project/crypticl/cvsroot/crypticl/src/utilities.lisp 2007/01/07 15:55:17 1.5 @@ -203,4 +203,13 @@ (do ((i 0 (1+ i))) ((>= i (length v1)) t) (unless (equal (aref v1 i) (aref v2 i)) - (return nil))))) \ No newline at end of file + (return nil))))) + + +(defun string-startswith (s prefix) + "Return true if the string s starts with the given prefix" + (let ((len (length prefix))) + (if (> len (length s)) + nil ; prefix longer than string + (string= s prefix :end1 len)))) + --- /project/crypticl/cvsroot/crypticl/src/sha256.lisp 2007/01/07 00:45:33 1.3 +++ /project/crypticl/cvsroot/crypticl/src/sha256.lisp 2007/01/07 15:55:17 1.4 @@ -6,9 +6,14 @@ ;;;; Distribution: See the accompanying file LICENSE.
-;;; Based on the reference [1] +;;; Based on reference [1] from http://csrc.nist.gov/cryptval/shs.htm +;;; (live 07.01.2007). ;;; -;;; [1] FIPS 180-2 "Secure Hash Standard" +;;; [1] NIST. 2002. Secure Hash Standard. FIPS PUB 180-2, +;;; http://csrc.nist.gov/publications/fips/fips180-2/ +;;; fips180-2withchangenotice.pdf. +;;; [2] Lawrence E. Bassham III. 2004. The Secure Hash Algorithm +;;; Validation System (SHAVS).
(in-package crypticl)
@@ -53,9 +58,8 @@ ;;; words, which are represented as x, y, and z. The result of each function ;;; is a new 32-bit word. ;;; -;;; Note on the notation in the docstrings: -;;; not is a bitwise not operation, also referred to as the complement -;;; operation. +;;; Note on the notation in the docstrings: not is a bitwise not operation, +;;; also referred to as the complement operation. (defun ch-256 (x y z) "(x and y) xor (not x and z)" (logxor (logand x y) @@ -92,9 +96,8 @@ (ash x -10)))
- (defun sha-256-encode (buffer-filler) - "Main non-CLOS function. Encodes 512 bits blocks until done." + "Compute SHA-256 hash." (let ((mb (make-array 16 :element-type '(unsigned-byte 32))) a b c d e f g h) ; the 8 working variables. (initial-sha-256-hash-value a b c d e f g h) @@ -195,8 +198,16 @@ (make-buffer-filler (make-string-reader-function string))))
+(defun sha-256-on-octet-vector (octet-vector) + "Return SHA-256 hash of byte array/octect vector" + (sha-256-encode + (make-buffer-filler + (make-byte-array-reader-function octet-vector)))) +
+;;;; ;;;; tests +;;;; (defun test-sha-256 () "Test vector 1 and 2 are taken from reference FIPS 180-2." (let ((test-list @@ -221,4 +232,78 @@ (make-string 1000000 :initial-element #\a))) "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0") () "sha-256 test for long test vector 1000000.") - (format t "Long messages OK.~%")) \ No newline at end of file + (format t "Long messages OK.~%")) + + +;;; Official test vectors from The Secure Hash Algorithm Validation System +;;; (SHAVS) (reference [2]. +(defun shavs (stream) + (parse-shavs-lines + (loop for line = (read-line stream nil 'eof) + until (eq line 'eof) + collect line)) + (format t "SHAVS tests OK")) + +(defun parse-shavs-lines (lines) + "Parse the SHAVS file format. + +file format: +Len = 0 +Msg = 00 +MD = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + +Len = 8 +Msg = bd +MD = 68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b +" + (let ((state 'read-more) + (count 0) + len + msg + md) + (dolist (line lines) + (cond + ((string-startswith line "Len") + (setf len (parse-integer line :start 6))) + ((string-startswith line "Msg") + (setf msg (subseq line 6))) + ((string-startswith line "MD") + (setf md (subseq line 5) + state 'run-sha)) + (t + (setf state 'read-more))) + + (case state + ;; continue reading + (read-more nil) + ;; we have a new test vector + (run-sha (shavs-256 len msg md) + (incf count) + (setf state 'read-more + len nil + msg nil + md nil)) + )) + + (format t "Tested ~D test vectors~%" count) + )) + + +(defun shavs-256 (len msg md) + (when (= len 0) + (setf msg "")) + (assert (string= (hex (sha-256-on-octet-vector (hexo msg))) + md) + nil (format nil "Failed on msg ~A" msg))) + + +(defun run-shavs (&optional (path "../test/SHA256ShortMsg.txt")) + "Verify SHA-256 against SHAVS test vectors from file. + +NB The long test vectors are in the file ../test/SHA256LongMsg.txt" + (with-open-file (str path) + (shavs str))) + +(defun run-shavs-on-string (string) + (with-input-from-string (str string) + (shavs str))) \ No newline at end of file