Continuing from my SHA1 implementations, I'm now implementing all SHA functions across my three main languages. I've finished with the Common Lisp first, sans the SHA-3 family to be finished later. I chose rather different approaches across these three languages, with the Common Lisp defining a CLOS protocol. The design is still heavily influenced by the Ada and, as with the SHA1, deals in octets.
This program is licensed under the GNU Affero General Public License version three.
As with the SHA1, this library is intended to be used without any use of USE-PACKAGE or IMPORT. The naming scheme makes this pleasant and practical. It suffers from Common Lisp lacking overloading by return value, as Ada features, however. Unlike the SHA1, constants have nicer names and share these with the classes they represent, for dispatching. Follows is an example of SHA256 hashing a vector:
(SHA:STRING (SHA:HASH SHA:256 #(0 1 2 3 4 5 6 7 8 9)))
As with all of my SHA designs, a BLOCKHASH and PAD are provided for cases where the HASH insuffices.
The CLOS protocol defines a STATUS class with UNIT and STATUS slots and from which the rest descend. STATUS objects should respond to BLOCKHASH, BLOCKLENGTH, PAD, and DIGEST messages. The DIGEST value is intended to be used only with the STRING and OCTETS functions and its return type may be changed.
Follows are brief descriptions of all external functionality, with symbols followed by lambda lists:
BLOCKHASH (STATUS BLOCK) STATUS
This is the fundamental hashing function, destructively updating STATUS and not modifying the BLOCK. The block is an octet vector of appropriate length for the particular function determined by STATUS. Don't use this function on the constants; use MAKE-INSTANCE to create a new STATUS for that purpose.
BLOCKLENGTH (STATUS) INTEGER
This function needs merely return that bit-length of an appropriate block for the particular STATUS.
PAD (STATUS LENGTH BLOCK &OPTIONAL SECOND) (VALUES BLOCK ...)
This function pads the BLOCK as appropriate, for the particular STATUS. The LENGTH is a bit-length. If SECOND is provided, it mustn't be EQ to BLOCK, and doing so prevents PAD from allocating its own. Both blocks are modified; the return value is the first block, and the second is returned if needed.
DIGEST (STATUS) VECTOR
The DIGEST is intended to suffice for all SHA. It returns a new vector describing the SHA, one-way.
OCTETS (DIGEST) VECTOR
This converts the return value of DIGEST to an octet vector.
STRING (DIGEST) STRING
This converts the return value of DIGEST to its hexadecimal string representation.
HASH (STATUS SET &KEY) DIGEST
This is the prime function of the library, taking a starting STATUS and the SET to collect octets to hash from. It only dispatches based on the type of SET, internally using BLOCKHASH, PAD and DIGEST. Currently, there are methods for PATHNAMEs, STREAMs, and methods for VECTORs and LISTs will succeed.
Unfortunately, basic testing has shown this library to be far too slow for practical usage. Further functionality and optimizations will be applied later; I anticipate making this library far greater.
This library is still undergoing careful review, so be wary.
Here is the source and the documentation. Here is the license.